def __init__( self, algorithm, mode: Mode, length: int, rlen: int, llen: typing.Optional[int], location: CounterLocation, label: typing.Optional[bytes], context: typing.Optional[bytes], fixed: typing.Optional[bytes], backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) if not isinstance(backend, CMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement CMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not issubclass(algorithm, ciphers.BlockCipherAlgorithm) or not issubclass( algorithm, ciphers.CipherAlgorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported cipher algorithm.", _Reasons.UNSUPPORTED_CIPHER, ) self._algorithm = algorithm self._backend = backend self._cipher: typing.Optional[ciphers.BlockCipherAlgorithm] = None self._deriver = _KBKDFDeriver( self._prf, mode, length, rlen, llen, location, label, context, fixed, )
def aes_key_unwrap(wrapping_key, wrapped_key, backend=None): backend = _get_backend(backend) if len(wrapped_key) < 24: raise InvalidUnwrap("Must be at least 24 bytes") if len(wrapped_key) % 8 != 0: raise InvalidUnwrap("The wrapped key must be a multiple of 8 bytes") if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") aiv = b"\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6" r = [wrapped_key[i : i + 8] for i in range(0, len(wrapped_key), 8)] a = r.pop(0) a, r = _unwrap_core(wrapping_key, a, r, backend) if not bytes_eq(a, aiv): raise InvalidUnwrap() return b"".join(r)
def load_ssh_public_key(data, backend=None): """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 __init__(self, algorithm, length, salt, info, backend=None): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) self._algorithm = algorithm if salt is None: salt = b"\x00" * self._algorithm.digest_size else: utils._check_bytes("salt", salt) self._salt = salt self._backend = backend self._hkdf_expand = HKDFExpand(self._algorithm, length, info, backend)
def __init__(self, algorithm: ciphers.BlockCipherAlgorithm, backend=None, ctx=None): backend = _get_backend(backend) if not isinstance(backend, CMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement CMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not isinstance(algorithm, ciphers.BlockCipherAlgorithm): raise TypeError("Expected instance of BlockCipherAlgorithm.") self._algorithm = algorithm self._backend = backend if ctx is None: self._ctx = self._backend.create_cmac_ctx(self._algorithm) else: self._ctx = ctx
def aes_key_wrap_with_padding(wrapping_key: bytes, key_to_wrap: bytes, backend=None) -> bytes: backend = _get_backend(backend) if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap)) # pad the key to wrap if necessary pad = (8 - (len(key_to_wrap) % 8)) % 8 key_to_wrap = key_to_wrap + b"\x00" * pad if len(key_to_wrap) == 8: # RFC 5649 - 4.1 - exactly 8 octets after padding encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() b = encryptor.update(aiv + key_to_wrap) assert encryptor.finalize() == b"" return b else: r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] return _wrap_core(wrapping_key, aiv, r, backend)
def aes_key_unwrap_with_padding(wrapping_key: bytes, wrapped_key: bytes, backend=None) -> bytes: backend = _get_backend(backend) if len(wrapped_key) < 16: raise InvalidUnwrap("Must be at least 16 bytes") if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") if len(wrapped_key) == 16: # RFC 5649 - 4.2 - exactly two 64-bit blocks decryptor = Cipher(AES(wrapping_key), ECB(), backend).decryptor() b = decryptor.update(wrapped_key) assert decryptor.finalize() == b"" a = b[:8] data = b[8:] n = 1 else: r = [wrapped_key[i:i + 8] for i in range(0, len(wrapped_key), 8)] encrypted_aiv = r.pop(0) n = len(r) a, r = _unwrap_core(wrapping_key, encrypted_aiv, r, backend) data = b"".join(r) # 1) Check that MSB(32,A) = A65959A6. # 2) Check that 8*(n-1) < LSB(32,A) <= 8*n. If so, let # MLI = LSB(32,A). # 3) Let b = (8*n)-MLI, and then check that the rightmost b octets of # the output data are zero. (mli, ) = struct.unpack(">I", a[4:]) b = (8 * n) - mli if (not bytes_eq(a[:4], b"\xa6\x59\x59\xa6") or not 8 * (n - 1) < mli <= 8 * n or (b != 0 and not bytes_eq(data[-b:], b"\x00" * b))): raise InvalidUnwrap() if b == 0: return data else: return data[:-b]
def __init__( self, algorithm: hashes.HashAlgorithm, length: int, otherinfo: typing.Optional[bytes], backend: typing.Optional[Backend] = None, ): backend = _get_backend(backend) _common_args_checks(algorithm, length, otherinfo) self._algorithm = algorithm self._length = length self._otherinfo: bytes = otherinfo if otherinfo is not None else b"" if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( "Backend object does not implement HashBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) self._backend = backend self._used = False
def __init__(self, algorithm, length, sharedinfo, backend=None): backend = _get_backend(backend) max_len = algorithm.digest_size * (2**32 - 1) if length > max_len: raise ValueError( "Can not derive keys larger than {} bits.".format(max_len)) if sharedinfo is not None: utils._check_bytes("sharedinfo", sharedinfo) self._algorithm = algorithm self._length = length self._sharedinfo = sharedinfo if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( "Backend object does not implement HashBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) self._backend = backend self._used = False
def __init__(self, algorithm, length, salt, iterations, backend=None): backend = _get_backend(backend) if not isinstance(backend, PBKDF2HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement PBKDF2HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not backend.pbkdf2_hmac_supported(algorithm): raise UnsupportedAlgorithm( "{} is not supported for PBKDF2 by this backend.".format( algorithm.name), _Reasons.UNSUPPORTED_HASH, ) self._used = False self._algorithm = algorithm self._length = length utils._check_bytes("salt", salt) self._salt = salt self._iterations = iterations self._backend = backend
def sign(self, encoding, options, backend=None): if len(self._signers) == 0: raise ValueError("Must have at least one signer") if self._data is None: raise ValueError("You must add data to sign") options = list(options) if not all(isinstance(x, PKCS7Options) for x in options): raise ValueError("options must be from the PKCS7Options enum") if encoding not in ( serialization.Encoding.PEM, serialization.Encoding.DER, serialization.Encoding.SMIME, ): raise ValueError( "Must be PEM, DER, or SMIME from the Encoding enum") # Text is a meaningless option unless it is accompanied by # DetachedSignature if (PKCS7Options.Text in options and PKCS7Options.DetachedSignature not in options): raise ValueError("When passing the Text option you must also pass " "DetachedSignature") if PKCS7Options.Text in options and encoding in ( serialization.Encoding.DER, serialization.Encoding.PEM, ): raise ValueError( "The Text option is only available for SMIME serialization") # No attributes implies no capabilities so we'll error if you try to # pass both. if (PKCS7Options.NoAttributes in options and PKCS7Options.NoCapabilities in options): raise ValueError( "NoAttributes is a superset of NoCapabilities. Do not pass " "both values.") backend = _get_backend(backend) return backend.pkcs7_sign(self, encoding, options)
def __init__( self, algorithm: CipherAlgorithm, mode: typing.Optional[modes.Mode], backend=None, ): backend = _get_backend(backend) if not isinstance(backend, CipherBackend): raise UnsupportedAlgorithm( "Backend object does not implement CipherBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not isinstance(algorithm, CipherAlgorithm): raise TypeError("Expected interface of CipherAlgorithm.") if mode is not None: mode.validate_for_algorithm(algorithm) self.algorithm = algorithm self.mode = mode self._backend = backend
def __init__(self, key: bytes, algorithm: hashes.HashAlgorithm, backend=None, ctx=None): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not isinstance(algorithm, hashes.HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm self._backend = backend self._key = key if ctx is None: self._ctx = self._backend.create_hmac_ctx(key, self.algorithm) else: self._ctx = ctx
def __init__( self, algorithm: HashAlgorithm, backend: typing.Optional[Backend] = None, ctx: typing.Optional["HashContext"] = None, ): backend = _get_backend(backend) if not isinstance(backend, HashBackend): raise UnsupportedAlgorithm( "Backend object does not implement HashBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not isinstance(algorithm, HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm self._backend = backend if ctx is None: self._ctx = self._backend.create_hash_ctx(self.algorithm) else: self._ctx = ctx
def __init__(self, algorithm, length, salt, otherinfo, backend=None): backend = _get_backend(backend) _common_args_checks(algorithm, length, otherinfo) self._algorithm = algorithm self._length = length self._otherinfo = otherinfo if self._otherinfo is None: self._otherinfo = b"" if salt is None: salt = b"\x00" * algorithm.block_size else: utils._check_bytes("salt", salt) self._salt = salt if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) self._backend = backend self._used = False
def sign(self, private_key, algorithm, backend=None): """ Signs the certificate using the CA's private key. """ backend = _get_backend(backend) if self._subject_name is None: raise ValueError("A certificate must have a subject name") if self._issuer_name is None: raise ValueError("A certificate must have an issuer name") if self._serial_number is None: raise ValueError("A certificate must have a serial number") if self._not_valid_before is None: raise ValueError("A certificate must have a not valid before time") if self._not_valid_after is None: raise ValueError("A certificate must have a not valid after time") if self._public_key is None: raise ValueError("A certificate must have a public key") return backend.create_x509_certificate(self, private_key, algorithm)
def generate_private_key( curve: EllipticCurve, backend=None ) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.generate_elliptic_curve_private_key(curve)
def load_key_and_certificates(data, password, backend=None): backend = _get_backend(backend) return backend.load_key_and_certificates_from_pkcs12(data, password)
def serialize_ssh_private_key( private_key: _SSH_PRIVATE_KEY_TYPES, password: typing.Optional[bytes] = None, ) -> bytes: """Serialize private key with OpenSSH custom encoding.""" if password is not None: utils._check_bytes("password", password) if password and len(password) > _MAX_PASSWORD: raise ValueError("Passwords longer than 72 bytes are not supported by " "OpenSSH private key format") if isinstance(private_key, ec.EllipticCurvePrivateKey): key_type = _ecdsa_key_type(private_key.public_key()) elif isinstance(private_key, rsa.RSAPrivateKey): key_type = _SSH_RSA elif isinstance(private_key, dsa.DSAPrivateKey): key_type = _SSH_DSA elif isinstance(private_key, ed25519.Ed25519PrivateKey): key_type = _SSH_ED25519 else: raise ValueError("Unsupported key type") kformat = _lookup_kformat(key_type) # setup parameters f_kdfoptions = _FragList() if password: ciphername = _DEFAULT_CIPHER blklen = _SSH_CIPHERS[ciphername][3] kdfname = _BCRYPT rounds = _DEFAULT_ROUNDS salt = os.urandom(16) f_kdfoptions.put_sshstr(salt) f_kdfoptions.put_u32(rounds) backend: Backend = _get_backend(None) ciph = _init_cipher(ciphername, password, salt, rounds, backend) else: ciphername = kdfname = _NONE blklen = 8 ciph = None nkeys = 1 checkval = os.urandom(4) comment = b"" # encode public and private parts together f_public_key = _FragList() f_public_key.put_sshstr(key_type) kformat.encode_public(private_key.public_key(), f_public_key) f_secrets = _FragList([checkval, checkval]) f_secrets.put_sshstr(key_type) kformat.encode_private(private_key, f_secrets) f_secrets.put_sshstr(comment) f_secrets.put_raw(_PADDING[:blklen - (f_secrets.size() % blklen)]) # top-level structure f_main = _FragList() f_main.put_raw(_SK_MAGIC) f_main.put_sshstr(ciphername) f_main.put_sshstr(kdfname) f_main.put_sshstr(f_kdfoptions) f_main.put_u32(nkeys) f_main.put_sshstr(f_public_key) f_main.put_sshstr(f_secrets) # copy result info bytearray slen = f_secrets.size() mlen = f_main.size() buf = memoryview(bytearray(mlen + blklen)) f_main.render(buf) ofs = mlen - slen # encrypt in-place if ciph is not None: ciph.encryptor().update_into(buf[ofs:mlen], buf[ofs:]) txt = _ssh_pem_encode(buf[:mlen]) # Ignore the following type because mypy wants # Sequence[bytes] but what we're passing is fine. # https://github.com/python/mypy/issues/9999 buf[ofs:mlen] = bytearray(slen) # type: ignore return txt
def load_ssh_private_key( data: bytes, password: typing.Optional[bytes], backend: typing.Optional[Backend] = None, ) -> _SSH_PRIVATE_KEY_TYPES: """Load private key from OpenSSH custom encoding.""" utils._check_byteslike("data", data) backend = _get_backend(backend) 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 load_der_parameters(data: bytes, backend=None) -> dh.DHParameters: backend = _get_backend(backend) return backend.load_der_parameters(data)
def load_der_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_public_key(data)
def load_der_private_key( data: bytes, password: typing.Optional[bytes], backend=None ) -> _PRIVATE_KEY_TYPES: backend = _get_backend(backend) return backend.load_der_private_key(data, password)
def load_der_x509_crl(data: bytes, backend=None) -> CertificateRevocationList: backend = _get_backend(backend) return backend.load_der_x509_crl(data)
def load_der_x509_csr(data: bytes, backend=None) -> CertificateSigningRequest: backend = _get_backend(backend) return backend.load_der_x509_csr(data)
def load_der_x509_certificate(data: bytes, backend=None) -> Certificate: backend = _get_backend(backend) return backend.load_der_x509_certificate(data)
def __init__( self, algorithm: hashes.HashAlgorithm, mode: Mode, length: int, rlen: int, llen: typing.Optional[int], location: CounterLocation, label: typing.Optional[bytes], context: typing.Optional[bytes], fixed: typing.Optional[bytes], backend=None, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) if not isinstance(algorithm, hashes.HashAlgorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported hash algorithm.", _Reasons.UNSUPPORTED_HASH, ) if not backend.hmac_supported(algorithm): raise UnsupportedAlgorithm( "Algorithm supplied is not a supported hmac algorithm.", _Reasons.UNSUPPORTED_HASH, ) if not isinstance(mode, Mode): raise TypeError("mode must be of type Mode") if not isinstance(location, CounterLocation): raise TypeError("location must be of type CounterLocation") if (label or context) and fixed: raise ValueError("When supplying fixed data, " "label and context are ignored.") if rlen is None or not self._valid_byte_length(rlen): raise ValueError("rlen must be between 1 and 4") if llen is None and fixed is None: raise ValueError("Please specify an llen") if llen is not None and not isinstance(llen, int): raise TypeError("llen must be an integer") if label is None: label = b"" if context is None: context = b"" utils._check_bytes("label", label) utils._check_bytes("context", context) self._algorithm = algorithm self._mode = mode self._length = length self._rlen = rlen self._llen = llen self._location = location self._label = label self._context = context self._backend = backend self._used = False self._fixed_data = fixed
def public_key(self, backend=None) -> EllipticCurvePublicKey: backend = _get_backend(backend) return backend.load_elliptic_curve_public_numbers(self)
def private_key(self, backend=None) -> EllipticCurvePrivateKey: backend = _get_backend(backend) return backend.load_elliptic_curve_private_numbers(self)
def public_bytes(self, backend=None): backend = _get_backend(backend) return backend.x509_name_bytes(self)