public void init(DerivationParameters param) { if (!(param instanceof HKDFParameters)) { throw new IllegalArgumentException( "HKDF parameters required for HKDFBytesGenerator"); } HKDFParameters params = (HKDFParameters)param; if (params.skipExtract()) { // use IKM directly as PRK hMacHash.init(new KeyParameter(params.getIKM())); } else { hMacHash.init(extract(params.getSalt(), params.getIKM())); } info = params.getInfo(); generatedBytes = 0; currentT = new byte[hashLen]; }
/** * Generate a key from the given data. * * @param attribute * Attribute of the key to generate. * @param id * Id of the key to generate. * @param version * Version of the key to generate. * @param length * Length of the key to generate. * @return Generated key. */ private static byte[] generateKey(byte[] masterSecret, String attribute, String id, int version, int length) { ByteArrayOutputStream metadata = new ByteArrayOutputStream(); try { if (attribute != null) { metadata.write(Ints.toByteArray(attribute.length())); metadata.write(attribute.getBytes(ENCODING_CHARSET)); } metadata.write(Ints.toByteArray(version)); metadata.write(Ints.toByteArray(length)); } catch (IOException e) { /* won't be thrown */} hkdf.init(new HKDFParameters(masterSecret, id.getBytes(ENCODING_CHARSET), metadata.toByteArray())); byte[] key = new byte[length]; hkdf.generateBytes(key, 0, key.length); return key; }
/** * Generate a key from the given data. * * @param attribute * Attribute of the key to generate. * @param id * Id of the key to generate. * @param version * Version of the key to generate. * @param length * Length of the key to generate. * @return Generated key. */ private static byte[] generateKey(String attribute, String id, int version, int length) { ByteArrayOutputStream metadata = new ByteArrayOutputStream(); try { if (attribute != null) { metadata.write(Ints.toByteArray(attribute.length())); metadata.write(attribute.getBytes(ENCODING_CHARSET)); } metadata.write(Ints.toByteArray(version)); metadata.write(Ints.toByteArray(length)); } catch (IOException e) { /* won't be thrown */} hkdf.init(new HKDFParameters(MASTER_SECRET, id.getBytes(ENCODING_CHARSET), metadata.toByteArray())); byte[] key = new byte[length]; hkdf.generateBytes(key, 0, key.length); return key; }
@Override public void setPassword(String pass) throws FailToSyncCipherDataException { if (salts == null) { byte[] macSalt = new byte[8]; byte[] encSalt = new byte[8]; // left blank intentionally rand.nextBytes(macSalt); salts = new ByteParameterPair(encSalt, macSalt); try { Files.write(additSalt.toPath(), salts.toString().getBytes(StandardCharsets.US_ASCII), StandardOpenOption.WRITE, StandardOpenOption.CREATE); } catch (IOException e) { FailToSyncCipherDataException fc = new FailToSyncCipherDataException( "Cannot write salt to " + additSalt.getAbsolutePath() + " message:" + e.getMessage()); fc.initCause(e); throw fc; } } masterKey = this.generateKey(pass); hkdf.init(new HKDFParameters(masterKey, salts.getSecond(), "Mac Key".getBytes())); byte[] macKey = new byte[this.getMacKeySize() / 8]; hkdf.generateBytes(macKey, 0, macKey.length); this.initMac(macKey); }
@Override protected byte[] decryptData(String cData) { ByteParameterPair pair = ByteParameterPair.valueOf(cData); int keysize = StreamCipherEncryptors.INSTANCE.getKeySize(algName) / 8; int ivsize = StreamCipherEncryptors.INSTANCE.getIVSize(algName) / 8; byte[] keyCombo = new byte[keysize + ivsize]; hkdf.init(new HKDFParameters(masterKey, pair.getFirst(), "Encryption Key".getBytes())); hkdf.generateBytes(keyCombo, 0, keyCombo.length); byte[] key = new byte[keysize]; byte[] iv = new byte[ivsize]; System.arraycopy(keyCombo, 0, key, 0, keysize); System.arraycopy(keyCombo, keysize, iv, 0, ivsize); StreamCipherEncryptor enc = StreamCipherEncryptors.INSTANCE.getEncryptor(algName); return enc.decrypt(pair.getSecond(), key, iv); }
public static final byte[] apply(byte[] ikm, byte[] salt, byte[] info, Supplier<Digest> digestSupplier, int keyLengthBytes) { logger.trace("<< apply() - ikm: 0x{} salt: 0x{} info: 0x{} digestSupplier: {} keyLengthBytes: {}", Hex.toHexString(ikm), Hex.toHexString(salt), Hex.toHexString(info), digestSupplier, keyLengthBytes); Digest hash = digestSupplier.get(); byte[] okm = new byte[keyLengthBytes]; HKDFParameters params = new HKDFParameters(ikm, salt, info); HKDFBytesGenerator hkdf = new HKDFBytesGenerator(hash); hkdf.init(params); hkdf.generateBytes(okm, 0, keyLengthBytes); logger.trace(">> apply() - output keying material: 0x{}", Hex.toHexString(okm)); return okm; }
private HttpResponse createUser(byte[] username, byte[] ltpk, byte[] proof) throws Exception { HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA512Digest()); hkdf.init(new HKDFParameters(k, "Pair-Setup-Controller-Sign-Salt".getBytes(StandardCharsets.UTF_8), "Pair-Setup-Controller-Sign-Info".getBytes(StandardCharsets.UTF_8))); byte[] okm = new byte[32]; hkdf.generateBytes(okm, 0, 32); byte[] completeData = ByteUtils.joinBytes(okm, username, ltpk); if (!new EdsaVerifier(ltpk).verify(completeData, proof)) { throw new Exception("Invalid signature"); } authInfo.createUser(authInfo.getMac()+new String(username, StandardCharsets.UTF_8), ltpk); advertiser.setDiscoverable(false); return createResponse(); }
/** * Generate a key from the given data. * * @param attribute * Attribute of the key to generate. * @param id * Id of the key to generate. * @param version * Version of the key to generate. * @param length * Length of the key to generate. * @return Generated key. */ private byte[] generateKey(String attribute, String id, int version, int length) { ByteArrayOutputStream metadata = new ByteArrayOutputStream(); try { metadata.write(id.getBytes(StandardCharsets.UTF_8)); metadata.write(Ints.toByteArray(version)); metadata.write(Ints.toByteArray(length)); } catch (IOException e) { /* won't be thrown */} byte[] key = new byte[length]; hkdf.init(new HKDFParameters(HKDF_KEY, attribute.getBytes(StandardCharsets.UTF_8), metadata.toByteArray())); hkdf.generateBytes(key, 0, key.length); return key; }
/** * derive the key from the password * * @throws FailToSyncCipherDataException */ @Override public void setPassword(String string) throws FailToSyncCipherDataException { try { String saltRaw = salts.read(StandardCharsets.US_ASCII); if (saltRaw.length() > 0) { saltPair = ByteParameterPair.valueOf(saltRaw); } else { byte[] encSalt = new byte[8]; byte[] macSalt = new byte[8]; rand.nextBytes(encSalt); rand.nextBytes(macSalt); saltPair = new ByteParameterPair(encSalt, macSalt); salts.write(saltPair.toString(), StandardCharsets.US_ASCII); } } catch (IOException e) { FailToSyncCipherDataException fc = new FailToSyncCipherDataException( "Cannot load encryption and mac salt from file"); fc.initCause(e); throw fc; } this.key = generateKey(string); hkdf.init(new HKDFParameters(key, saltPair.getFirst(), "Encryption Key".getBytes())); cryptKey = new byte[enc.getKeySize() / 8]; hkdf.generateBytes(cryptKey, 0, cryptKey.length); byte[] macKey = new byte[getMacKeySize() / 8]; hkdf.init(new HKDFParameters(key, saltPair.getSecond(), "Mac Key".getBytes())); hkdf.generateBytes(macKey, 0, macKey.length); initMac(macKey); }
/** * Convenience method for computing the HMAC Key Derivation Function. The * real work is offloaded to BouncyCastle. */ protected static byte[] hkdfExpand(byte[] ikm, byte[] salt, byte[] info, int length) throws InvalidKeyException, NoSuchAlgorithmException { HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA256Digest()); hkdf.init(new HKDFParameters(ikm, salt, info)); byte[] okm = new byte[length]; hkdf.generateBytes(okm, 0, length); return okm; }
public HttpResponse handle(PairSetupRequest req) throws Exception { HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA512Digest()); hkdf.init(new HKDFParameters(k, "Pair-Setup-Encrypt-Salt".getBytes(StandardCharsets.UTF_8), "Pair-Setup-Encrypt-Info".getBytes(StandardCharsets.UTF_8))); byte[] okm = hkdf_enc_key = new byte[32]; hkdf.generateBytes(okm, 0, 32); return decrypt((Stage3Request) req, okm); }
private HttpResponse createResponse() throws Exception { HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA512Digest()); hkdf.init(new HKDFParameters(k, "Pair-Setup-Accessory-Sign-Salt".getBytes(StandardCharsets.UTF_8), "Pair-Setup-Accessory-Sign-Info".getBytes(StandardCharsets.UTF_8))); byte[] okm = new byte[32]; hkdf.generateBytes(okm, 0, 32); EdsaSigner signer = new EdsaSigner(authInfo.getPrivateKey()); byte[] material = ByteUtils.joinBytes(okm, authInfo.getMac().getBytes(StandardCharsets.UTF_8), signer.getPublicKey()); byte[] proof = signer.sign(material); Encoder encoder = TypeLengthValueUtils.getEncoder(); encoder.add(MessageType.USERNAME, authInfo.getMac().getBytes(StandardCharsets.UTF_8)); encoder.add(MessageType.PUBLIC_KEY, signer.getPublicKey()); encoder.add(MessageType.SIGNATURE, proof); byte[] plaintext = encoder.toByteArray(); ChachaEncoder chacha = new ChachaEncoder(hkdf_enc_key, "PS-Msg06".getBytes(StandardCharsets.UTF_8)); byte[] ciphertext = chacha.encodeCiphertext(plaintext); encoder = TypeLengthValueUtils.getEncoder(); encoder.add(MessageType.STATE, (short) 6); encoder.add(MessageType.ENCRYPTED_DATA, ciphertext); return new PairingResponse(encoder.toByteArray()); }
private HttpResponse stage1(Stage1Request request) throws Exception { logger.debug("Starting pair verification for "+registry.getLabel()); clientPublicKey = request.getClientPublicKey(); publicKey = new byte[32]; byte[] privateKey = new byte[32]; getSecureRandom().nextBytes(privateKey); Curve25519.keygen(publicKey, null, privateKey); sharedSecret = new byte[32]; Curve25519.curve(sharedSecret, privateKey, clientPublicKey); byte[] material = ByteUtils.joinBytes(publicKey, authInfo.getMac().getBytes(StandardCharsets.UTF_8), clientPublicKey); byte[] proof = new EdsaSigner(authInfo.getPrivateKey()).sign(material); HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA512Digest()); hkdf.init(new HKDFParameters(sharedSecret, "Pair-Verify-Encrypt-Salt".getBytes(StandardCharsets.UTF_8), "Pair-Verify-Encrypt-Info".getBytes(StandardCharsets.UTF_8))); hkdfKey = new byte[32]; hkdf.generateBytes(hkdfKey, 0, 32); Encoder encoder = TypeLengthValueUtils.getEncoder(); encoder.add(MessageType.USERNAME, authInfo.getMac().getBytes(StandardCharsets.UTF_8)); encoder.add(MessageType.SIGNATURE, proof); byte[] plaintext = encoder.toByteArray(); ChachaEncoder chacha = new ChachaEncoder(hkdfKey, "PV-Msg02".getBytes(StandardCharsets.UTF_8)); byte[] ciphertext = chacha.encodeCiphertext(plaintext); encoder = TypeLengthValueUtils.getEncoder(); encoder.add(MessageType.STATE, (short) 2); encoder.add(MessageType.ENCRYPTED_DATA, ciphertext); encoder.add(MessageType.PUBLIC_KEY, publicKey); return new PairingResponse(encoder.toByteArray()); }
private byte[] createKey(String info) { HKDFBytesGenerator hkdf = new HKDFBytesGenerator(new SHA512Digest()); hkdf.init(new HKDFParameters(sharedSecret, "Control-Salt".getBytes(StandardCharsets.UTF_8), info.getBytes(StandardCharsets.UTF_8))); byte[] key = new byte[32]; hkdf.generateBytes(key, 0, 32); return key; }
@Override protected String encryptData(byte[] bytes) { byte[] randomSource = new byte[16]; rand.nextBytes(randomSource); int keysize = StreamCipherEncryptors.INSTANCE.getKeySize(algName) / 8; int ivsize = StreamCipherEncryptors.INSTANCE.getIVSize(algName) / 8; byte[] keyCombo = new byte[keysize + ivsize]; hkdf.init(new HKDFParameters(masterKey, randomSource, "Encryption Key".getBytes())); hkdf.generateBytes(keyCombo, 0, keyCombo.length); byte[] key = new byte[keysize]; byte[] iv = new byte[ivsize]; System.arraycopy(keyCombo, 0, key, 0, keysize); System.arraycopy(keyCombo, keysize, iv, 0, ivsize); StreamCipherEncryptor enc = StreamCipherEncryptors.INSTANCE.getEncryptor(algName); byte[] ecrypted = enc.encrypt(bytes, key, iv); ByteParameterPair pair = new ByteParameterPair(randomSource, ecrypted); return pair.toString(); }
/** * @param ikm * Master key * @param salt * @param info * Some extra (public) information. * @param outKeyLen * The derived key length * @return A derived key. */ public static byte[] deriveKey(byte[] ikm, byte[] salt, byte[] info, int outKeyLen) { HKDFBytesGenerator kdf = new HKDFBytesGenerator(new SHA1Digest()); kdf.init(new HKDFParameters(ikm, salt, info)); byte[] outKey = new byte[outKeyLen]; kdf.generateBytes(outKey, 0, outKeyLen); return outKey; }