2

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?

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
cantara256
  • 83
  • 5
  • I've added Java to the tags. Try always to indicate the runtime environment. Please change if I guessed wrong. – Maarten Bodewes Feb 27 '19 at 01:07
  • 1
    Note that SHA-384 is essentially SHA-512 with different initial constant values and then taking the leftmost bits from the result. SHA-512 will have the same properties and a larger output, if you need that. – Maarten Bodewes Feb 27 '19 at 01:10

1 Answers1

1

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.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Interesting that it can be a static public string or a random nonce; I assume random bytes are better. On the Bouncy Castle email list it was recommended to use random bytes with length at least the size of the KDF digest (e.g. SHA384 in the BCFIPS examples). – cantara256 Feb 27 '19 at 00:57
  • 1
    It's probably essential that they are random bytes if both DH keys are static. But then you would definitely have to validate the session key(s) afterwards. Validating them is a good idea anyway, of course, e.g. by calculating a MAC over previous messages. Injecting more randomness will ease some proofs of security, but as the (EC)DH key pairs should be generated randomly anyway, it is not strictly necessary in practice. – Maarten Bodewes Feb 27 '19 at 01:04