Cuatrocientas sesenta y tres líneas para un cero
Quien se da de alta en la Plataforma de Contratación del Sector Público elige una contraseña, y a su lado hay un contador que empieza en 0. La página está programada para subirlo hasta 100 mientras se escribe, y pide llegar a 60. Ese número lo calcula en el navegador un fichero de 463 líneas. El formulario guarda aparte, escondido, otro número para mandar al servidor, y mientras se teclea nadie lo toca: se queda en el cero con que llega.
- Dominio
- contrataciondelestado.es
- Guardado
- 05 SEP 2026
- Citas
- 7 en 2 ficheros guardados
- Lectura
- unos 4 min

El formulario es de los completos: usuario, correo, contraseña, repetir contraseña, un captcha y un aviso de seguridad que hay que aceptar. A la derecha de la contraseña hay un contador rotulado Complejidad de la contraseña, que empieza en cero. Debajo, las reglas: de 8 a 30 caracteres, ni eñes ni acentos, y un grado de complejidad de al menos 60. Y dos botones, Mostrar contraseña y Generar contraseña.

Ese contador lo calcula un fichero llamado calculadorFortalezaContrasenya.js, de 16.591 bytes y 463 líneas de JavaScript, el lenguaje de los programas que corren en el navegador. Y se ejecuta entero en cada tecla: los dos campos, el de la contraseña y el de repetirla, lo llaman con cada pulsación, y la cuenta se rehace con la contraseña completa cada vez. Doce caracteres son doce vueltas al fichero, con sus bucles y sus expresiones regulares, los patrones con que se busca una forma dentro de un texto. No se nota, pero está pasando.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 16,6 kB
- sha256
- 21f98d34fe83…
| 110 | for (var s=0; s < this.length; s++) { |
| 111 | newstring = this.charAt(s) + newstring; |
| 112 | } |
| 113 | |
| 114 | return newstring; |
| 115 | }; |
| 116 | |
| 117 | / |
| 118 | Funcion principal que comprueba la fortaleza de una contraseña. |
| 119 | ******************************************************************************************************************/ |
| 120 | function comprobar |
| 121 | |
| 122 | var oScorebar = $("scorebar"); |
| 123 | var oScore = $("score"); |
| 124 | |
| 125 | var fortaleza = 0; |
| 126 | |
| 127 | var longitudPassword = 0; |
| 128 | |
| 129 | var numCaracteresMayus = 0; |
| 130 | var numCaracteresMinus = 0; |
| 131 | var numNumeros = 0; |
Lo que hace dentro tiene su mérito. Cuenta mayúsculas, minúsculas, números y símbolos. Detecta caracteres repetidos y penaliza. Detecta secuencias, tres letras, tres números o tres símbolos seguidos, y penaliza otra vez. Comprueba que la contraseña no sea un NIF, con un patrón de siete o más cifras y una letra mayúscula. Comprueba que no contenga el nombre de usuario. Suma, resta, y al final deja el resultado entre 0 y 100.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 16,6 kB
- sha256
- 21f98d34fe83…
| 1 | / |
| 2 | Funcion para corregir que el algoritmo para que la calidad de contraseñas compuestas por una serie de números |
| 3 | y una letra mayúscula (p.e. un NIF) no supere el umbral (en contra de las condiciones de calidad). |
| 4 | ******************************************************************************************************************/ |
| 5 | function comprobarSiNIF(password){ |
| 6 | var esNIF=false; |
| 7 | |
| 8 | var expresion_regular_nif = /^\d{7,}[A-Z]$/; |
| 9 | |
| 10 | if (expresion_ |
| 11 | esNIF=true; |
| 12 | } |
| 13 | |
| 14 | return esNIF; |
| 15 | } |
Por el camino se fabrica una herramienta que el lenguaje ya traía: una función para dar la vuelta a un texto, escrita a mano, carácter a carácter, y añadida a todos los textos del programa. JavaScript sabe hacerlo en una línea. Aquí ocupa nueve, y se usa tres veces, para buscar las secuencias también del revés. Nada de eso es un fallo: un contador en el navegador es lo que hay que hacer, porque su trabajo es avisar a quien teclea, ahí mismo y sin esperas. Lo curioso está en la página que lo carga.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 16,6 kB
- sha256
- 21f98d34fe83…
| 97 | if (caracter. |
| 98 | res = true; |
| 99 | } |
| 100 | |
| 101 | return res; |
| 102 | } |
| 103 | |
| 104 | / |
| 105 | Funcion que devuelve una cadena al revés. |
| 106 | ******************************************************************************************************************/ |
| 107 | String.prototype.strReverse = function() { |
| 108 | var newstring = ""; |
| 109 | |
| 110 | for (var s=0; s < this.length; s++) { |
| 111 | newstring = this.charAt(s) + newstring; |
| 112 | } |
| 113 | |
| 114 | return newstring; |
| 115 | }; |
| 116 | |
| 117 | / |
| 118 | Funcion principal que comprueba la fortaleza de una contraseña. |
Dentro del formulario hay un campo escondido, de los que no se ven en pantalla y viajan igual cuando uno pulsa el botón de enviar. Se llama idFuerzaContrasenyaAutoRegistro, algo así como fuerza de la contraseña del alta, y llega con el valor 0. O sea que, además de enseñarle el número a quien se registra, la página tiene preparado un sitio para mandárselo al servidor, el ordenador de la Plataforma que recibe el alta.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 77,3 kB
- sha256
- 2b4d3a605c92…
| 923 | <div class="input-form col-xs-12 col-sm-12 col-md-12"> |
| 924 | <label for=" |
| 925 | </div> |
| 926 | </div> |
| 927 | <!-- BOTONES GENERAR CONTRASEÑA Y MOSTRAR CONTRASEÑA --> |
| 928 | <div class="row no-gutters"> |
| 929 | <div class="input-form col-xs-12 col-sm-12 col-md-12"> |
| 930 | <!-- Enlaces para mostrar en claro la contraseña --> |
| 931 | <div class="btn-group right"> |
| 932 | <script type="text/javascript" src="/ |
| 933 | <!-- Enlace para generar nueva contraseña --> |
| 934 | …value="0" /> |
| 935 | </div> |
| 936 | </div> |
| 937 | <div class="row no-gutters"> |
| 938 | <div class="input-form col-xs-12 col-sm-12 col-md-12"> |
| 939 | <span id=" |
| 940 | </div> |
| 941 | </div> |
| 942 | </div> |
| 943 | </div> |
| 944 | <div class="input-form col-xs-12 col-sm-6 col-md-6" style="display:flex; justify-content:center"> |
| 945 | <!-- Texto validez cotraseña --> |
Quien lo rellena es una función, escribirFortaleza, que pinta la barra, escribe el número en pantalla y, si el campo escondido existe, le mete el valor. Es la única línea de la página que escribe ese campo. Y a esa función solo la llama un sitio: la respuesta de una petición al servidor que devuelve la palabra FORTALEZA y un número. El número que viaja lo calcula el servidor, y el navegador lo copia.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 77,3 kB
- sha256
- 2b4d3a605c92…
| 801 | } |
| 802 | ); |
| 803 | } |
| 804 | |
| 805 | function escribir |
| 806 | var oScorebar = document. |
| 807 | var oScore = document. |
| 808 | oScorebar. |
| 809 | oScore.innerHTML = fortaleza; |
| 810 | |
| 811 | if(document. |
| 812 | document. |
| 813 | } |
| 814 | } |
| 815 | |
| 816 | function obtenerValorUsuario(){ |
| 817 | if(document. |
| 818 | nombreUsuario = document. |
| 819 | } |
| 820 | } |
| 821 | |
| 822 | |
| 823 | function setear |
escribirFortaleza, y a escribirFortaleza solo la llama la respuesta del servidor.Falta saber cuándo se le pregunta al servidor. La petición vive en una función llamada calculoFortalezaAjax, y la página la llama una sola vez, dentro de un if, una condición: solo si la variable copiarContrasenyas es verdadera. Dos líneas más arriba, en el mismo bloque, la página trae escrito su valor: false. Así que, en la página tal como se abre, esa pregunta no se hace, y teclear la contraseña no la dispara.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 77,3 kB
- sha256
- 2b4d3a605c92…
| 1120 | hX_ |
| 1121 | hX_ |
| 1122 | hX_6.onPageLoad();</script> |
| 1123 | |
| 1124 | |
| 1125 | |
| 1126 | <!-- <div id="capa_oculta"></div> --> |
| 1127 | |
| 1128 | |
| 1129 | |
| 1130 | <script type="text/javascript"> |
| 1131 | var copiarContrasenyas = false; |
| 1132 | |
| 1133 | if(copiarContrasenyas){ |
| 1134 | if(document. |
| 1135 | calculo |
| 1136 | } |
| 1137 | } |
| 1138 | |
| 1139 | |
| 1140 | function mostrarEnlace(){ |
| 1141 | if(document. |
| 1142 | document. |
Lo que no sabemos es si esa variable vale siempre false. Está escrita en la página que manda el servidor, y en todas las copias que tenemos, que son de la página recién abierta, vale false. El botón Generar contraseña envía el formulario al servidor, que devuelve la página otra vez. Qué trae entonces esa variable, cuyo nombre habla de copiar contraseñas, no lo hemos visto, porque el museo no envía formularios de nadie.
Lo escrito es esto. Mientras alguien teclea su contraseña en la página recién abierta, el contador de la pantalla sube y baja con las 463 líneas del navegador, y el campo escondido no se entera: sigue en el cero con que llegó. La cuenta que la página tenía prevista para el servidor tiene su dirección escrita ahí arriba, la de un servlet, un programa del servidor que contesta peticiones, llamado CalculoFortalezaPasswordAjaxServlet. Esa pregunta no se hace.
- Copia
- archivo
- Guardado
- 5 sep 2026
- Peso
- 77,3 kB
- sha256
- 2b4d3a605c92…
| 752 | <script type="text/javascript" src="/ |
| 753 | <script type="text/javascript" src="/ |
| 754 | |
| 755 | <script type="text/javascript"> |
| 756 | |
| 757 | var nombreUsuario = ""; |
| 758 | var minLongPass = 8; |
| 759 | var maxLongPass = 30; |
| 760 | var minFortPass = 60; |
| 761 | var caracEspec = '._ |
| 762 | |
| 763 | var urlPeticionAjax = "/ |
| 764 | |
| 765 | function beforeSubmit(){ |
| 766 | |
| 767 | |
| 768 | var linkAcciones = document. |
| 769 | if(linkAcciones!=null){ |
| 770 | linkAcciones. |
| 771 | } |
Qué hace el servidor con ese cero cuando le llega el alta no lo sabemos, y no vamos a averiguarlo: habría que enviar el formulario. Puede que lo ignore y haga su propia comprobación. Lo que se puede afirmar es lo que está en la página: el número que prepara para mandar no cambia al teclear, y lo que calculan las 463 líneas a cada tecla se queda en la pantalla.
Y sigue igual. El fichero que pedimos el 15 y el 26 de septiembre de 2026 tiene la misma huella y los mismos 16.591 bytes que el que guardamos el 4. La página conserva la variable en false, el campo escondido con su cero y las cuatro llamadas al calculador, dos por campo. La copia del 4 se sirvió en inglés y la del 26, en español: las mismas líneas, palabra por palabra.
La página calcula un número a cada tecla y lo enseña. El que tiene preparado para mandar, mientras se teclea, es el cero con el que llegó.
- En la página de alta de contrataciondelestado.es, guardada el 4 de septiembre de 2026, los dos campos de contraseña llaman en cada pulsación a
comprobarFortalezaPassword, una función del ficherocalculadorFortalezaContrasenya.js, de 463 líneas y 16.591 bytes, que calcula un número de 0 a 100 y lo escribe en pantalla. - El formulario incluye un campo oculto llamado
idFuerzaContrasenyaAutoRegistrocon valor 0. - La única línea de la página que asigna ese campo está dentro de la función
escribirFortaleza, a la que solo llama la respuesta decalculoFortalezaAjax; ycalculoFortalezaAjaxse invoca una sola vez, dentro de un if cuya condición es la variablecopiarContrasenyas, declarada dos líneas antes con valor false en la página tal como se sirve al abrirla. - En el calculador, la función que da la vuelta a un texto ocupa nueve líneas y se usa tres veces, y el patrón del NIF es de siete o más cifras y una letra mayúscula.
- El 15 de septiembre de 2026, pedida en español y en inglés, y el 26, pedida en español, la página conserva las mismas líneas y el fichero tiene el mismo sha256.
- No decimos qué hace el servidor con ese cero cuando recibe el alta: no lo hemos comprobado y no vamos a hacerlo, porque eso exigiría enviar un formulario, y el museo solo lee.
- No decimos que
copiarContrasenyasvalga siempre false: vale false en la página recién abierta, y no sabemos qué vale cuando el servidor la devuelve después de Generar contraseña. - No decimos que una contraseña débil se acepte, ni que una fuerte se rechace.
- No decimos que el calculador esté mal hecho; hace lo que dice.
- Y no decimos nada de la dirección del servlet más allá de que está escrita en la página.
De dónde sale cada cita
Cada trozo de código de esta ficha está en un fichero guardado tal como lo entregó el servidor, con su huella (sha256) y su hora. Las citas entre «» se comprueban por programa contra ese fichero antes de publicar.
- https://contrataciondelestado.es/wps/PA_PortletsPlace/js/fuerzaContrasenya/calculadorFortalezaContrasenya.js5 de septiembre de 2026, 00:54archivosha256 21f98d34fe83cb0f61a8b2ac3b7c28632a61ad1d764fcb2d4afc2621912ad111
- https://contrataciondelestado.es/wps/portal/registrarse5 de septiembre de 2026, 00:54archivosha256 2b4d3a605c927776f42617ad3c0682374ed7ac1612bef7dee24842a1ece3305b