Solución:
Mi respuesta se basa en leer el código fuente de Maven e investigar un poco.
- ¿La contraseña maestra cifrada proporciona seguridad simplemente por existir en
settings-security.xml
en una carpeta a la que solo puede acceder un usuario (~/.m2
)? Si es así, ¿por qué molestarse en encriptar una ‘contraseña maestra’ (por qué no usar simplemente algún valor aleatorio)? ¿No es la ‘contraseña maestra’ realmente solo una entrada de entropía para la función criptográfica? Llamarla contraseña es confuso: esperaba que Maven me solicitara esta contraseña antes de descifrar cualquier contraseña de servidor cifrada, pero no fue así.
La contraseña maestra es una entrada en la función criptográfica para cifrar / descifrar las contraseñas del servidor. Si alguien tiene sus contraseñas de servidor cifradas individuales, no podrá descifrarlas a menos que también tenga su contraseña maestra. Esto significa que puede compartir libremente su archivo maven settings.xml con otros, sin que ellos puedan descifrar las contraseñas de su servidor. Esta es también la razón por la que la contraseña maestra se guarda en un archivo separado.
Este fundamento se explica de alguna manera en la guía de cifrado.
- ¿La contraseña maestra y las contraseñas del servidor utilizan el mismo proceso de cifrado / cifrado? Las contraseñas del servidor se basan en la contraseña maestra, por lo que debe haber alguna diferencia en el algoritmo. ¿Dónde se encuentra el código fuente para esto?
Por lo que puedo decir, la contraseña maestra está cifrada con el mismo cifrado que las contraseñas del servidor. Al descifrar las contraseñas del servidor, la contraseña maestra (forma no cifrada) es una entrada; al descifrar la contraseña maestra, la cadena mágica ‘”settings.security”‘ se utiliza como entrada adicional.
Puede ver el código fuente PBECipher y MavenCli.java.
- He observado que la misma contraseña maestra o contraseña de servidor cifrada varias veces da diferentes valores hash. De acuerdo con la respuesta de Marcelo Morales sobre Cómo funciona maven –encrypt-master-password, esto se debe a que se agrega a la contraseña ‘una sal aleatoria de 64 bits específica de la configuración de JVM (generalmente SHA1PRNG)’ a la contraseña antes de la encriptación. Maven descifra las contraseñas almacenadas cuando se utilizan en el momento de la compilación. ¿No significa esto que las sales deben almacenarse en algún lugar?
Un enfoque tradicional para el manejo de sales es que la sal aleatoria se almacena junto con el texto cifrado. Consulte el artículo de Wikipedia.
Según el código fuente vinculado anteriormente, la sal parece estar almacenada como los primeros 8 bytes de los bytes decodificados de Base64, justo antes de la contraseña cifrada.
- También he observado que una contraseña normal cifrada con una contraseña maestra cifrada seguirá funcionando si la contraseña maestra se vuelve a cifrar y se almacena en el
settings-security.xml
expediente, aunque el texto cifrado de la contraseña maestra ahora es diferente. ¿Alguien puede explicar cómo funciona esto?
Esto se debe a que descifrado se utiliza la forma de la contraseña maestra, no el “texto cifrado”. Por lo tanto, volver a cifrarlo no afecta el cifrado / descifrado de la contraseña del servidor.
No sé la respuesta a sus dos últimas (5 y 6) preguntas.
Necesito saber esto para bnd (herramientas) para poder compartir un análisis más profundo.
Las contraseñas ‘encriptadas’ tienen una sintaxis de:
output ::= '{' base64(packet) '}'
packet ::= salt[8] padlen[1] encrypted[?] padding[padlen]
salt ::= <random>
padlen ::= <length of padding >
padding ::= <random to make packet length a multiple of 16>
El cifrado utilizado es AES/CBC/PKCS5Padding
. La clave secreta y el vector de inicialización se calculan de la siguiente manera:
sha = sha256( X + salt[8] )
key = sha[0..16]
iv = sha[16..32]
Para la contraseña maestra, X es “security.settings”. Dado que esta es una constante bien conocida la contraseña maestra no está encriptada, solo oculta. Para las contraseñas de servidor, X es la contraseña maestra decodificada.
El motivo por el que se rellena el paquete resultante parece una pérdida de bytes, ya que el formato del paquete hace que sea trivial eliminarlo y nunca forman parte del cifrado / descifrado. Simplemente agregan algunos caracteres aleatorios a la cadena base64.
La única forma en que esto es útil es utilizando la función de reubicación. Por ejemplo, si monta settings-security.xml en un montaje privado en el servidor de compilación. A continuación, puede compartir libremente el settings.xml
archivo en repositorios públicos. Sin embargo, esta también es una solución desagradable, ya que necesita montarlo en el mismo punto de montaje para todos sus usuarios y servidores de compilación de CI.
Tenga en cuenta que cualquier complemento puede decodificar todas las contraseñas de su servidor, por lo que nunca utilice contraseñas reales para los servidores. Nexus puede crear contraseñas de proxy.
Aquí hay un código de ejemplo que muestra cómo descifrar la contraseña maestra de maven de
~/.m2/security-settings.xml
y también las contraseñas del servidor de
~/.m2/settings.xml
Fuente de MavenPasswordDecryptor.java
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
public class MavenPasswordDecryptor {
public static void main(String[] args) throws Exception {
if (args.length < 1 || args.length > 2 ) {
System.out.println("Usage: java -jar maven-password-decryptor.jar <encrypted-password>");
System.out.println("Usage: java -jar maven-password-decryptor.jar <encrypted-password> <master-password>");
return;
}
DefaultPlexusCipher cipher = new DefaultPlexusCipher();
String encryptedPassword = args[0];
String passPhrase = (args.length == 2 && args[1] != null && !args[1].isEmpty()) ? args[1] : "settings.security";
String result = cipher.decryptDecorated(encryptedPassword, passPhrase);
System.out.println(result);
}
}
También hay un proyecto de ejemplo en GitHub:
https://github.com/uweguenther/maven-password-decryptor