private static byte[] scp03_kdf(byte[] key, byte constant, byte[] context, int blocklen_bits) { // 11 bytes byte[] label = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ByteArrayOutputStream bo = new ByteArrayOutputStream(); try { bo.write(label); // 11 bytes of label bo.write(constant); // constant for the last byte bo.write(0x00); // separator bo.write((blocklen_bits >> 8) & 0xFF); // block size in two bytes bo.write(blocklen_bits & 0xFF); } catch (IOException ioe) { throw new RuntimeException(ioe); } byte[] blocka = bo.toByteArray(); byte[] blockb = context; BlockCipher cipher = new AESEngine(); CMac cmac = new CMac(cipher); KDFCounterBytesGenerator kdf = new KDFCounterBytesGenerator(cmac); kdf.init(new KDFCounterParameters(key, blocka, blockb, 8)); // counter size in bits byte[] cgram = new byte[blocklen_bits / 8]; kdf.generateBytes(cgram, 0, cgram.length); return cgram; }
public static byte[] ctrHMac(byte[] keyDerivationKey, byte[] label, Supplier<Digest> digestSupplier, int keyLengthBytes) { logger.trace("<< ctrHMac() - keyDerivationKey: 0x{} label: {} digestSupplier: {} length: {}", Hex.toHexString(keyDerivationKey), Hex.toHexString(label), digestSupplier, keyLengthBytes); byte[] derivedKey = new byte[keyLengthBytes]; // fixedInputData = label || 0x00 || dkLen in bits as 4 bytes big endian ByteBuffer buffer = ByteBuffer.allocate(label.length + 5); buffer.put(label); buffer.put((byte) 0); buffer.putInt(keyLengthBytes * 8); byte[] fixedInputData = buffer.array(); logger.debug("-- ctrHMac() - fixed input data: 0x{}", Hex.toHexString(fixedInputData)); HMac hMac = new HMac(digestSupplier.get()); KDFCounterBytesGenerator generator = new KDFCounterBytesGenerator(hMac); generator.init(new KDFCounterParameters(keyDerivationKey, fixedInputData, R)); generator.generateBytes(derivedKey, 0, derivedKey.length); logger.trace(">> ctrHMac() - derivedKey: 0x{}", Hex.toHexString(derivedKey)); return derivedKey; }
/** * @param sessionKey * @param label * @param context */ private static byte[] derive ( byte[] sessionKey, byte[] label, byte[] context ) { KDFCounterBytesGenerator gen = new KDFCounterBytesGenerator(new HMac(new SHA256Digest())); int r = 32; byte[] suffix = new byte[label.length + context.length + 5]; // per bouncycastle // <li>1: K(i) := PRF( KI, [i]_2 || Label || 0x00 || Context || [L]_2 ) with the counter at the very beginning // of the fixedInputData (The default implementation has this format)</li> // with the parameters // <li>1. KDFCounterParameters(ki, null, "Label || 0x00 || Context || [L]_2]", 8); // all fixed inputs go into the suffix: // + label System.arraycopy(label, 0, suffix, 0, label.length); // + 1 byte 0x00 // + context System.arraycopy(context, 0, suffix, label.length + 1, context.length); // + 4 byte (== r bits) big endian encoding of L suffix[ suffix.length - 1 ] = (byte) 128; DerivationParameters param = new KDFCounterParameters(sessionKey, null /* prefix */, suffix /* suffix */, r /* r */); gen.init(param); byte[] derived = new byte[16]; gen.generateBytes(derived, 0, 16); return derived; }
public void receiveCAVPVectors(String name, Properties config, Properties vectors) { // always skip AFTER_FIXED, not included in SP 800-108 if (config.getProperty("CTRLOCATION").matches("AFTER_FIXED")) { return; } // create Mac based PRF from PRF property, create the KDF final Mac prf = CAVPReader.createPRF(config); final KDFCounterBytesGenerator gen = new KDFCounterBytesGenerator(prf); Matcher matcherForR = CAVPReader.PATTERN_FOR_R.matcher(config.getProperty("RLEN")); if (!matcherForR.matches()) { throw new IllegalStateException("RLEN value should always match"); } final int r = Integer.parseInt(matcherForR.group(1)); final int count = Integer.parseInt(vectors.getProperty("COUNT")); final int l = Integer.parseInt(vectors.getProperty("L")); final byte[] ki = Hex.decode(vectors.getProperty("KI")); final byte[] fixedInputData = Hex.decode(vectors.getProperty("FixedInputData")); final KDFCounterParameters params = new KDFCounterParameters(ki, fixedInputData, r); gen.init(params); final byte[] koGenerated = new byte[l / 8]; gen.generateBytes(koGenerated, 0, koGenerated.length); final byte[] koVectors = Hex.decode(vectors.getProperty("KO")); compareKO(name, config, count, koGenerated, koVectors); }