def deriveSecrets(self, masterKey): """ Derive various session keys from the given `masterKey'. The argument `masterKey' is used to derive two session keys and nonces for AES-CTR and two HMAC keys. The derivation is done using HKDF-SHA256. """ assert len(masterKey) == const.MASTER_KEY_LENGTH log.debug("Deriving session keys from %d-byte master key." % len(masterKey)) # We need key material for two symmetric AES-CTR keys, nonces and # HMACs. In total, this equals 144 bytes of key material. hkdf = mycrypto.HKDF_SHA256(masterKey, "", (32 * 4) + (8 * 2)) okm = hkdf.expand() assert len(okm) >= ((32 * 4) + (8 * 2)) # Set AES-CTR keys and nonces for our two AES instances. self.sendCrypter.setSessionKey(okm[0:32], okm[32:40]) self.recvCrypter.setSessionKey(okm[40:72], okm[72:80]) # Set the keys for the two HMACs protecting our data integrity. self.sendHMAC = okm[80:112] self.recvHMAC = okm[112:144] if self.weAreServer: self.sendHMAC, self.recvHMAC = self.recvHMAC, self.sendHMAC self.sendCrypter, self.recvCrypter = self.recvCrypter, \ self.sendCrypter
def test4_HKDF_TestCase4( self ): self.assertRaises(ValueError, mycrypto.HKDF_SHA256, "x" * 40, length=(32*255)+1) self.assertRaises(ValueError, mycrypto.HKDF_SHA256, "tooShort") # Accidental re-use should raise an exception. hkdf = mycrypto.HKDF_SHA256("x" * 40) hkdf.expand() self.assertRaises(base.PluggableTransportError, hkdf.expand)
def _deriveSecrets(self, masterKey): """Derives session keys (AES keys, counter nonces, HMAC keys and magic values) from the given master secret. All key material is derived using HKDF-SHA256.""" log.debug("Master key: 0x%s." % masterKey.encode('hex')) # We need key material for two magic values, symmetric keys, nonces and # HMACs. All of them are 32 bytes in size. hkdf = mycrypto.HKDF_SHA256(masterKey, "", 32 * 8) okm = hkdf.expand() # Set the symmetric AES keys. self.sendCrypter.setSessionKey(okm[0:32], okm[32:64]) self.recvCrypter.setSessionKey(okm[64:96], okm[96:128]) # Derive a magic value for the client as well as the server. They must # be distinct to prevent fingerprinting (e.g. look for two identical # 256-bit strings). self.sendMagic = okm[128:160] self.recvMagic = okm[160:192] # Set the HMAC keys. self.sendHMAC = okm[192:224] self.recvHMAC = okm[224:256] if self.weAreServer: self.sendHMAC, self.recvHMAC = util.swap(self.sendHMAC, self.recvHMAC) self.sendCrypter, self.recvCrypter = util.swap(self.sendCrypter, \ self.recvCrypter) self.sendMagic, self.recvMagic = util.swap(self.sendMagic, \ self.recvMagic) log.debug("Magic values derived from session key: send=0x%s, " \ "recv=0x%s." % (self.sendMagic.encode('hex'), \ self.recvMagic.encode('hex')))
def runHKDF( self, ikm, salt, info, prk, okm ): myprk = self.extract(salt, ikm) self.failIf(myprk != prk) myokm = mycrypto.HKDF_SHA256(myprk, info).expand() self.failUnless(myokm in okm)