Support for masked passwords in client XML config

In  elytron

Overview

The Elytron client should support masked passwords, as it is supported in PicketBox. The masked password will have the following attributes:

algorithm

The algorithm that was used to encrypt the password. If this attribute is not specified, the default value is "masked-MD5-DES".

key-material

The initial key material that was used to encrypt the password. If this attribute is not specified, the default value is "somearbitrarycrazystringthatdoesnotmatter".

iteration-count

The iteration count that was used to encrypt the password. This attribute is required.

salt

The salt that was used to encrypt the password. This attribute is required.

masked-password

The base64 encrypted password (without the "MASK-" prefix). This attribute is required.

initialization-vector

The initialization vector that was used to encrypt the password. This attribute is optional.

It should be possible to use masked passwords in place of any clear password written in the Elytron Client XML configuration. For example, instead of:

<credentials>
    <clear-password password="password"/>
</credentials>

The following would also be possible to use:

<credentials>
    <masked-password iteration-count="12" salt="12345678" masked-password="j37uUs8kG9t2QSWjoxxtDg=="/>
</credentials>

It should also be possible to specify a masked password to be used for authentication programmatically:

 AuthenticationConfiguration maskedConfig =
                AuthenticationConfiguration.empty()
                        .setSaslMechanismSelector(SaslMechanismSelector.NONE.addMechanism(PLAIN))
                        .useName(USERNAME)
                        .usePassword("YFBlotObdCo=", null, null, "100", "12345678", null); //attributes of a masked password

Issue Metadata

Issue

Dev Contacts

QE Contacts

Testing By

[x] Engineering

[ ] QE

Affected Projects or Components

  • WildFly Elytron

Other Interested Projects

Requirements

Hard Requirements

  • Everywhere in the Elytron client configuration where a clear password can be used, it should be possible to use a masked password instead:

    • credential in authentication-configuration

    • key-store password

    • key-store reference (like in key-store-ssl-certificate)

    • resource-owner-credentials (in oauth2-bearer-token)

    • client-credentials (in oauth2-bearer-token)

  • It should be possible to use passwords generated in PicketBox-format into Elytron

  • It should be possible to represent the password in modular crypt format

  • This will require not using the initialization vectors (IV) randomly generated by the javax.crypto.Cipher as that makes decryption impossible

  • This will also deprecate the PKDBF2 algorithms for masked passwords as these algorithms cannot be used to get a Cipher instance.

  • It should be possible to programmatically specify a masked password to be used for authentication.

Implementation Details

When testing the original implementation for this feature, it was discovered that no SASL mechanisms support masked passwords from the client side (similar to: https://issues.redhat.com/browse/ELY-1252).

In order to support masked passwords as credentials for configuration on the client side, it is proposed that the masked password be converted to a clear password. This would be done in ElytronXmlParser#parseMaskedPassword. After parsing the attributes of the masked password, the clear text password can be obtained and a ClearPassword can be generated as follows:

...
final MaskedPasswordSpec spec = new MaskedPasswordSpec(initialKeyMaterial, iterationCount, salt, maskedPasswordBytes, initializationVector);
PasswordFactory factory1 = PasswordFactory.getInstance(algorithm, providers);
ClearPasswordSpec unmasked = factory1.getKeySpec(factory1.generatePassword(spec).castAs(MaskedPassword.class), ClearPasswordSpec.class);
final char[] finalPassword = unmasked.getEncodedPassword();
return () -> {
    try {
        PasswordFactory factory2 = PasswordFactory.getInstance(ClearPassword.ALGORITHM_CLEAR, providers);
        return Assert.assertNotNull(factory2.generatePassword(new ClearPasswordSpec(finalPassword)).castAs(ClearPassword.class));
    } catch (InvalidKeySpecException | NoSuchAlgorithmException cause) {
        throw xmlLog.xmlFailedToCreateCredential(location, cause);
     }
};
...

Nice-to-Have Requirements

Non-Requirements

Test Plan

  • Tests will be added to test masked passwords with a clear spec as well as encryptable spec (in modular crypt format).

  • Elytron XML parser tests will be added.

  • Tests will be added to test PicketBox compatability.

  • Tests using Elytron client with clear-password will be copied and implemented with masked password instead.

Community Documentation

  • Documentation will be added in the "<credential-stores/>" and "<key-stores />" sections under _client-guide/authentication-client in the WildFly documentation to indicate that credentials and key store passwords can be specified as a masked-password in the Elytron authentication client.

  • Documentation will be added in the "The Configuration File Approach" and "The Programmatic Approach" sections under _elytron/Client_Authentication_with_Elytron_Client in the WildFly documentation to indicate that a masked password can be specified programmatically or in the client XML configuration file to be used for authentication.