Key derivation fixes, renamed a key derivation method.

This commit is contained in:
akwizgran
2016-03-30 12:02:49 +01:00
parent a8fa6339fb
commit e78ba2e806
5 changed files with 35 additions and 52 deletions

View File

@@ -36,11 +36,10 @@ public interface CryptoComponent {
int deriveBTConfirmationCode(SecretKey master, boolean alice);
/**
* Derives a header key for an invitation stream from the given master
* secret.
* Derives a stream header key from the given master secret.
* @param alice whether the key is for use by Alice or Bob.
*/
SecretKey deriveBTInvitationKey(SecretKey master, boolean alice);
SecretKey deriveHeaderKey(SecretKey master, boolean alice);
/**
* Derives a nonce from the given master secret for one of the parties to
@@ -107,7 +106,7 @@ public interface CryptoComponent {
* Derives a master secret from two public keys and one of the corresponding
* private keys.
* <p/>
* Part of BQP. This is a helper method that calls
* This is a helper method that calls
* deriveMasterSecret(deriveSharedSecret(theirPublicKey, ourKeyPair, alice))
*
* @param theirPublicKey the ephemeral public key of the remote party

View File

@@ -93,6 +93,9 @@ public class ContactExchangeTaskImpl extends Thread
@Override
public void run() {
// Derive the header keys for the transport streams
SecretKey aliceHeaderKey = crypto.deriveHeaderKey(masterSecret, true);
SecretKey bobHeaderKey = crypto.deriveHeaderKey(masterSecret, false);
BdfReader r;
BdfWriter w;
try {
@@ -100,13 +103,13 @@ public class ContactExchangeTaskImpl extends Thread
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(
conn.getReader().getInputStream(),
masterSecret);
alice ? bobHeaderKey : aliceHeaderKey);
r = bdfReaderFactory.createReader(streamReader);
// Create the writers
OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(
conn.getWriter().getOutputStream(),
masterSecret);
alice ? aliceHeaderKey : bobHeaderKey);
w = bdfWriterFactory.createWriter(streamWriter);
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
@@ -115,7 +118,7 @@ public class ContactExchangeTaskImpl extends Thread
return;
}
// Derive the invitation nonces
// Derive the nonces to be signed
byte[] aliceNonce = crypto.deriveSignatureNonce(masterSecret, true);
byte[] bobNonce = crypto.deriveSignatureNonce(masterSecret, false);
@@ -155,8 +158,8 @@ public class ContactExchangeTaskImpl extends Thread
try {
// Add the contact
ContactId contactId =
addContact(remoteAuthor, masterSecret, timestamp, true);
ContactId contactId = addContact(remoteAuthor, masterSecret,
timestamp, alice);
// Reuse the connection as a transport connection
connectionManager.manageOutgoingConnection(contactId, transportId,
conn);

View File

@@ -63,24 +63,22 @@ class CryptoComponentImpl implements CryptoComponent {
return s.getBytes(Charset.forName("US-ASCII"));
}
// KDF label for bluetooth master key derivation
private static final byte[] BT_MASTER = ascii("MASTER");
// KDF labels for bluetooth confirmation code derivation
private static final byte[] BT_A_CONFIRM = ascii("ALICE_CONFIRMATION_CODE");
private static final byte[] BT_B_CONFIRM = ascii("BOB_CONFIRMATION_CODE");
// KDF labels for bluetooth invitation stream header key derivation
private static final byte[] BT_A_INVITE = ascii("ALICE_INVITATION_KEY");
private static final byte[] BT_B_INVITE = ascii("BOB_INVITATION_KEY");
// KDF labels for bluetooth signature nonce derivation
private static final byte[] BT_A_NONCE = ascii("ALICE_SIGNATURE_NONCE");
private static final byte[] BT_B_NONCE = ascii("BOB_SIGNATURE_NONCE");
// KDF labels for contact exchange stream header key derivation
private static final byte[] A_INVITE = ascii("ALICE_INVITATION_KEY");
private static final byte[] B_INVITE = ascii("BOB_INVITATION_KEY");
// KDF labels for contact exchange signature nonce derivation
private static final byte[] A_SIG_NONCE = ascii("ALICE_SIGNATURE_NONCE");
private static final byte[] B_SIG_NONCE = ascii("BOB_SIGNATURE_NONCE");
// Hash label for BQP public key commitment derivation
private static final byte[] COMMIT = ascii("COMMIT");
// Hash label for BQP shared secret derivation
// Hash label for shared secret derivation
private static final byte[] SHARED_SECRET = ascii("SHARED_SECRET");
// KDF label for BQP confirmation key derivation
private static final byte[] CONFIRMATION_KEY = ascii("CONFIRMATION_KEY");
// KDF label for BQP master key derivation
// KDF label for master key derivation
private static final byte[] MASTER_KEY = ascii("MASTER_KEY");
// KDF labels for tag key derivation
private static final byte[] A_TAG = ascii("ALICE_TAG_KEY");
@@ -210,12 +208,14 @@ class CryptoComponentImpl implements CryptoComponent {
return ByteUtils.readUint(b, CODE_BITS);
}
public SecretKey deriveBTInvitationKey(SecretKey master, boolean alice) {
return new SecretKey(macKdf(master, alice ? BT_A_INVITE : BT_B_INVITE));
public SecretKey deriveHeaderKey(SecretKey master,
boolean alice) {
return new SecretKey(macKdf(master, alice ? A_INVITE : B_INVITE));
}
public byte[] deriveSignatureNonce(SecretKey master, boolean alice) {
return macKdf(master, alice ? BT_A_NONCE : BT_B_NONCE);
public byte[] deriveSignatureNonce(SecretKey master,
boolean alice) {
return macKdf(master, alice ? A_SIG_NONCE : B_SIG_NONCE);
}
public byte[] deriveKeyCommitment(byte[] publicKey) {
@@ -438,29 +438,6 @@ class CryptoComponentImpl implements CryptoComponent {
}
}
// Key derivation function based on a hash function - see NIST SP 800-56A,
// section 5.8
private byte[] hashKdf(byte[]... inputs) {
Digest digest = new Blake2sDigest();
// The output of the hash function must be long enough to use as a key
int hashLength = digest.getDigestSize();
if (hashLength < SecretKey.LENGTH) throw new IllegalStateException();
// Calculate the hash over the concatenated length-prefixed inputs
byte[] length = new byte[INT_32_BYTES];
for (byte[] input : inputs) {
ByteUtils.writeUint32(input.length, length, 0);
digest.update(length, 0, length.length);
digest.update(input, 0, input.length);
}
byte[] hash = new byte[hashLength];
digest.doFinal(hash, 0);
// The output is the first SecretKey.LENGTH bytes of the hash
if (hash.length == SecretKey.LENGTH) return hash;
byte[] truncated = new byte[SecretKey.LENGTH];
System.arraycopy(hash, 0, truncated, 0, truncated.length);
return truncated;
}
// Key derivation function based on a pseudo-random function - see
// NIST SP 800-108, section 5.1
private byte[] macKdf(SecretKey key, byte[]... inputs) {

View File

@@ -125,8 +125,8 @@ class AliceConnector extends Connector {
if (LOG.isLoggable(INFO))
LOG.info(pluginName + " confirmation succeeded");
// Derive the header keys
SecretKey aliceHeaderKey = crypto.deriveBTInvitationKey(master, true);
SecretKey bobHeaderKey = crypto.deriveBTInvitationKey(master, false);
SecretKey aliceHeaderKey = crypto.deriveHeaderKey(master, true);
SecretKey bobHeaderKey = crypto.deriveHeaderKey(master, false);
// Create the readers
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in,

View File

@@ -125,8 +125,10 @@ class BobConnector extends Connector {
if (LOG.isLoggable(INFO))
LOG.info(pluginName + " confirmation succeeded");
// Derive the header keys
SecretKey aliceHeaderKey = crypto.deriveBTInvitationKey(master, true);
SecretKey bobHeaderKey = crypto.deriveBTInvitationKey(master, false);
SecretKey aliceHeaderKey = crypto.deriveHeaderKey(master,
true);
SecretKey bobHeaderKey = crypto.deriveHeaderKey(master,
false);
// Create the readers
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in,
@@ -138,8 +140,10 @@ class BobConnector extends Connector {
bobHeaderKey);
w = bdfWriterFactory.createWriter(streamWriter);
// Derive the nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
byte[] bobNonce = crypto.deriveSignatureNonce(master, false);
byte[] aliceNonce = crypto.deriveSignatureNonce(master,
true);
byte[] bobNonce = crypto.deriveSignatureNonce(master,
false);
// Exchange pseudonyms, signed nonces and timestamps
Author remoteAuthor;
long remoteTimestamp;