web-dev-qa-db-fra.com

Comment fonctionne le cryptage de mot de passe Maven 3?

J'essaie de comprendre la fonctionnalité de cryptage de mot de passe de Maven 3. J'ai trouvé que cette fonctionnalité est mal documentée et déroutante. Par exemple, les articles feature et a d'un blog de l'auteur de l'article se contredisent sur plusieurs points.

Cette question est plus large que Comment maven --encrypt-master-password fonctionne et n’est pas couverte par Maven encrypt-master-password est une bonne pratique pour choisir un mot de passe .

Plus précisément, j'essaie de répondre aux questions suivantes qui ne sont pas couvertes par la documentation. J'ai mis en italique les informations que j'ai pu recueillir jusqu'à présent sous chaque question.

  1. Le mot de passe principal crypté assure-t-il la sécurité simplement en existant dans settings-security.xml dans un dossier auquel seul un utilisateur peut accéder (~/.m2)? Si oui, pourquoi se préoccuper de chiffrer un «mot de passe principal» (pourquoi ne pas simplement utiliser une valeur aléatoire)? Le «mot de passe principal» n'est-il pas vraiment une simple entrée d'entropie dans la fonction cryptographique? Appeler un mot de passe est déroutant - je m'attendais à ce que Maven me demande ce mot de passe avant de déchiffrer les mots de passe chiffrés du serveur, mais cela n'a pas été le cas.

D'après ce que je comprends, oui, cela ne garantit la sécurité que si vous existez dans un fichier protégé par le système d'exploitation. Je pense que Maven vous permet de chiffrer un mot de passe principal de sorte que si vous perdez le fichier settings-security.xml, vous pouvez le générer à nouveau. correct?

  1. Le mot de passe principal et les mots de passe du serveur utilisent-ils le même processus/chiffrement? Les mots de passe du serveur sont basés sur le mot de passe principal. L'algorithme doit donc présenter une différence. Où se trouve le code source pour cela?

La réponse de Marcelo Morales sur Comment maven --encrypt-master-password fonctionne renvoie au projet plexus-cihper sur GitHub . Il n’est pas clair si c’est un chiffrement, ou le plugin Maven qui fournit la fonctionnalité de mot de passe cependant.

  1. J'ai constaté que le même mot de passe principal ou le même mot de passe du serveur chiffré à plusieurs reprises donne des résultats différents. D'après la réponse de Marcelo Morales sur Comment fonctionne maven --encrypt-master-password , cela est dû au fait qu'un 'sel aléatoire 64 bits spécifique à la configuration de la machine virtuelle Java (généralement SHA1PRNG)' est ajouté au mot de passe avant cryptage. Maven décrypte les mots de passe stockés lorsqu'ils sont utilisés au moment de la compilation. Cela ne signifie-t-il pas que les sels doivent être stockés quelque part?

Je n'ai aucune idée.

  1. J'ai également observé qu'un mot de passe normal crypté à l'aide d'un mot de passe principal crypté fonctionnera toujours si le mot de passe principal est rechiffré et stocké dans le fichier settings-security.xml, même si le mot de passe crypté du mot de passe principal crypté est maintenant différent . Quelqu'un peut-il expliquer comment cela fonctionne?

Je n'en ai aucune idée. Il me semble que Maven fait quelque chose de louche ou stocke du texte clair quelque part.

  1. Si j'ai bien compris, les mots de passe cryptés ne peuvent être utilisés qu'avec les balises <server /> du fichier settings.xml. Est-ce vrai? Où les serveurs définis dans settings.xml peuvent-ils être utilisés?

D'après ce que j'ai compris, les définitions de <server /> peuvent être utilisées dans <repositories /> et <distributionManagement />, mais pas <scm />. Quelqu'un peut-il le vérifier?

  1. Pour une fonctionnalité aussi critique (sécurité du système de compilation), il me semble qu’il ya beaucoup de confusion et une documentation médiocre. Quelqu'un peut-il indiquer comment fonctionne la documentation sur le site Web Maven 3? Existe-t-il un lien wiki quelque part qui me permettrait d'essayer d'améliorer la documentation?

Je n'ai aucune idée

Désolé pour le mur de texte et merci pour toutes les réponses.

19
aaronsnoswell

Ma réponse est basée sur la lecture du code source Maven et sur un peu de recherche.

  1. Le mot de passe principal crypté assure-t-il la sécurité simplement en existant dans settings-security.xml dans un dossier auquel seul un utilisateur peut accéder (~/.m2)? Si oui, pourquoi se préoccuper de chiffrer un «mot de passe principal» (pourquoi ne pas simplement utiliser une valeur aléatoire)? Le «mot de passe principal» n'est-il pas vraiment une simple entrée d'entropie dans la fonction cryptographique? Appeler un mot de passe est déroutant - je m'attendais à ce que Maven me demande ce mot de passe avant de déchiffrer les mots de passe chiffrés du serveur, mais cela n'a pas été le cas.

Le mot de passe principal est une entrée dans la fonction cryptographique pour chiffrer/déchiffrer les mots de passe du serveur. Si quelqu'un a vos mots de passe de serveur cryptés, ils ne pourront pas les décrypter à moins de posséder également votre mot de passe principal. Cela signifie que vous pouvez partager librement votre fichier maven settings.xml avec d'autres personnes, sans que celles-ci ne puissent déchiffrer les mots de passe de votre serveur. C'est aussi pourquoi le mot de passe principal est conservé dans un fichier séparé. 

Cette raison est un peu expliquée dans guide de chiffrement

  1. Le mot de passe principal et les mots de passe du serveur utilisent-ils le même processus/chiffrement? Les mots de passe du serveur sont basés sur le mot de passe principal. L'algorithme doit donc présenter une différence. Où se trouve le code source pour cela?

D'après ce que je peux dire, le mot de passe principal est crypté à l'aide du même chiffrement que les mots de passe du serveur. Lors du déchiffrement des mots de passe du serveur, le mot de passe principal (forme cryptée) est une entrée; lors du déchiffrement du mot de passe principal, la chaîne magique "" settings.security "" est utilisée comme entrée supplémentaire.

Vous pouvez voir le code source PBECipher et MavenCli.Java .

  1. J'ai constaté que le même mot de passe principal ou le même mot de passe du serveur chiffré à plusieurs reprises donne des résultats différents. Selon la réponse de Marcelo Morales sur Comment fonctionne maven --encrypt-master-password , cela est dû au fait qu'un "sel aléatoire 64 bits spécifique à la configuration de la machine virtuelle Java (généralement SHA1PRNG)" est ajouté au mot de passe avant cryptage. Maven décrypte les mots de passe stockés lorsqu'ils sont utilisés au moment de la compilation. Cela ne signifie-t-il pas que les sels doivent être stockés quelque part?

Une approche traditionnelle de la manipulation des sels consiste à stocker le sel aléatoire en même temps que le texte crypté. Voir le article Wikipedia .

Sur la base du code source lié ci-dessus, le sel semble être stocké sous les 8 premiers octets des octets décodés en Base64, juste avant le mot de passe crypté.

  1. J'ai également observé qu'un mot de passe normal crypté à l'aide d'un mot de passe principal crypté fonctionnera toujours si le mot de passe principal est rechiffré et stocké dans le fichier settings-security.xml, même si le mot de passe crypté du mot de passe principal crypté est maintenant différent . Quelqu'un peut-il expliquer comment cela fonctionne?

En effet, le formulaire décrypté du mot de passe principal est utilisé, et non le "texte chiffré" crypté. Ainsi, le rechiffrement n'affecte pas le chiffrement/déchiffrement du mot de passe du serveur.

Je ne connais pas la réponse à vos deux dernières questions (5 et 6).

10
GreenGiant

J'ai besoin de le savoir pour bnd (outils) afin de pouvoir partager une analyse plus approfondie.

Les mots de passe 'cryptés' ont une syntaxe 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>

Le chiffre utilisé est AES/CBC/PKCS5Padding. La clé secrète et le vecteur d’initialisation sont calculés comme suit:

sha = sha256( X + salt[8] )
key = sha[0..16]
iv  = sha[16..32]

Pour le mot de passe principal, X est "security.settings". Comme il s'agit d'une constante bien connue, le mot de passe principal n'est pas crypté, mais seulement masqué. Pour les mots de passe du serveur, X est le mot de passe principal décodé. 

Pourquoi le paquet résultant est rempli semble un gaspillage d'octets puisque le format de paquet rend trivial le strip-tease et qu'ils ne font jamais partie du cryptage/décryptage. Ils ajoutent juste quelques caractères aléatoires à la chaîne base64.

La seule façon dont cela est utile est d'utiliser la fonction de relocalisation. Par exemple, si vous montez le fichier settings-security.xml sur un montage privé sur le serveur de génération. Vous pouvez ensuite partager librement le fichier settings.xml dans des dépôts publics. Cependant, il s’agit également d’une solution peu astucieuse, car vous devez monter le même point de montage pour tous vos utilisateurs et serveurs de build CI.

Sachez que n'importe quel plugin peut décoder tous les mots de passe de votre serveur, aussi ne jamais utiliser de vrais mots de passe pour les serveurs. Nexus peut créer des mots de passe proxy.

2
Peter Kriens

Voici un exemple de code montrant comment décrypter le mot de passe maven master de 

~/.m2/security-settings.xml 

et aussi les mots de passe du serveur de 

~/.m2/settings.xml

Source 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);
    }
}

Il y a aussi un exemple de projet sur GitHub:

https://github.com/uweguenther/maven-password-decryptor

1
Uwe Günther