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,
        )
Пример #2
0
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)
Пример #3
0
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
Пример #4
0
    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)
Пример #5
0
    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
Пример #6
0
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)
Пример #7
0
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
Пример #9
0
    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
Пример #10
0
    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
Пример #11
0
    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)
Пример #12
0
    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
Пример #13
0
    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
Пример #14
0
    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
Пример #15
0
    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
Пример #16
0
    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)
Пример #17
0
def generate_private_key(
    curve: EllipticCurve, backend=None
) -> EllipticCurvePrivateKey:
    backend = _get_backend(backend)
    return backend.generate_elliptic_curve_private_key(curve)
Пример #18
0
def load_key_and_certificates(data, password, backend=None):
    backend = _get_backend(backend)
    return backend.load_key_and_certificates_from_pkcs12(data, password)
Пример #19
0
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
Пример #20
0
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
Пример #21
0
def load_der_parameters(data: bytes, backend=None) -> dh.DHParameters:
    backend = _get_backend(backend)
    return backend.load_der_parameters(data)
Пример #22
0
def load_der_public_key(data: bytes, backend=None) -> _PUBLIC_KEY_TYPES:
    backend = _get_backend(backend)
    return backend.load_der_public_key(data)
Пример #23
0
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)
Пример #24
0
def load_der_x509_crl(data: bytes, backend=None) -> CertificateRevocationList:
    backend = _get_backend(backend)
    return backend.load_der_x509_crl(data)
Пример #25
0
def load_der_x509_csr(data: bytes, backend=None) -> CertificateSigningRequest:
    backend = _get_backend(backend)
    return backend.load_der_x509_csr(data)
Пример #26
0
def load_der_x509_certificate(data: bytes, backend=None) -> Certificate:
    backend = _get_backend(backend)
    return backend.load_der_x509_certificate(data)
Пример #27
0
    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
Пример #28
0
 def public_key(self, backend=None) -> EllipticCurvePublicKey:
     backend = _get_backend(backend)
     return backend.load_elliptic_curve_public_numbers(self)
Пример #29
0
 def private_key(self, backend=None) -> EllipticCurvePrivateKey:
     backend = _get_backend(backend)
     return backend.load_elliptic_curve_private_numbers(self)
Пример #30
0
 def public_bytes(self, backend=None):
     backend = _get_backend(backend)
     return backend.x509_name_bytes(self)