def derive(self, key_material): utils._check_byteslike("key_material", key_material) if self._used: raise AlreadyFinalized self._used = True return self._expand(key_material)
def _check_params(self, nonce: bytes, data: bytes, associated_data: bytes) -> None: utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if len(nonce) != 12: raise ValueError("Nonce must be 12 bytes")
def _check_params(self, nonce: bytes, data: bytes, associated_data: bytes) -> None: utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if not 7 <= len(nonce) <= 13: raise ValueError("Nonce must be between 7 and 13 bytes")
def __init__(self, tweak): utils._check_byteslike("tweak", tweak) if len(tweak) != 16: raise ValueError("tweak must be 128-bits (16 bytes)") self._tweak = tweak
def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized utils._check_byteslike("key_material", key_material) self._used = True # inverse floor division (equivalent to ceiling) rounds = -(-self._length // self._algorithm.digest_size) output = [b""] # For counter mode, the number of iterations shall not be # larger than 2^r-1, where r <= 32 is the binary length of the counter # This ensures that the counter values used as an input to the # PRF will not repeat during a particular call to the KDF function. r_bin = utils.int_to_bytes(1, self._rlen) if rounds > pow(2, len(r_bin) * 8) - 1: raise ValueError("There are too many iterations.") for i in range(1, rounds + 1): h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) counter = utils.int_to_bytes(i, self._rlen) if self._location == CounterLocation.BeforeFixed: h.update(counter) h.update(self._generate_fixed_input()) if self._location == CounterLocation.AfterFixed: h.update(counter) output.append(h.finalize()) return b"".join(output)[:self._length]
def derive(self, key_material: bytes) -> bytes: utils._check_byteslike("key_material", key_material) if self._used: raise AlreadyFinalized self._used = True return self._expand(key_material)
def _check_params(self, nonce: bytes, data: bytes, associated_data: bytes) -> None: utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if len(nonce) < 8 or len(nonce) > 128: raise ValueError("Nonce must be between 8 and 128 bytes")
def derive(self, key_material): if self._used: raise AlreadyFinalized utils._check_byteslike("key_material", key_material) self._used = True # inverse floor division (equivalent to ceiling) rounds = -(-self._length // self._algorithm.digest_size) output = [b''] # For counter mode, the number of iterations shall not be # larger than 2^r-1, where r <= 32 is the binary length of the counter # This ensures that the counter values used as an input to the # PRF will not repeat during a particular call to the KDF function. r_bin = utils.int_to_bytes(1, self._rlen) if rounds > pow(2, len(r_bin) * 8) - 1: raise ValueError('There are too many iterations.') for i in range(1, rounds + 1): h = hmac.HMAC(key_material, self._algorithm, backend=self._backend) counter = utils.int_to_bytes(i, self._rlen) if self._location == CounterLocation.BeforeFixed: h.update(counter) h.update(self._generate_fixed_input()) if self._location == CounterLocation.AfterFixed: h.update(counter) output.append(h.finalize()) return b''.join(output)[:self._length]
def __init__(self, key, nonce): self.key = _verify_key_size(self, key) utils._check_byteslike("nonce", nonce) if len(nonce) != 16: raise ValueError("nonce must be 128-bits (16 bytes)") self._nonce = nonce
def derive(self, key_material): if self._used: raise AlreadyFinalized("Scrypt instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) return self._backend.derive_scrypt(key_material, self._salt, self._length, self._n, self._r, self._p)
def _verify_key_size(algorithm, key): # Verify that the key is instance of bytes utils._check_byteslike("key", key) # Verify that the key size matches the expected key size if len(key) * 8 not in algorithm.key_sizes: raise ValueError("Invalid key size ({}) for {}.".format( len(key) * 8, algorithm.name)) return key
def derive(self, key_material): if self._used: raise AlreadyFinalized("Scrypt instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) return self._backend.derive_scrypt( key_material, self._salt, self._length, self._n, self._r, self._p )
def derive(self, key_material): if self._used: raise AlreadyFinalized("PBKDF2 instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) return self._backend.derive_pbkdf2_hmac(self._algorithm, self._length, self._salt, self._iterations, key_material)
def _verify_key_size(algorithm, key): # Verify that the key is instance of bytes utils._check_byteslike("key", key) # Verify that the key size matches the expected key size if len(key) * 8 not in algorithm.key_sizes: raise ValueError("Invalid key size ({0}) for {1}.".format( len(key) * 8, algorithm.name )) return key
def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized("Scrypt instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) from cryptography.hazmat.backends.openssl.backend import backend return backend.derive_scrypt(key_material, self._salt, self._length, self._n, self._r, self._p)
def __init__(self, key): if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "ChaCha20Poly1305 is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER) utils._check_byteslike("key", key) if len(key) != 32: raise ValueError("ChaCha20Poly1305 key must be 32 bytes.") self._key = key
def __init__(self, key: bytes): utils._check_byteslike("key", key) if len(key) not in (32, 48, 64): raise ValueError("AESSIV key must be 256, 384, or 512 bits.") self._key = key if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "AES-SIV is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER, )
def __init__(self, key): if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "ChaCha20Poly1305 is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER ) utils._check_byteslike("key", key) if len(key) != 32: raise ValueError("ChaCha20Poly1305 key must be 32 bytes.") self._key = key
def __init__(self, key: bytes): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESOCB3 key must be 128, 192, or 256 bits.") self._key = key if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "OCB3 is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER, )
def derive(self, key_material): if self._used: raise AlreadyFinalized("PBKDF2 instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) return self._backend.derive_pbkdf2_hmac( self._algorithm, self._length, self._salt, self._iterations, key_material )
def __init__(self, key, tag_length=16): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESCCM key must be 128, 192, or 256 bits.") self._key = key if not isinstance(tag_length, int): raise TypeError("tag_length must be an integer") if tag_length not in (4, 6, 8, 10, 12, 14, 16): raise ValueError("Invalid tag_length") self._tag_length = tag_length
def _byte_unpadding_update(buffer_, data, block_size): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) buffer_ += bytes(data) finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) result = buffer_[:finished_blocks * (block_size // 8)] buffer_ = buffer_[finished_blocks * (block_size // 8):] return buffer_, result
def _byte_padding_update(buffer_: typing.Optional[bytes], data: bytes, block_size: int): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) buffer_ += bytes(data) finished_blocks = len(buffer_) // (block_size // 8) result = buffer_[:finished_blocks * (block_size // 8)] buffer_ = buffer_[finished_blocks * (block_size // 8):] return buffer_, result
def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized("PBKDF2 instances can only be used once.") self._used = True utils._check_byteslike("key_material", key_material) from cryptography.hazmat.backends.openssl.backend import backend return backend.derive_pbkdf2_hmac( self._algorithm, self._length, self._salt, self._iterations, key_material, )
def _concatkdf_derive(key_material, length, auxfn, otherinfo): utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while (length > outlen): h = auxfn() h.update_user(_int_to_u32be(counter)) h.update_user(key_material) h.update_user(otherinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:length]
def _concatkdf_derive(key_material, length, auxfn, otherinfo): utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while (length > outlen): h = auxfn() h.update(_int_to_u32be(counter)) h.update(key_material) h.update(otherinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:length]
def _byte_unpadding_update(buffer_, data, block_size): if buffer_ is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior # of future's newbytes type. Unconditionally call bytes() after Python 2 # support is gone. buffer_ += data if isinstance(data, bytes) else bytes(data) finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) result = buffer_[:finished_blocks * (block_size // 8)] buffer_ = buffer_[finished_blocks * (block_size // 8):] return buffer_, result
def __init__(self, key, tag_length=16): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESCCM key must be 128, 192, or 256 bits.") self._key = key if not isinstance(tag_length, int): raise TypeError("tag_length must be an integer") if tag_length not in (4, 6, 8, 10, 12, 14, 16): raise ValueError("Invalid tag_length") self._tag_length = tag_length if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "AESCCM is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER)
def __init__(self, initialization_vector, tag=None, min_tag_length=16): # len(initialization_vector) must in [1, 2 ** 64), but it's impossible # to actually construct a bytes object that large, so we don't check # for it utils._check_byteslike("initialization_vector", initialization_vector) if len(initialization_vector) == 0: raise ValueError("initialization_vector must be at least 1 byte") self._initialization_vector = initialization_vector if tag is not None: utils._check_bytes("tag", tag) if min_tag_length < 4: raise ValueError("min_tag_length must be >= 4") if len(tag) < min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( min_tag_length)) self._tag = tag self._min_tag_length = min_tag_length
def __init__(self, initialization_vector, tag=None, min_tag_length=16): # len(initialization_vector) must in [1, 2 ** 64), but it's impossible # to actually construct a bytes object that large, so we don't check # for it utils._check_byteslike("initialization_vector", initialization_vector) if len(initialization_vector) == 0: raise ValueError("initialization_vector must be at least 1 byte") self._initialization_vector = initialization_vector if tag is not None: utils._check_bytes("tag", tag) if min_tag_length < 4: raise ValueError("min_tag_length must be >= 4") if len(tag) < min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( min_tag_length) ) self._tag = tag self._min_tag_length = min_tag_length
def __init__(self, key, tag_length=16): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESCCM key must be 128, 192, or 256 bits.") self._key = key if not isinstance(tag_length, int): raise TypeError("tag_length must be an integer") if tag_length not in (4, 6, 8, 10, 12, 14, 16): raise ValueError("Invalid tag_length") self._tag_length = tag_length if not backend.aead_cipher_supported(self): raise exceptions.UnsupportedAlgorithm( "AESCCM is not supported by this version of OpenSSL", exceptions._Reasons.UNSUPPORTED_CIPHER )
def __init__(self, initialization_vector, tag=None, min_tag_length=16): # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive # This is a sane limit anyway so we'll enforce it here. utils._check_byteslike("initialization_vector", initialization_vector) if len(initialization_vector) < 8 or len(initialization_vector) > 128: raise ValueError( "initialization_vector must be between 8 and 128 bytes (64 " "and 1024 bits).") self._initialization_vector = initialization_vector if tag is not None: utils._check_bytes("tag", tag) if min_tag_length < 4: raise ValueError("min_tag_length must be >= 4") if len(tag) < min_tag_length: raise ValueError( "Authentication tag must be {} bytes or longer.".format( min_tag_length)) self._tag = tag self._min_tag_length = min_tag_length
def load_ssh_public_key( data: bytes, backend: typing.Optional[Backend] = None) -> _SSH_PUBLIC_KEY_TYPES: """Load public key from OpenSSH one-line format.""" backend = _get_backend(backend) utils._check_byteslike("data", data) m = _SSH_PUBKEY_RC.match(data) if not m: raise ValueError("Invalid line format") key_type = orig_key_type = m.group(1) key_body = m.group(2) with_cert = False if _CERT_SUFFIX == key_type[-len(_CERT_SUFFIX):]: with_cert = True key_type = key_type[:-len(_CERT_SUFFIX)] kformat = _lookup_kformat(key_type) try: data = memoryview(binascii.a2b_base64(key_body)) except (TypeError, binascii.Error): raise ValueError("Invalid key format") inner_key_type, data = _get_sshstr(data) if inner_key_type != orig_key_type: raise ValueError("Invalid key format") if with_cert: nonce, data = _get_sshstr(data) public_key, data = kformat.load_public(key_type, data, backend) if with_cert: serial, data = _get_u64(data) cctype, data = _get_u32(data) key_id, data = _get_sshstr(data) principals, data = _get_sshstr(data) valid_after, data = _get_u64(data) valid_before, data = _get_u64(data) crit_options, data = _get_sshstr(data) extensions, data = _get_sshstr(data) reserved, data = _get_sshstr(data) sig_key, data = _get_sshstr(data) signature, data = _get_sshstr(data) _check_empty(data) return public_key
def derive(self, key_material): if self._used: raise AlreadyFinalized self._used = True utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while self._length > outlen: h = hashes.Hash(self._algorithm, self._backend) h.update(key_material) h.update(_int_to_u32be(counter)) if self._sharedinfo is not None: h.update(self._sharedinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:self._length]
def derive(self, key_material: bytes) -> bytes: if self._used: raise AlreadyFinalized self._used = True utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while self._length > outlen: h = hashes.Hash(self._algorithm) h.update(key_material) h.update(_int_to_u32be(counter)) if self._sharedinfo is not None: h.update(self._sharedinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:self._length]
def _concatkdf_derive( key_material: bytes, length: int, auxfn: typing.Callable[[], hashes.HashContext], otherinfo: bytes, ) -> bytes: utils._check_byteslike("key_material", key_material) output = [b""] outlen = 0 counter = 1 while length > outlen: h = auxfn() h.update(_int_to_u32be(counter)) h.update(key_material) h.update(otherinfo) output.append(h.finalize()) outlen += len(output[-1]) counter += 1 return b"".join(output)[:length]
def update(self, data: bytes) -> None: if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data)
def load_ssh_private_key(data, password, backend): """Load private key from OpenSSH custom encoding. """ utils._check_byteslike("data", data) if password is not None: utils._check_bytes("password", password) m = _PEM_RC.search(data) if not m: raise ValueError("Not OpenSSH private key format") p1 = m.start(1) p2 = m.end(1) data = binascii.a2b_base64(memoryview(data)[p1:p2]) if not data.startswith(_SK_MAGIC): raise ValueError("Not OpenSSH private key format") data = memoryview(data)[len(_SK_MAGIC):] # parse header ciphername, data = _get_sshstr(data) kdfname, data = _get_sshstr(data) kdfoptions, data = _get_sshstr(data) nkeys, data = _get_u32(data) if nkeys != 1: raise ValueError("Only one key supported") # load public key data pubdata, data = _get_sshstr(data) pub_key_type, pubdata = _get_sshstr(pubdata) kformat = _lookup_kformat(pub_key_type) pubfields, pubdata = kformat.get_public(pubdata) _check_empty(pubdata) # load secret data edata, data = _get_sshstr(data) _check_empty(data) if (ciphername, kdfname) != (_NONE, _NONE): ciphername = ciphername.tobytes() if ciphername not in _SSH_CIPHERS: raise UnsupportedAlgorithm("Unsupported cipher: %r" % ciphername) if kdfname != _BCRYPT: raise UnsupportedAlgorithm("Unsupported KDF: %r" % kdfname) blklen = _SSH_CIPHERS[ciphername][3] _check_block_size(edata, blklen) salt, kbuf = _get_sshstr(kdfoptions) rounds, kbuf = _get_u32(kbuf) _check_empty(kbuf) ciph = _init_cipher(ciphername, password, salt.tobytes(), rounds, backend) edata = memoryview(ciph.decryptor().update(edata)) else: blklen = 8 _check_block_size(edata, blklen) ck1, edata = _get_u32(edata) ck2, edata = _get_u32(edata) if ck1 != ck2: raise ValueError("Corrupt data: broken checksum") # load per-key struct key_type, edata = _get_sshstr(edata) if key_type != pub_key_type: raise ValueError("Corrupt data: key type mismatch") private_key, edata = kformat.load_private(edata, pubfields, backend) comment, edata = _get_sshstr(edata) # yes, SSH does padding check *after* all other parsing is done. # need to follow as it writes zero-byte padding too. if edata != _PADDING[:len(edata)]: raise ValueError("Corrupt data: invalid padding") return private_key
def _check_params(self, nonce, data, associated_data): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if not 7 <= len(nonce) <= 13: raise ValueError("Nonce must be between 7 and 13 bytes")
def set_data(self, data: bytes) -> "PKCS7SignatureBuilder": _check_byteslike("data", data) if self._data is not None: raise ValueError("data may only be set once") return PKCS7SignatureBuilder(data, self._signers)
def _check_params(self, nonce, data, associated_data): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) if len(nonce) != 12: raise ValueError("Nonce must be 12 bytes")
def __init__(self, initialization_vector): utils._check_byteslike("initialization_vector", initialization_vector) self._initialization_vector = initialization_vector
def update(self, data): if self._ctx is None: raise AlreadyFinalized("Context was already finalized.") utils._check_byteslike("data", data) self._ctx.update(data)
def derive(self, key_material): utils._check_byteslike("key_material", key_material) return self._hkdf_expand.derive(self._extract(key_material))
def __init__(self, key): utils._check_byteslike("key", key) if len(key) not in (16, 24, 32): raise ValueError("AESGCM key must be 128, 192, or 256 bits.") self._key = key
def __init__(self, nonce): utils._check_byteslike("nonce", nonce) self._nonce = nonce