Search code examples
javacryptographybouncycastlediffie-hellmankdf

Bouncy Castle Diffie-Hellman KeyAgreement with KDF: What is user keying material?


The Bouncy Castle Diffie-Hellman documentation speaks of using "user keying material" and a KDF when deriving ephemeral keys from a static long term key pair. There is no mention of how to generate this key material.

For example, in BCFipsIn100.pdf, they have this example:

    public static byte[] initiatorAgreementWithKdf(PrivateKey initiatorPrivate, PublicKey recipientPublic, byte[] userKeyingMaterial) throws GeneralSecurityException {
        KeyAgreement agreement = KeyAgreement.getInstance("ECCDHwithSHA384CKDF", "BCFIPS");
        agreement.init(initiatorPrivate, new UserKeyingMaterialSpec(userKeyingMaterial));
        agreement.doPhase(recipientPublic, true);
        SecretKey agreedKey = agreement.generateSecret("AES[256]");
        return agreedKey.getEncoded();
    }

Their examples use static strings for userKeyingMaterial, but make no mention of generally what this is supposed to be.

What are the specifications on how to generate userKeyingMaterial? Can it be a single static string like their examples or is it essentially a nonce? What length? Can it be shared publicly when the parties exchange their public keys?


Solution

  • It is used as extraInfo parameter in the DHKDFParameters class, which is used to initialize the KDF. The KDF may be used to derive different keys from a master key by mixing in additional bytes besides the shared secret, calculated from the key agreement algorithm, in this case ECCDH. The SHA384KDF is likely an ANS X9.63 compatible KDF, which takes an additional Info octet string (there are various "info" inspired names for this octet string (i.e. byte array).

    There are no specifications on how to generate it. It could be the ASCII encoding of a label, say "SessionKeyMaterial".getBytes(StandardCharsets.US_ASCII). It could also include identifiers of both parties, public keys, nonces. Essentially it can take any data, as long as you manage to have an explicit encoding of that data that doesn't overlap (i.e. a canonical representation of the data).

    Usually it is just a static string called a label. No length restrictions and the data can be shared publicly. The shared secret will make sure that the resulting key is just shared between the right parties, as long as the connection is authenticated one way or another; you need to know who you're performing the key agreement with, after all.