def opdata1_decrypt_master_key(data, key, hmac_key, aes_size=C_AES_SIZE, ignore_hmac=False): key_size = KEY_SIZE[aes_size] bare_key = opdata1_decrypt_item(data, key, hmac_key, aes_size=aes_size, ignore_hmac=ignore_hmac) # XXX: got the following step from jeff@agilebits (as opposed to the # docs anywhere) digest = Hash(SHA512(), backend=_backend) digest.update(bare_key) hashed_key = digest.finalize() return hashed_key[:key_size], hashed_key[key_size:]
def sha256(message): """Generates a SHA256 hash of a message""" if isinstance(message, str): message = bytes(message, encoding='utf-8') elif isinstance(message, bytearray): message = bytes(message) digest = Hash(SHA256(), backend=default_backend()) digest.update(message) return digest.finalize()
def compute_verify_data(self, basekey, handshake_context): hash_len = self.hash.digest_size finished_key = self.expand_label(basekey, b"finished", b"", hash_len) h = Hash(self.hash, backend=default_backend()) h.update(handshake_context) hash_value = h.finalize() hm = HMAC(finished_key, self.hash, default_backend()) hm.update(hash_value) return hm.finalize()
def _generate_property_iv(entity_iv, pk, rk, property_name, isJavaV1): ''' Uses the entity_iv, partition key, and row key to generate and return the iv for the specified property. ''' digest = Hash(SHA256(), default_backend()) if not isJavaV1: digest.update(entity_iv + (rk + pk + property_name).encode('utf-8')) else: digest.update(entity_iv + (pk + rk + property_name).encode('utf-8')) propertyIV = digest.finalize() return propertyIV[:16]
def a_decrypt_item(data, key, aes_size=A_AES_SIZE): key_size = KEY_SIZE[aes_size] if data[:len(SALT_MARKER)] == SALT_MARKER: salt = data[len(SALT_MARKER):len(SALT_MARKER) + SALT_SIZE] data = data[len(SALT_MARKER) + SALT_SIZE:] pb_gen = pbkdf1.PBKDF1(key, salt) nkey = pb_gen.read(key_size) iv = pb_gen.read(key_size) else: digest = Hash(MD5(), backend=_backend) digest.update(key) nkey = digest.finalize() iv = '\x00'*key_size aes = Cipher(algorithms.AES(nkey), modes.CBC(iv), backend=_backend) decryptor = aes.decryptor() return padding.pkcs5_unpad(decryptor.update(data) + decryptor.finalize())
def decrypt(secret, hash, data): """ Decrypt per telegram docs at https://core.telegram.org/passport. Args: secret (:obj:`str` or :obj:`bytes`): The encryption secret, either as bytes or as a base64 encoded string. hash (:obj:`str` or :obj:`bytes`): The hash, either as bytes or as a base64 encoded string. data (:obj:`str` or :obj:`bytes`): The data to decrypt, either as bytes or as a base64 encoded string. file (:obj:`bool`): Force data to be treated as raw data, instead of trying to b64decode it. Raises: :class:`TelegramDecryptionError`: Given hash does not match hash of decrypted data. Returns: :obj:`bytes`: The decrypted data as bytes. """ if not CRYPTO_INSTALLED: raise RuntimeError( 'To use Telegram Passports, PTB must be installed via `pip install ' 'python-telegram-bot[passport]`.') # Make a SHA512 hash of secret + update digest = Hash(SHA512(), backend=default_backend()) digest.update(secret + hash) secret_hash_hash = digest.finalize() # First 32 chars is our key, next 16 is the initialisation vector key, init_vector = secret_hash_hash[:32], secret_hash_hash[32:32 + 16] # Init a AES-CBC cipher and decrypt the data cipher = Cipher(AES(key), CBC(init_vector), backend=default_backend()) decryptor = cipher.decryptor() data = decryptor.update(data) + decryptor.finalize() # Calculate SHA256 hash of the decrypted data digest = Hash(SHA256(), backend=default_backend()) digest.update(data) data_hash = digest.finalize() # If the newly calculated hash did not match the one telegram gave us if data_hash != hash: # Raise a error that is caught inside telegram.PassportData and transformed into a warning raise TelegramDecryptionError( f"Hashes are not equal! {data_hash} != {hash}") # Return data without padding return data[data[0]:]
def create_token(self): a_token = { 'type': 'access_token', 'client': self.id, 'scope': self.scope, } token_ser = tokenserializer.dumps(a_token) h = Hash(SHA256(), default_backend()) h.update(token_ser.encode('utf-8')) self.token = h.finalize() db.session.add(self) db.session.commit() return token_ser
def _build_index(self): index = {} for path in get_git_files(self._repository): if (self._repository / path).is_file(): uuid = str(uuid4()) while index.get(uuid): uuid = str(uuid4()) hasher = Hash(BLAKE2b(64)) with open(self._repository / path, 'rb') as file: hasher.update(file.read()) index[str(path)] = { 'path': str(path), 'uuid': uuid, 'checksum': hasher.finalize().hex() } for path in (self._repository / '.git').glob('**/*'): if path.is_file(): uuid = str(uuid4()) while index.get(uuid): uuid = str(uuid4()) hasher = Hash(BLAKE2b(64)) with open(path, 'rb') as file: hasher.update(file.read()) short_path = path.relative_to(self._repository) index[str(short_path)] = { 'path': str(short_path), 'uuid': uuid, 'checksum': hasher.finalize().hex() } return index
def make_or_ciphers(key): backend = _default_backend Df = key[1] Db = key[2] Kf = key[3] Kb = key[4] initial_counter = "\x00" * 16 Dffunc = Hash(SHA1(), backend=backend) Dbfunc = Hash(SHA1(), backend=backend) Kffunc = Cipher(AES(Kf), modes.CTR(initial_counter), backend=_default_backend).encryptor() Kbfunc = Cipher(AES(Kb), modes.CTR(initial_counter), backend=_default_backend).encryptor() Dffunc.update(Df) Dbfunc.update(Db) return (Dffunc, Dbfunc, Kffunc, Kbfunc)
async def decrypt_stream( self, stream: AsyncIterator[bytes]) -> AsyncIterator[bytes]: decryptor = self._cipher.decryptor() # type: ignore assert isinstance(decryptor, CipherContext) digest = Hash(SHA256()) skip = None async for chunk in stream: decrypted = decryptor.update(chunk) digest.update(decrypted) if skip is None: skip = decrypted[0] if skip >= len(decrypted): skip = skip - len(decrypted) else: yield decrypted[skip:] skip = 0 decrypted = decryptor.finalize() digest.update(decrypted) computed_hash = digest.finalize() if not bytes_eq(computed_hash, self._data_hash): raise RuntimeError('Decryption error') yield decrypted[skip:]
def nc_kep(kep2, kep4) -> bool: """ Check that sha512(kep4[4:] = Kep2.kdf2 :param kep2: bytes, sent by the dsc :param kep4: bytes, sent by the dsc :return: bool """ validate_kep2("nc_kep", kep2) validate_kep4("nc_kep", kep4) kep0 = Hash(SHA512(), backend=default_backend()) kep0.update(kep4[4:]) kep0_out = kep0.finalize() left = kep0_out right = Kep2(kep2).kdf2 log.debug("nc_kep left : {}, {}".format(left.hex(), len(left.hex()))) log.debug("nc_kep right: {}, {}".format(right.hex(), len(right.hex()))) return left == right
def decrypt_encryption_key_fallback(self): """Decrypts the encryption key using the FALLBACK method. In this method, the context string, usually "CredEncryption" or "PSEEncryption", is encrypted using a derivation of a fixed key hardcoded in CommonCryptoLib, and used as key to encrypt the actual encryption key used in the file with the AES cipher. :return: Encryption key decrypted :rtype: string """ log_lps.debug("Obtaining encryption key with FALLBACK LPS mode") digest = Hash(SHA1(), backend=default_backend()) digest.update(cred_key_lps_fallback) hashed_key = digest.finalize() hmac = HMAC(hashed_key, SHA1(), backend=default_backend()) hmac.update(self.context) default_key = hmac.finalize()[:16] iv = "\x00" * 16 decryptor = Cipher(algorithms.AES(default_key), modes.CBC(iv), backend=default_backend()).decryptor() encryption_key = decryptor.update(self.encrypted_key) + decryptor.finalize() return encryption_key
def get_linekey(lineNum, userKey, fileKey): ''' Get line number specific key by hashing userkey, linenum and filekey ''' hasher = Hash(algorithm=SHA256(), backend=default_backend()) hasher.update(userKey) hasher.update(lineNum.to_bytes(4, 'little')) hasher.update(fileKey) key = base64.urlsafe_b64encode(hasher.finalize()) #print("linekey:{}:{}:{}={}".format(lineNum, userKey, fileKey, key), file=GERRFILE) return key
def derive(self, key_material): if not isinstance(key_material, bytes): raise TypeError("key_material must be bytes.") h = Hash(self._algorithm(), backend=self._backend) h.update(key_material) h.update(self._salt) derived_key = h.finalize() for i in xrange(self._iterations-1): h = Hash(self._algorithm(), backend=self._backend) h.update(derived_key) derived_key = h.finalize() return derived_key
def derive(self, key_material): if not isinstance(key_material, bytes): raise TypeError("key_material must be bytes.") h = Hash(self._algorithm(), backend=self._backend) h.update(key_material) h.update(self._salt) derived_key = h.finalize() for i in xrange(self._iterations - 1): h = Hash(self._algorithm(), backend=self._backend) h.update(derived_key) derived_key = h.finalize() return derived_key
def hash_password(password: str, salt: str) -> str: """ Generates the password hash for the given user :param password: The password to hash :param salt: The salt(base64) to use in hash :return: The password hash """ hash_ = Hash(SHA3_512()) hash_.update(password.encode('ascii') + b64decode(salt.encode('ascii'))) digest = hash_.finalize() hash_ = Hash(SHA3_512()) hash_.update(digest) digest = hash_.finalize() hash_ = Hash(SHA3_512()) hash_.update(digest + b64decode(salt.encode('ascii'))) digest = hash_.finalize() return b64encode(digest).decode('ascii')
def gen_key(key: bytes): digest = Hash(SHA256()) digest.update(key) hash_bytes = digest.finalize() return hash_bytes[:32]
KDF2_input = b'EAP-NOOB' + base64url_decode(Np2_b64) + base64url_decode(Ns2_b64) KDF2_out = KDF(algorithm=SHA256(), length=288, otherinfo=KDF2_input, backend=default_backend()).derive(Kz) Kms2 = KDF2_out[224:256] Kmp2 = KDF2_out[256:288] # Remove trailing '=' from base64 encoded values Np_b64 = Np_b64.strip('=') Ns_b64 = Ns_b64.strip('=') Np2_b64 = Np2_b64.strip('=') Ns2_b64 = Ns2_b64.strip('=') Noob_b64 = Noob_b64.strip('=') ## NoobId NoobId_input = Hash(SHA256(), backend=default_backend()) NoobId_input.update(b'NoobId') NoobId_input.update(Noob_b64.encode()) NoobId = NoobId_input.finalize()[:16] NoobId_b64 = base64url_encode(NoobId).decode().strip('=') ## Hoob Hoob_values = loads('{"Hoob":[]}', object_pairs_hook=OrderedDict) Hoob_values['Hoob'] = [Dir, Vers, Verp, PeerId, Cryptosuites, Dirs, loads(ServerInfo, object_pairs_hook=OrderedDict), Cryptosuitep, Dirp, Realm, loads(PeerInfo, object_pairs_hook=OrderedDict), 0, PKs_full, Ns_b64, PKp_full, Np_b64, Noob_b64] Hoob_input = Hash(SHA256(), backend=default_backend()) Hoob_input.update(dumps(Hoob_values['Hoob'], separators=(',', ':')).encode()) Hoob = Hoob_input.finalize()[:16] Hoob_b64 = base64url_encode(Hoob).decode().strip('=')
def sha256(bytes): digest = Hash(SHA256(), backend=default_backend()) digest.update(bytes) return digest.finalize()
def digest(inp): h = Hash(self._algorithm(), backend=self._backend) h.update(inp) return h.finalize()
def test_validate_encryption(self): # Arrange entity = self._create_default_entity_for_encryption() key_encryption_key = KeyWrapper('key1') self.ts.key_encryption_key = key_encryption_key self.ts.insert_entity(self.table_name, entity) # Act self.ts.key_encryption_key = None entity = self.ts.get_entity(self.table_name, entity['PartitionKey'], entity['RowKey']) # Note the minor discrepancy from the normal decryption process: because the entity was retrieved # without being decrypted, the encrypted_properties list is now stored in an EntityProperty object # and is already raw bytes. encrypted_properties_list = entity['_ClientEncryptionMetadata2'].value encryption_data = entity['_ClientEncryptionMetadata1'] encryption_data = _dict_to_encryption_data(loads(encryption_data)) content_encryption_key = key_encryption_key.unwrap_key(encryption_data.wrapped_content_key.encrypted_key, encryption_data.wrapped_content_key.algorithm) digest = Hash(SHA256(), default_backend()) digest.update(encryption_data.content_encryption_IV + (entity['RowKey'] + entity['PartitionKey'] + '_ClientEncryptionMetadata2').encode('utf-8')) metadataIV = digest.finalize() metadataIV = metadataIV[:16] cipher = _generate_AES_CBC_cipher(content_encryption_key, metadataIV) # Decrypt the data. decryptor = cipher.decryptor() encrypted_properties_list = decryptor.update(encrypted_properties_list) + decryptor.finalize() # Unpad the data. unpadder = PKCS7(128).unpadder() encrypted_properties_list = unpadder.update(encrypted_properties_list) + unpadder.finalize() encrypted_properties_list = encrypted_properties_list.decode('utf-8') # Strip the square braces from the ends and split string into list. encrypted_properties_list = loads(encrypted_properties_list) entity_iv, encrypted_properties, content_encryption_key = \ (encryption_data.content_encryption_IV, encrypted_properties_list, content_encryption_key) decrypted_entity = deepcopy(entity) for property in encrypted_properties_list: value = entity[property] digest = Hash(SHA256(), default_backend()) digest.update(entity_iv + (entity['RowKey'] + entity['PartitionKey'] + property).encode('utf-8')) propertyIV = digest.finalize() propertyIV = propertyIV[:16] cipher = _generate_AES_CBC_cipher(content_encryption_key, propertyIV) # Decrypt the property. decryptor = cipher.decryptor() decrypted_data = (decryptor.update(value.value) + decryptor.finalize()) # Unpad the data. unpadder = PKCS7(128).unpadder() decrypted_data = (unpadder.update(decrypted_data) + unpadder.finalize()) decrypted_data = decrypted_data.decode('utf-8') decrypted_entity[property] = decrypted_data decrypted_entity.pop('_ClientEncryptionMetadata1') decrypted_entity.pop('_ClientEncryptionMetadata2') # Assert self.assertEqual(decrypted_entity['sex'], 'male')
def sha256(data): hash = Hash(SHA256()) hash.update(data) return hash.finalize().hex()
def sha256(data: bytes) -> bytes: digest = Hash(SHA256()) digest.update(data) return digest.finalize()
def derive_secret(self, secret, label, messages): h = Hash(self.hash, backend=default_backend()) h.update(messages) hash_messages = h.finalize() hash_len = self.hash.digest_size return self.expand_label(secret, label, hash_messages, hash_len)
def gen_nonce_from_timestamp(timestamp: int): digest = Hash(SHA256()) digest.update(str(timestamp).encode("utf-8")) hash_bytes = digest.finalize() return hash_bytes[:12]
def sha1_hash(data): sha = Hash(SHA1(), backend) sha.update(data) return sha.finalize()
def sign(msg): digest = Hash(SHA512(), backend=default_backend()) digest.update(msg.encode()) signingdata = int.from_bytes(digest.finalize(), "big") return pow(signingdata, key.d, key.public_numbers.n)
def sha256(bytestr): hash = Hash(SHA256, DEFAULT_BACKEND) hash.update(bytestr) hash = hash.finalize() return hash
def generate() -> "SessionKey": rs = os.urandom(SessionKey._hash_algo.digest_size) h = Hash(SessionKey._hash_algo(), backend=default_backend()) h.update(rs) return SessionKey(h.finalize())
def setup_hmac_aes(salt, password): hash = Hash(SHA256(), default_backend()) hash.update(salt + bytes(password, 'ascii')) hmac = HMAC(hash.finalize()[16:], SHA256(), default_backend()) return hmac
def sm3(data): hash = Hash(SM3()) hash.update(data) return hash.finalize().hex()
def sha1(msg): sha = Hash(SHA1(), backend=bend) sha.update(msg) return sha.finalize()
def _get_digest(self, data, digest_algorithm): hasher = Hash(algorithm=digest_algorithm, backend=default_backend()) hasher.update(data) return ensure_str(b64encode(hasher.finalize()))
def derive_keyhash_v1(password, salt, iterations): derived_key = derive_key_v1(password, salt, iterations) hf = Hash(SHA256(), backend=_CRYPTO_BACKEND) hf.update(derived_key) return hf.finalize()
class ntor(object): def __init__(self, node): # 5.1.4. The "ntor" handshake # This handshake uses a set of DH handshakes to compute a set of # shared keys which the client knows are shared only with a particular # server, and the server knows are shared with whomever sent the # original handshake (or with nobody at all). Here we use the # "curve25519" group and representation as specified in "Curve25519: # new Diffie-Hellman speed records" by D. J. Bernstein. # [The ntor handshake was added in Tor 0.2.4.8-alpha.] self.node = node # In this section, define: # H(x,t) as HMAC_SHA256 with message x and key t. # H_LENGTH = 32. # ID_LENGTH = 20. # G_LENGTH = 32 # PROTOID = "ntor-curve25519-sha256-1" # t_mac = PROTOID | ":mac" # t_key = PROTOID | ":key_extract" # t_verify = PROTOID | ":verify" # MULT(a,b) = the multiplication of the curve25519 point 'a' by the # scalar 'b'. # G = The preferred base point for curve25519 ([9]) # KEYGEN() = The curve25519 key generation algorithm, returning # a private/public keypair. # m_expand = PROTOID | ":key_expand" # H is defined as hmac() # MULT is included in the curve25519 library as get_shared_key() # KEYGEN() is curve25519.Private() self.protoid = 'ntor-curve25519-sha256-1' self.t_mac = self.protoid + ':mac' self.t_key = self.protoid + ':key_extract' self.t_verify = self.protoid + ':verify' self.m_expand = self.protoid + ':key_expand' # To perform the handshake, the client needs to know an identity key # digest for the server, and an ntor onion key (a curve25519 public # key) for that server. Call the ntor onion key "B". The client # generates a temporary keypair: # x,X = KEYGEN() self.x = curve25519.Private() self.X = self.x.get_public() self.B = curve25519.Public(b64decode(self.node['ntor-onion-key'])) # and generates a client-side handshake with contents: # NODEID Server identity digest [ID_LENGTH bytes] # KEYID KEYID(B) [H_LENGTH bytes] # CLIENT_PK X [G_LENGTH bytes] self.handshake = b64decode(self.node['identity']) self.handshake += self.B.serialize() self.handshake += self.X.serialize() def complete_handshake(self, Y, auth): # The server's handshake reply is: # SERVER_PK Y [G_LENGTH bytes] # AUTH H(auth_input, t_mac) [H_LENGTH bytes] # The client then checks Y is in G^* [see NOTE below], and computes # secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID si = self.x.get_shared_key(curve25519.Public(Y), hash_func) si += self.x.get_shared_key(self.B, hash_func) si += b64decode(self.node['identity']) si += self.B.serialize() si += self.X.serialize() si += Y si += 'ntor-curve25519-sha256-1' # KEY_SEED = H(secret_input, t_key) # verify = H(secret_input, t_verify) key_seed = hmac(self.t_key, si) verify = hmac(self.t_verify, si) # auth_input = verify | ID | B | Y | X | PROTOID | "Server" ai = verify ai += b64decode(self.node['identity']) ai += self.B.serialize() ai += Y ai += self.X.serialize() ai += self.protoid ai += 'Server' # The client verifies that AUTH == H(auth_input, t_mac). if auth != hmac(self.t_mac, ai): raise NtorError('auth input does not match.') # Both parties check that none of the EXP() operations produced the # point at infinity. [NOTE: This is an adequate replacement for # checking Y for group membership, if the group is curve25519.] # Both parties now have a shared value for KEY_SEED. They expand this # into the keys needed for the Tor relay protocol, using the KDF # described in 5.2.2 and the tag m_expand. # 5.2.2. KDF-RFC5869 # For newer KDF needs, Tor uses the key derivation function HKDF from # RFC5869, instantiated with SHA256. (This is due to a construction # from Krawczyk.) The generated key material is: # K = K_1 | K_2 | K_3 | ... # Where H(x,t) is HMAC_SHA256 with value x and key t # and K_1 = H(m_expand | INT8(1) , KEY_SEED ) # and K_(i+1) = H(K_i | m_expand | INT8(i+1) , KEY_SEED ) # and m_expand is an arbitrarily chosen value, # and INT8(i) is a octet with the value "i". # In RFC5869's vocabulary, this is HKDF-SHA256 with info == m_expand, # salt == t_key, and IKM == secret_input. keys = hkdf(key_seed, length=72, info=self.m_expand) # When used in the ntor handshake, the first HASH_LEN bytes form the # forward digest Df; the next HASH_LEN form the backward digest Db; the # next KEY_LEN form Kf, the next KEY_LEN form Kb, and the final # DIGEST_LEN bytes are taken as a nonce to use in the place of KH in the # hidden service protocol. Excess bytes from K are discarded. Df, Db, Kf, Kb = struct.unpack('>20s20s16s16s', keys) # we do what we can with what we've got. del self.X del self.x del self.B del key_seed del keys del verify del ai del auth del si del Y self.send_digest = Hash(SHA1(), backend=bend) self.send_digest.update(Df) self.recv_digest = Hash(SHA1(), backend=bend) self.recv_digest.update(Db) self.encrypt = Cipher(AES(Kf), CTR('\x00' * 16), backend=bend).encryptor() self.decrypt = Cipher(AES(Kb), CTR('\x00' * 16), backend=bend).decryptor() def get_handshake(self): return self.handshake
def sha_256(ctx, input, output, status): digest = Hash(SHA256(), backend=default_backend()) digest.update(_to_bytes(input)) data = digest.finalize() _write_bytes(output, data) return True
def nc_kdf(shared_secret, kep2, kep3) -> list: """ Return a list of results from the kdf procedure. :param shared_secret: bytes :param kep2: bytes, sent by the dsc :param kep3: bytes, sent by the adv :return: list of results Kep2 might be containied in a single payload together with Kep1. Interesting return values: rv[6] = cli2ser_key: dsc (encrypt) --> adv (decrypt) rv[8] = ser2cli_key: adv (encrypt) --> dsc (decrypt) rv[9] = auth token """ validate_shared_secret("nc_kdf", shared_secret) validate_kep2("nc_kdf", kep2) validate_kep3("nc_kdf", kep3) rv = [] kdf1 = Hash(SHA256(), backend=default_backend()) kdf1.update(shared_secret) kdf1_out = kdf1.finalize() # log.debug("nc_kdf kdf1_out: {}, {}".format(kdf1_out, type(kdf1_out))) rv.append(kdf1_out) kdf2 = HMAC(NC_STR_UKEY2v1auth, SHA256(), backend=default_backend()) kdf2.update(kdf1_out) kdf2_out = kdf2.finalize() # log.debug("nc_kdf kdf2_out: {}, {}".format(kdf2_out, type(kdf2_out))) rv.append(kdf2_out) kdf3 = HMAC(kdf2_out, SHA256(), backend=default_backend()) kdf3_inp_hex = kep2[4:].hex() + kep3[4:].hex() # log.debug("nc_kdf kdf3_inp_hex: {}, {}".format(kdf3_inp_hex, len(kdf3_inp_hex))) kdf3_inp = unhexlify(kdf3_inp_hex) # NOTE: heuristic assert len(kdf3_inp) == 252 or len(kdf3_inp) == 253 or len(kdf3_inp) == 254 kdf3.update(kdf3_inp) kdf3.update(b'\x01') kdf3_out = kdf3.finalize() # log.debug("nc_kdf kdf3_out: {}, {}".format(kdf3_out, type(kdf3_out))) rv.append(kdf3_out) kdf4 = HMAC(NC_STR_UKEY2v1next, SHA256(), backend=default_backend()) kdf4.update(kdf1_out) kdf4_out = kdf4.finalize() # log.debug("nc_kdf kdf4_out: {}, {}".format(kdf4_out, type(kdf4_out))) rv.append(kdf4_out) # NOTE: same inputs of kdf3 kdf5 = HMAC(kdf4_out, SHA256(), backend=default_backend()) kdf5.update(kdf3_inp) kdf5.update(b'\x01') kdf5_out = kdf5.finalize() # log.debug("nc_kdf kdf5_out: {}, {}".format(kdf5_out, type(kdf5_out))) rv.append(kdf5_out) kdf6 = HMAC(NC_KDF_KEY, SHA256(), backend=default_backend()) kdf6.update(kdf5_out) kdf6_out = kdf6.finalize() # log.debug("nc_kdf kdf6_out: {}, {}".format(kdf6_out, type(kdf6_out))) rv.append(kdf6_out) # NOTE: computes cli2ser_key kdf7 = HMAC(kdf6_out, SHA256(), backend=default_backend()) kdf7.update(NC_STR_CLIENT) kdf7.update(b'\x01') kdf7_out = kdf7.finalize() # log.debug("nc_kdf kdf7_out: {}, {}".format(kdf7_out, type(kdf7_out))) cli2ser_key = kdf7_out log.debug("nc_kdf cli2ser_key: {}, {}".format(kdf7_out, len(kdf7_out))) rv.append(kdf7_out) # NOTE: same as kdf6 kdf8 = HMAC(NC_KDF_KEY, SHA256(), backend=default_backend()) kdf8.update(kdf5_out) kdf8_out = kdf8.finalize() # log.debug("nc_kdf kdf8_out: {}, {}".format(kdf8_out, type(kdf8_out))) rv.append(kdf8_out) # NOTE: computes ser2cli_key kdf9 = HMAC(kdf8_out, SHA256(), backend=default_backend()) kdf9.update(NC_STR_SERVER) kdf9.update(b'\x01') kdf9_out = kdf9.finalize() # log.debug("nc_kdf kdf9_out: {}, {}".format(kdf9_out, type(kdf9_out))) ser2cli_key = kdf9_out log.debug("nc_kdf ser2cli_key: {}, {}".format(kdf9_out, len(kdf9_out))) rv.append(kdf9_out) # NOTE: computes auth token from kdf3_out r_auth_token = b64encode(kdf3_out)[:5] auth_token = r_auth_token.decode('utf-8').upper() assert len(auth_token) == 5 log.debug("nc_kdf auth_token: {}, {}".format(auth_token, len(auth_token))) rv.append(auth_token) return rv
length=288, otherinfo=KDF2_input, backend=default_backend()).derive(Kz) Kms2 = KDF2_out[224:256] Kmp2 = KDF2_out[256:288] # Remove trailing '=' from base64 encoded values Np_b64 = Np_b64.strip('=') Ns_b64 = Ns_b64.strip('=') Np2_b64 = Np2_b64.strip('=') Ns2_b64 = Ns2_b64.strip('=') Noob_b64 = Noob_b64.strip('=') ## NoobId NoobId_input = Hash(SHA256(), backend=default_backend()) NoobId_input.update(b'NoobId') NoobId_input.update(Noob_b64.encode()) NoobId = NoobId_input.finalize()[:16] NoobId_b64 = base64url_encode(NoobId).decode().strip('=') ## Hoob Hoob_values = loads('{"Hoob":[]}', object_pairs_hook=OrderedDict) Hoob_values['Hoob'] = [ Dir, Vers, Verp, PeerId, Cryptosuites, Dirs, loads(ServerInfo, object_pairs_hook=OrderedDict), Cryptosuitep, Dirp, Realm, loads(PeerInfo, object_pairs_hook=OrderedDict), PKs_full, Ns_b64, PKp_full, Np_b64, Noob_b64 ] Hoob_input = Hash(SHA256(), backend=default_backend()) Hoob_input.update(dumps(Hoob_values['Hoob'], separators=(',', ':')).encode())
def nc_scapy_pkt(pt_type, fields) -> bytes: """ Generates NC scapy packets, :param pt_type: string in NC_PT_TYPES :param fields: list content depends on pt_type :return: scapy packet kep1 fields: fields[0]: eid, str fields[1]: ncname, str fields[2]: strategy, str fields[3]: wifi_mode, str kep4 fields: fields[0]: pri_key, bytes fields[1]: pub_key, tuple of bytes kep2 fields: fields[0]: kep4, bytes kep3 fields: fields[0]: pri_key, bytes fields[1]: pub_key, tuple of bytes eka fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int ewl fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int fields[3]: ip, list fields[4]: tcp_port, bytes eha fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int fields[3]: essid, bytes, 28 or DIRECT- fields[4]: password, bytes, 12 or 8 fields[5]: tcp_port, bytes, 3 esh fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int esh2 fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int pay fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int fields[3]: pt, bytes fields[4]: pid, bytes pay2 fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int fields[3]: pay_len, int fields[4]: pid, bytes iw fields: fields[0]: key, bytes fields[1]: iv, bytes fields[2]: count, int fields[3]: eid, str """ validate_pt_type("nc_scapy_pkt", pt_type) rv = b'' if pt_type == 'kep1': eid = fields[0] validate_str('nc_scapy_pkt kep1', eid) ncname = fields[1] validate_str('nc_scapy_pkt kep1', ncname) strategy = fields[2] validate_strategy('nc_scapy_pkt kep1', strategy) wifi_mode = fields[3] validate_wifi_mode('nc_scapy_pkt kep1', wifi_mode) # NOTE: use only latest version if strategy == 'P2P_STAR': if wifi_mode == 'hostapd': kep1_scapy = SCAPY_KEP1_STAR_HA_TEMPLATE elif wifi_mode == 'direct': kep1_scapy = SCAPY_KEP1_STAR_WD_TEMPLATE elif strategy == 'P2P_CLUSTER': kep1_scapy = SCAPY_KEP1_CLUS_TEMPLATE kep1_scapy.eid = eid kep1_scapy.ncname = ncname # NOTE: 4 depends on SCAPY_KEP1_TEMPLATE if len(ncname) != 4: delta = 4 - len(ncname) kep1_scapy.ncname_len = len(ncname) kep1_scapy.len1 -= delta kep1_scapy.len2 -= delta kep1_scapy.len3 -= delta # log.debug("nc_scapy_pkt kep1: {}".format(repr(kep1_scapy))) # log.debug("nc_scapy_pkt kep1_scapy.name: {}".format(kep1_scapy.name)) rv = kep1_scapy elif pt_type == 'kep4': pri_key = fields[0] validate_pri_key('nc_scapy_pkt kep4', pri_key) pub_key = None pub_key = fields[1] if pub_key is not None: validate_pub_key('nc_scapy_pkt kep4', pub_key) # NOTE: not validating if it is in the curve else: pri_key_int = bytes_to_int(pri_key) pub_key_int = scalar_mult(pri_key_int, (EC_XG_INT, EC_YG_INT)) pub_key = (int_to_bytes(pub_key_int[0]), int_to_bytes(pub_key_int[1])) validate_point('nc_scapy_pkt kep4', pub_key) xD = pub_key[0] yD = pub_key[1] # NOTE: preprend \x00 if coordinate starts with 0b1 if bin(xD[0]).startswith('0b1'): xD = b'\x00' + xD if bin(yD[0]).startswith('0b1'): yD = b'\x00' + yD kep4_scapy = SCAPY_KEP4_TEMPLATE # NOTE: 32 depends on the SCAPY_KEP4_TEMPLATE delta = 32 - len(xD) + 32 - len(yD) kep4_scapy.len1 -= delta kep4_scapy.len2 -= delta kep4_scapy.len3 -= delta kep4_scapy.len4 -= delta kep4_scapy.xD = xD kep4_scapy.xD_len = len(xD) kep4_scapy.yD = yD kep4_scapy.yD_len = len(yD) # log.debug("nc_scapy_pkt kep4_hex: {}".format(raw(kep4_scapy).hex())) rv = kep4_scapy # NOTE: so far passing constant kdf1 and kdf2 elif pt_type == 'kep2': kep4 = fields[0] validate_bytes('nc_scapy_pkt kep2', kep4) kep2_scapy = SCAPY_KEP2_TEMPLATE kep0 = Hash(SHA512(), backend=default_backend()) kep0.update(kep4[4:]) kep2_kdf2 = kep0.finalize() kep2_scapy.kdf2 = kep2_kdf2 rv = kep2_scapy elif pt_type == 'kep3': pri_key = fields[0] validate_pri_key('nc_scapy_pkt kep3', pri_key) pub_key = None pub_key = fields[1] # NOTE: if fields[1] contains a pub_key if pub_key is not None: validate_pub_key('nc_scapy_pkt kep3', pub_key) # NOTE: not validating if it is in the curve else: pri_key_int = bytes_to_int(pri_key) pub_key_int = scalar_mult(pri_key_int, (EC_XG_INT, EC_YG_INT)) pub_key = (int_to_bytes(pub_key_int[0]), int_to_bytes(pub_key_int[1])) validate_point('nc_scapy_pkt kep3', pub_key) xA = pub_key[0] yA = pub_key[1] # NOTE: preprend \x00 if coordinate starts with 0b1 if bin(xA[0]).startswith('0b1'): xA = b'\x00' + xA if bin(yA[0]).startswith('0b1'): yA = b'\x00' + yA # NOTE: kdf field is kept constant so far kep3_scapy = SCAPY_KEP3_TEMPLATE # NOTE: 32 depends on the SCAPY_KEP3_TEMPLATE delta = 32 - len(xA) + 32 - len(yA) kep3_scapy.len1 -= delta kep3_scapy.len2 -= delta kep3_scapy.len3 -= delta kep3_scapy.len4 -= delta kep3_scapy.xA = xA kep3_scapy.xA_len = len(xA) kep3_scapy.yA = yA kep3_scapy.yA_len = len(yA) # log.debug("nc_scapy_pkt kep3_hex: {}".format(raw(kep3_scapy).hex())) rv = kep3_scapy elif pt_type == 'eka': key = fields[0] validate_aes256_key("nc_scapy_pkt eka", key) iv = fields[1] validate_iv("nc_scapy_pkt eka", iv) count = fields[2] validate_int("nc_scapy_pkt eka", count) pt_scapy = SCAPY_KA_TEMPLATE pt_scapy.count = count pt = raw(pt_scapy) # log.debug("nc_scapy_pkt eka pt_hex: {} {}, count {}".format(pt.hex(), # len(pt.hex()), count)) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] eka_scapy = SCAPY_EKA_TEMPLATE eka_scapy.iv = iv eka_scapy.ct = ct eka_scapy.mac = mac rv = eka_scapy elif pt_type == 'ewl': key = fields[0] validate_aes256_key("nc_scapy_pkt ewl", key) iv = fields[1] validate_iv("nc_scapy_pkt ewl", iv) count = fields[2] validate_int("nc_scapy_pkt ewl", count) ip = fields[3] validate_ip("nc_scapy_pkt ewl", ip) wl_scapy = SCAPY_WL_TEMPLATE wl_scapy.count = count wl_scapy.ip = ip if fields[4] == None: # NOTE: use the tcp_port from the template pass else: tcp_port = fields[4] validate_tcp_port("nc_scapy_pkt ewl", tcp_port) wl_scapy.tcp_port = tcp_port pt = raw(wl_scapy) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] # NOTE: similar to eka_scapy ewl_scapy = SCAPY_EWL_TEMPLATE ewl_scapy.iv = iv ewl_scapy.ct = ct ewl_scapy.mac = mac rv = ewl_scapy elif pt_type == 'eha': key = fields[0] validate_aes256_key("nc_scapy_pkt eha", key) iv = fields[1] validate_iv("nc_scapy_pkt eha", iv) count = fields[2] validate_int("nc_scapy_pkt eha", count) essid = fields[3] validate_essid("nc_scapy_pkt eha", essid) password = fields[4] validate_password("nc_scapy_pkt eha", password) ha_scapy = SCAPY_HA_TEMPLATE ha_scapy.count = count ha_scapy.essid = essid ha_scapy.password = password if fields[5] == None: # NOTE: use the tcp_port from the template pass else: tcp_port = fields[5] validate_tcp_port("nc_scapy_pkt eha", tcp_port) ha_scapy.tcp_port = tcp_port pt = raw(ha_scapy) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] # NOTE: similar to eka_scapy eha_scapy = SCAPY_EHA_TEMPLATE eha_scapy.iv = iv eha_scapy.ct = ct eha_scapy.mac = mac rv = eha_scapy elif pt_type == 'esh': key = fields[0] validate_aes256_key("nc_scapy_pkt esh", key) iv = fields[1] validate_iv("nc_scapy_pkt esh", iv) count = fields[2] validate_int("nc_scapy_pkt esh", count) sh_scapy = SCAPY_SH_TEMPLATE sh_scapy.count = count pt = raw(sh_scapy) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] esh_scapy = SCAPY_EKA_TEMPLATE esh_scapy.iv = iv esh_scapy.ct = ct esh_scapy.mac = mac rv = esh_scapy elif pt_type == 'esh2': key = fields[0] validate_aes256_key("nc_scapy_pkt esh2", key) iv = fields[1] validate_iv("nc_scapy_pkt esh2", iv) count = fields[2] validate_int("nc_scapy_pkt esh2", count) sh2_scapy = SCAPY_SH2_TEMPLATE sh2_scapy.count = count pt = raw(sh2_scapy) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] esh2_scapy = SCAPY_EKA_TEMPLATE esh2_scapy.iv = iv esh2_scapy.ct = ct esh2_scapy.mac = mac rv = esh2_scapy elif pt_type == 'pay': key = fields[0] validate_aes256_key("nc_scapy_pkt pay", key) iv = fields[1] validate_iv("nc_scapy_pkt pay", iv) count = fields[2] validate_int("nc_scapy_pkt pay", count) pay = fields[3] validate_bytes("nc_scapy_pkt pay", pay) # pid = fields[4] # validate_bytes("nc_scapy_pkt pay", pid) # NOTE: uses Pt class pt_scapy = SCAPY_PT_TEMPLATE # NOTE: 4 depends on SCAPY_PT_TEMPLATE if len(pay) != 4: delta = 4 - len(pay) pt_scapy.len1 -= delta pt_scapy.len2 -= delta pt_scapy.len3 -= delta pt_scapy.pt_len = len(pay) pt_scapy.len4 -= delta pt_scapy.pay_len = len(pay) pt_scapy.pay = pay pt_scapy.count = count # log.debug("nc_scapy_pkt pt: {}".format(repr(pt_scapy))) pt = raw(pt_scapy) log.debug("nc_scapy_pkt pt_hex: {}".format(pt.hex())) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] # NOTE: len fields should not be affected by len(Pt) pay_scapy = SCAPY_PAY_TEMPLATE pay_scapy.iv = iv pay_scapy.ct = ct pay_scapy.mac = mac rv = pay_scapy elif pt_type == 'pay2': key = fields[0] validate_aes256_key("nc_scapy_pkt pay2", key) iv = fields[1] validate_iv("nc_scapy_pkt pay2", iv) count = fields[2] validate_int("nc_scapy_pkt pay2", count) pay_len = fields[3] # this is the len of Pt (not Pt2) validate_int("nc_scapy_pkt pay2", pay_len) # pid = fields[4] # validate_bytes("nc_scapy_pkt pay2", pid) # NOTE: uses Pt2 class pt2_scapy = SCAPY_PT2_TEMPLATE if pay_len != 4: delta = 4 - pay_len pt2_scapy.pt_len = pay_len pt2_scapy.pt_len2 = pay_len pt2_scapy.count = count # log.debug("nc_scapy_pkt pt2: {}".format(repr(pt2_scapy))) pt = raw(pt2_scapy) log.debug("nc_scapy_pkt pt2_hex: {}".format(pt.hex())) # log.debug("nc_scapy_pkt pay pt_hex: {} {}, count {}".format(pt.hex(), # len(pt.hex()), count)) ct = nc_encrypt(key, pt, iv)[2] mac = nc_mac(key, ct, iv, pt_type)[2] pay2_scapy = SCAPY_PAY2_TEMPLATE pay2_scapy.iv = iv pay2_scapy.ct = ct pay2_scapy.mac = mac rv = pay2_scapy # NOTE: not encrypted, key and iv not used elif pt_type == 'iw': key = fields[0] validate_aes256_key("nc_scapy_pkt iw", key) iv = fields[1] validate_iv("nc_scapy_pkt iw", iv) count = fields[2] validate_int("nc_scapy_pkt iw", count) eid = eid[2] validate_str("nc_scapy_pkt iw", eid) iw_scapy = SCAPY_IW_TEMPLATE iw_scapy.count = count iw_scapy.eid = eid pt = raw(iw_scapy) # log.debug("nc_scapy_pkt iw pt_hex: {} {}, count {}".format(pt.hex(), # len(pt.hex()), count)) rv = iw_scapy else: log.error('nc_scapy_pkt: pt_type {} not managed.'.format(pt_type)) return rv