29
votes

I'm trying to understand Maven 3's[password encryption feature. I have found that this feature is poorly documented and confusing. For example, the feature documentation and a blog post by the author of the feature contradict each other about several points.

This question is broader than How does maven --encrypt-master-password work and is not covered by Maven encrypt-master-password good practice for choosing password.

Specifically, I am trying to answer the following questions which are not covered by the documentation. I've put what information I have been able to gather so far below each question in italics.

  1. Does the encrypted master password provide security simply by existing in settings-security.xml in a folder that only one user can access (~/.m2)? If so, why bother with encrypting a 'master password' (why not just use some random value)? Isn't the 'master password' really just an entropy input to the cryptographic function? Calling it a password is confusing - I expected Maven to prompt me for this password before de-crypting any encrypted server passwords, but it did not.

My understanding is that yes, this only provides security by existing in an operating-system protected file. I believe Maven allows you to encrypt a master password so that if you loose the settings-security.xml file you can re-generate it. Is this correct?

  1. Do the master password and server passwords use the same encryption process/cipher? The server passwords are based on the master password, so there must be some difference in the algorithm. Where is the source code for this located?

Marcelo Morales' answer on How does maven --encrypt-master-password work links to the plexus-cihper project on GitHub. It isn't clear if that is just the cipher, or the actual Maven plugin that provides the password functionality though.

  1. I have observed that the same master password or server password encrypted multiple times gives different hashes. According to Marcelo Morales' answer on How does maven --encrypt-master-password work, this is because 'a JVM-configuration-specific (usually SHA1PRNG) 64-bit random salt' is added to the password prior to encrypting. Maven decrypts stored passwords when they are used at compile time. Doesn't this mean the salts have to be stored somewhere?

I have no idea.

  1. I have also observed that a regular password encrypted using one encrypted master password will still work if the master password is re-encrypted and stored in the settings-security.xml file, even though the encrypted master password ciphertext is now different. Can someone explain how this works?

I have no idea. This seems to me like Maven is doing something fishy or storing cleartext somewhere.

  1. My understanding is that the encrypted passwords can only be used with <server /> tags in the settings.xml file. is this true? Where can servers defined in settings.xml be used?

My understanding is that <server /> definitions can be used in <repositories /> and <distributionManagement />, but not <scm />. Can someone verify this?

  1. For such a critical feature (build system security) it seems to me that there is a lot of confusion and poor documentation. Can someone point out how the documentation on the Maven 3 website works? Is there a wiki link somewhere that would allow me to try and improve the documentation at all?

I have no idea

Sorry for the wall of text, and thanks for any answers.

3
You can store the settings-security.xml on an external storage device like usb. If you like to improve the docs or suggest how it could be improved or better explained please create an appropriate JIRA: issues.apache.org/jira/browse/MNGSITEkhmarbaise
wolf-71.blogspot.ch/2010/04/dont-hide-key-under-rock.html is a blogpost which stresses the point you have to keep your ~/.m2/settings-security.xml with your master password on an external device. Its just so easy with his 2 test cases and $M2_HOME/lib/plexus-cipher-1.7.jar to decrypt your master password and with that your server password. So the whole master password maven feature ist just obfuscating password.Uwe Günther

3 Answers

21
votes

My answer is based on reading the Maven source code and doing a little research.

  1. Does the encrypted master password provide security simply by existing in settings-security.xml in a folder that only one user can access (~/.m2)? If so, why bother with encrypting a 'master password' (why not just use some random value)? Isn't the 'master password' really just an entropy input to the cryptographic function? Calling it a password is confusing - I expected Maven to prompt me for this password before de-crypting any encrypted server passwords, but it did not.

The master password is an input into the cryptographic function for encrypting/decrypting the server passwords. If someone has your individual encrypted server passwords, they won't be able to decrypt them unless they also have your master password. This means you can freely share your maven settings.xml file with others, without them being able to decrypt your server passwords. This is also why the master password is kept in a separate file.

This rationale is somewhat explained in encryption guide

  1. Do the master password and server passwords use the same encryption process/cipher? The server passwords are based on the master password, so there must be some difference in the algorithm. Where is the source code for this located?

From what I can tell, the master password is encrypted using the same cipher as the server passwords. When decrypting the server passwords, the master password (unencrypted form) is an input; when decrypting the master password, the magic string '"settings.security"' is used as the additional input.

You can see the source code PBECipher and MavenCli.java.

  1. I have observed that the same master password or server password encrypted multiple times gives different hashes. According to Marcelo Morales' answer on How does maven --encrypt-master-password work, this is because 'a JVM-configuration-specific (usually SHA1PRNG) 64-bit random salt' is added to the password prior to encrypting. Maven decrypts stored passwords when they are used at compile time. Doesn't this mean the salts have to be stored somewhere?

A traditional approach to handling salts is that the random salt is stored with the encrypted text, alongside it. See the Wikipedia article.

Based on the source code linked above, the salt appears to be stored as the first 8 bytes of the Base64 decoded bytes, right before the encrypted password.

  1. I have also observed that a regular password encrypted using one encrypted master password will still work if the master password is re-encrypted and stored in the settings-security.xml file, even though the encrypted master password ciphertext is now different. Can someone explain how this works?

This is because the decrypted form of the master password is used, not the encrypted "ciphertext". Thus re-encrypting it doesn't affect the server password encryption/decryption.

I don't know the answer to your last two (5 and 6) questions.

4
votes

I need to know this for bnd(tools) so I can share some deeper analysis.

The 'encrypted' passwords have a syntax of:

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>

The cipher used is AES/CBC/PKCS5Padding. The secret key and initialisation vector is calculated as follows:

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

For the master password X is "security.settings". Since this is a well known constant the master password is not encrypted but only obscured. For the server passwords X is the decoded master password.

Why the resulting packet is padded seems a waste of bytes since the packet format makes it trivial to strip and they are never part of the encryption/decryption. They just add a few random characters to the base64 string.

The only way this is useful is using the relocation facility. For example, if you mount the settings-security.xml on a private mount on the build server. You can then you can freely share the settings.xml file in public repos. However, this is also a sucky solution since you need to mount it the same mount point for all your users and CI build servers.

Be aware that any plugin can decode all your server passwords so never use real passwords for the servers. Nexus can create proxy passwords.

2
votes

Here is example code which shows how to decrypt the maven master password from

~/.m2/security-settings.xml

and also the server passwords from

~/.m2/settings.xml

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

There is also an example project on GitHub:

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