def _hmacedString(key, string): """ Return the SHA-1 HMAC hash of the given key and string. """ hash = HMAC(key, digestmod=sha) hash.update(string) return hash.digest()
def compute_hash(key, pkt, pre=None, post=None): if (pre): h = HMAC(key, pre, Crypto.Hash.SHA) h.update(pkt) else: h = HMAC(key, pkt, Crypto.Hash.SHA) if post: h.update(post) return h.digest()
def wrap(data, authKey, keyWrapKey): hmac = HMAC(authKey, digestmod=SHA256) hmac.update(data) kwa = hmac.digest()[:8] iv = os.urandom(16) cipher = AES.new(keyWrapKey, AES.MODE_CBC, iv) wrapped = cipher.encrypt(pad(data + kwa)) wrapped = wrapped + iv return wrapped
def mac_sign(kwargs=None, expires=None, key='', mac_len=0, mac_format='hex'): key = key or config.SIGN_KEY if not key: raise Exception('No key configured for signing the HMAC') if not kwargs: raise Exception('No message provided to be signed') if expires: kwargs['_expires'] = int(time() + expires) parts = ["%s=%s" % (key, kwargs[key]) for key in sorted(kwargs.keys())] msg = "&".join(parts) hmac = HMAC(str(key), msg=str(msg), digestmod=SHA256Hash()) if mac_format == 'b64': tag = urlsafe_b64encode(hmac.digest()).rstrip('=') elif mac_format == 'bin': tag = hmac.digest() else: tag = hmac.hexdigest() if mac_len: tag = tag[:mac_len] kwargs['_mac'] = tag
def unwrap(data, authKey, keyWrapKey): iv = data[-16:] cipher = AES.new(keyWrapKey, AES.MODE_CBC, iv) unwrapped = cipher.decrypt(data[:-16]) unwrapped = unpad(unwrapped) kwa = unwrapped[-8:] unwrapped = unwrapped[:-8] hmac = HMAC(authKey, digestmod=SHA256) hmac.update(unwrapped) local_kwa = hmac.digest()[:8] if kwa != local_kwa: print("Unwrapped kwa does not match") return unwrapped
def ExtractEntropySeed(rounds, username, password, salt=None): # Concentrates and then extracts the random entropy provided # by the password into a seed value for the first hash stage. # If if an explicit salt value is missing, use a hash of # the username as if it were the salt. if salt is None: salt = SHA512.new(username).digest() # Confirm the supplied salt meets the minimum length of 64 # octets required, is aligned to a 32 octet boundary and does not # exceed 1,024 octets. Some implementations may not handle salt # values longer than 1,024 octets properly. elif len(salt) < 64: raise ValueError("The salt, if supplied, must be at least " \ "64 octets in length.") elif operator.mod(len(salt), 32) != 0: warnings.warn("The salt, if longer than 64 octets, should " \ "be aligned to a 32 octet boundary.") elif len(salt) > 1024: warnings.warn("The salt should not exceed 1,024 octets.") # For salt values which don't match the 128 octets required for # an HMAC key value, the salt is hashed twice using a 3 octet # counter value of 0 and 1, and the outputs are concatenated. if len(salt) != 128: key = \ SHA512.new(salt + struct.pack('>I', 0)[1:4]).digest() + \ SHA512.new(salt + struct.pack('>I', 1)[1:4]).digest() # If the supplied salt is 128 octets use it directly as the key value. else: key = salt # Initialize the HMAC instance using the key created above. hmac = HMAC(key, None, SHA512) # Repeat the plaintext password successively based on # the number of instances specified by the rounds variable. for unused in range(0, rounds): hmac.update(password) # Create the 64 octet seed value. seed = hmac.digest() return seed
def register(self): """ Gets authentication info from a DPT-RP1. You can call this BEFORE DigitalPaper.authenticate() Returns (ca, priv_key, client_id): - ca: a PEM-encoded X.509 server certificate, issued by the CA on the device - priv_key: a PEM-encoded 2048-bit RSA private key - client_id: the client id """ reg_url = "http://{addr}:8080".format(addr=self.addr) register_pin_url = "{base_url}/register/pin".format(base_url=reg_url) register_hash_url = "{base_url}/register/hash".format(base_url=reg_url) register_ca_url = "{base_url}/register/ca".format(base_url=reg_url) register_url = "{base_url}/register".format(base_url=reg_url) register_cleanup_url = "{base_url}/register/cleanup".format( base_url=reg_url) print("Cleaning up...") r = self.session.put(register_cleanup_url) print(r) print("Requesting PIN...") r = self.session.post(register_pin_url) m1 = r.json() n1 = base64.b64decode(m1["a"]) mac = base64.b64decode(m1["b"]) yb = base64.b64decode(m1["c"]) yb = int.from_bytes(yb, "big") n2 = os.urandom(16) # random nonce dh = DiffieHellman() ya = dh.gen_public_key() ya = b"\x00" + ya.to_bytes(256, "big") zz = dh.gen_shared_key(yb) zz = zz.to_bytes(256, "big") yb = yb.to_bytes(256, "big") derivedKey = PBKDF2(passphrase=zz, salt=n1 + mac + n2, iterations=10000, digestmodule=SHA256).read(48) authKey = derivedKey[:32] keyWrapKey = derivedKey[32:] hmac = HMAC(authKey, digestmod=SHA256) hmac.update(n1 + mac + yb + n1 + n2 + mac + ya) m2hmac = hmac.digest() m2 = dict( a=base64.b64encode(n1).decode("utf-8"), b=base64.b64encode(n2).decode("utf-8"), c=base64.b64encode(mac).decode("utf-8"), d=base64.b64encode(ya).decode("utf-8"), e=base64.b64encode(m2hmac).decode("utf-8"), ) print("Encoding nonce...") r = self.session.post(register_hash_url, json=m2) m3 = r.json() if base64.b64decode(m3["a"]) != n2: print("Nonce N2 doesn't match") return eHash = base64.b64decode(m3["b"]) m3hmac = base64.b64decode(m3["e"]) hmac = HMAC(authKey, digestmod=SHA256) hmac.update(n1 + n2 + mac + ya + m2hmac + n2 + eHash) if m3hmac != hmac.digest(): print("M3 HMAC doesn't match") return pin = input("Please enter the PIN shown on the DPT-RP1: ") hmac = HMAC(authKey, digestmod=SHA256) hmac.update(pin.encode()) psk = hmac.digest() rs = os.urandom(16) # random nonce hmac = HMAC(authKey, digestmod=SHA256) hmac.update(rs + psk + yb + ya) rHash = hmac.digest() wrappedRs = wrap(rs, authKey, keyWrapKey) hmac = HMAC(authKey, digestmod=SHA256) hmac.update(n2 + eHash + m3hmac + n1 + rHash + wrappedRs) m4hmac = hmac.digest() m4 = dict( a=base64.b64encode(n1).decode("utf-8"), b=base64.b64encode(rHash).decode("utf-8"), d=base64.b64encode(wrappedRs).decode("utf-8"), e=base64.b64encode(m4hmac).decode("utf-8"), ) print("Getting certificate from device CA...") r = self.session.post(register_ca_url, json=m4) print(r) m5 = r.json() if base64.b64decode(m5["a"]) != n2: print("Nonce N2 doesn't match") return wrappedEsCert = base64.b64decode(m5["d"]) m5hmac = base64.b64decode(m5["e"]) hmac = HMAC(authKey, digestmod=SHA256) hmac.update(n1 + rHash + wrappedRs + m4hmac + n2 + wrappedEsCert) if hmac.digest() != m5hmac: print("HMAC doesn't match!") return esCert = unwrap(wrappedEsCert, authKey, keyWrapKey) es = esCert[:16] cert = esCert[16:] hmac = HMAC(authKey, digestmod=SHA256) hmac.update(es + psk + yb + ya) if hmac.digest() != eHash: print("eHash does not match!") return # print("Certificate: ") # print(cert) print("Generating RSA2048 keys") new_key = RSA.generate(2048, e=65537) # with open("key.pem", 'wb') as f: # f.write(new_key.exportKey("PEM")) keyPubC = new_key.publickey().exportKey("PEM") selfDeviceId = str(uuid.uuid4()) print("Device ID: " + selfDeviceId) selfDeviceId = selfDeviceId.encode() # with open("client_id.txt", 'wb') as f: # f.write(selfDeviceId) wrappedDIDKPUBC = wrap(selfDeviceId + keyPubC, authKey, keyWrapKey) hmac = HMAC(authKey, digestmod=SHA256) hmac.update(n2 + wrappedEsCert + m5hmac + n1 + wrappedDIDKPUBC) m6hmac = hmac.digest() m6 = dict( a=base64.b64encode(n1).decode("utf-8"), d=base64.b64encode(wrappedDIDKPUBC).decode("utf-8"), e=base64.b64encode(m6hmac).decode("utf-8"), ) print("Registering device...") r = self.session.post(register_url, json=m6) print(r) print("Cleaning up...") r = self.session.put(register_cleanup_url) print(r) return ( cert.decode("utf-8"), new_key.exportKey("PEM").decode("utf-8"), selfDeviceId.decode("utf-8"), )