Esempio n. 1
0
    def __init__(self, hmac_key, algorithm):
        """Constructor for Hmac.

    Args:
      hmac_key: bytes, the symmetric hmac key.
      algorithm: string, HMAC algorithm as defined at
        https://tools.ietf.org/html/rfc7518#section-3.1.

    Raises:
      TypeError: if the hmac key is not bytes.
      UnsupportedAlgorithm: if the algorithm is not supported or key is too
      short.
    """
        if algorithm == "HS256":
            self._hash = hashes.SHA256()
        elif algorithm == "HS384":
            self._hash = hashes.SHA384()
        elif algorithm == "HS512":
            self._hash = hashes.SHA512()
        else:
            raise exceptions.UnsupportedAlgorithm("Unknown algorithm: %s " %
                                                  (algorithm))
        if not isinstance(hmac_key, six.binary_type):
            raise TypeError("hmac key must be bytes")
        if len(hmac_key) < 16:
            raise exceptions.UnsupportedAlgorithm("key too short")
        self._hmac_key = hmac_key
        self.algorithm = algorithm
Esempio n. 2
0
    def __init__(self, jwk_set):
        """Constructor for JwsPublicKeySign.

    Args:
      jwk_set: a JwkSet.

    Raises:
      UnsupportedAlgorithm: if the algorihtm is not defined at
      https://tools.ietf.org/html/rfc7518#section-3.1 or if jwk is not Rsa or
      Ecdsa key.
    """
        if len(jwk_set.keys) != 1:
            raise exceptions.UnsupportedAlgorithm(
                "Do not support multiple keys in signer")
        key = jwk_set.keys[0]
        if key.key_type == "RSA":
            self.signer = RsaSign(key.priv_key, key.algorithm)
        elif key.key_type == "EC":
            self.signer = EcdsaSign(key.priv_key, key.algorithm)
        else:
            raise exceptions.UnsupportedAlgorithm(
                "Unknown key type: %s or algorithm: %s" %
                (key.key_type, key.algorithm))
        if hasattr(key, "kid"):
            self.kid = key.kid
        self.algorithm = key.algorithm
Esempio n. 3
0
    def from_pem(cls, pem_key, algorithm, kid=""):
        """Parses PEM key and transformat it to Jwk key.

    As PEM key doesn't specify the full algorithm to use (e.g. a RSA key doesn't
    specify which hash function should be used), the caller has to specify what
    algorithm that it would use the key for.
    Args:
      pem_key: bytes, RSA or ECDSA key in PEM format.
      algorithm: string, RSA or ECDSA algorithm as defined at
        https://tools.ietf.org/html/rfc7518#section-3.1.
      kid: string, Key ID as defined at
        https://tools.ietf.org/html/rfc7515#section-4.1.4.

    Raises:
      UnsupportedAlgorithm: if the algorithm is not supported or pem_key is
      error.
    """
        if algorithm not in [
                "RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "PS256",
                "PS384", "PS512"
        ]:
            raise exceptions.UnsupportedAlgorithm("Unknown algorithm: %s" %
                                                  (algorithm))
        key_type = ""
        key = ""
        # Try to parse it as private key.
        try:
            key = load_pem_private_key(pem_key,
                                       None,
                                       backend=backends.default_backend())
        except (ValueError, TypeError,
                exceptions.UnsupportedAlgorithm) as ignored:
            # If not succeeded, try to parse it as public key.
            try:
                key = load_pem_public_key(pem_key,
                                          backend=backends.default_backend())
            except (ValueError, TypeError,
                    exceptions.UnsupportedAlgorithm) as e:
                raise exceptions.UnsupportedAlgorithm(
                    "Pem key parsing error: %s" % (e))
        if isinstance(key, rsa.RSAPrivateKey):
            return JwkSet(
                [Jwk("RSA", kid, algorithm, None, key, key.public_key())])
        elif isinstance(key, rsa.RSAPublicKey):
            return JwkSet([Jwk("RSA", kid, algorithm, None, None, key)])
        elif isinstance(key, ec.EllipticCurvePrivateKey):
            return JwkSet(
                [Jwk("EC", kid, algorithm, None, key, key.public_key())])
        elif isinstance(key, ec.EllipticCurvePublicKey):
            return JwkSet([Jwk("EC", kid, algorithm, None, None, key)])
        else:
            raise exceptions.UnsupportedAlgorithm(
                "Unknown supported key pem: %s" % (e))
Esempio n. 4
0
    def from_cryptography_key(cls, key, algorithm, kid=""):
        """Transform cryptography's key to Jwk key.

    As cryptography's key doesn't specify the full algorithm to use (e.g. a RSA
    key doesn't specify which hash function should be used), the caller has to
    specify what algorithm that it would use the key for.

    Args:
      key: rsa.RSAPrivateKey, rsa.RSAPublicKey, ec.EllipticCurvePrivateKey or
        ec.EllipticCurvePublicKey
      algorithm: string, RSA or ECDSA algorithm as defined at
        https://tools.ietf.org/html/rfc7518#section-3.1.
      kid: string, Key ID as defined at
        https://tools.ietf.org/html/rfc7515#section-4.1.4.

    Raises:
      UnsupportedAlgorithm: if the algorithm is not supported or cryptography
      key has error.

    Returns:
      A JwkSet.
    """
        rsa_algorithms = ["RS256", "RS384", "RS512", "PS256", "PS384", "PS512"]
        ecdsa_algorithms = ["ES256", "ES384", "ES512"]

        if algorithm in rsa_algorithms:
            if isinstance(key, rsa.RSAPrivateKey):
                return JwkSet(
                    [Jwk("RSA", kid, algorithm, None, key, key.public_key())])
            elif isinstance(key, rsa.RSAPublicKey):
                return JwkSet([Jwk("RSA", kid, algorithm, None, None, key)])
            else:
                raise exceptions.UnsupportedAlgorithm(
                    "Unsupported mismatch between algorithm: %s and cryptography key:%s"
                    % (algorithm, key))
        elif algorithm in ecdsa_algorithms:
            if isinstance(key, ec.EllipticCurvePrivateKey):
                return JwkSet(
                    [Jwk("EC", kid, algorithm, None, key, key.public_key())])
            elif isinstance(key, ec.EllipticCurvePublicKey):
                return JwkSet([Jwk("EC", kid, algorithm, None, None, key)])
            else:
                raise exceptions.UnsupportedAlgorithm(
                    "Unsupported mismatch between algorithm: %s and cryptography key:%s"
                    % (algorithm, key))
        else:
            raise exceptions.UnsupportedAlgorithm("Unknown algorithm: %s" %
                                                  (algorithm))
Esempio n. 5
0
def ecdsa_algorithm_to_curve_length(algorithm):
  """Computes curve length based on ecdsa's algorithm.

  Args:
    algorithm: string, Ecdsa algorithm as defined at
    https://tools.ietf.org/html/rfc7518#section-3.1.

  Raises:
    UnsupportedAlgorithm: if the algorithm is not supported.

  Returns:
    The curve length in bytes.
  """

  _NIST_P256_CURVE_LENGTH_IN_BITS = 256
  _NIST_P384_CURVE_LENGTH_IN_BITS = 384
  _NIST_P521_CURVE_LENGTH_IN_BITS = 521

  if algorithm == "ES256":
    return int(_NIST_P256_CURVE_LENGTH_IN_BITS // 8)
  elif algorithm == "ES384":
    return int(_NIST_P384_CURVE_LENGTH_IN_BITS // 8)
  elif algorithm == "ES512":
    return int((_NIST_P521_CURVE_LENGTH_IN_BITS + 7) // 8)
  else:
    raise exceptions.UnsupportedAlgorithm("Unknown algorithm: %s" % (algorithm))
Esempio n. 6
0
File: util.py Progetto: metabol/JWS
def parse_rsa_algorithm(algorithm):
    """Parses Rsa's algorithm and returns tuple (hash, padding).

  Args:
    algorithm: string, RSA algorithm as defined at
    https://tools.ietf.org/html/rfc7518#section-3.1.

  Raises:
    UnsupportedAlgorithm: if the algorithm is not supported.

  Returns:
    (hash, padding) tuple.
  """

    if algorithm == "RS256":
        return (hashes.SHA256(), padding.PKCS1v15())
    elif algorithm == "RS384":
        return (hashes.SHA384(), padding.PKCS1v15())
    elif algorithm == "RS512":
        return (hashes.SHA512(), padding.PKCS1v15())
    elif algorithm == "PS256":
        return (hashes.SHA256(),
                padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                            salt_length=padding.PSS.MAX_LENGTH))
    elif algorithm == "PS384":
        return (hashes.SHA384(),
                padding.PSS(mgf=padding.MGF1(hashes.SHA384()),
                            salt_length=padding.PSS.MAX_LENGTH))
    elif algorithm == "PS512":
        return (hashes.SHA512(),
                padding.PSS(mgf=padding.MGF1(hashes.SHA512()),
                            salt_length=padding.PSS.MAX_LENGTH))
    else:
        raise exceptions.UnsupportedAlgorithm("Unknown algorithm: %s" %
                                              (algorithm))
Esempio n. 7
0
    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
Esempio n. 8
0
    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,
            )
Esempio n. 9
0
    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,
            )
Esempio n. 10
0
    def __init__(self, pub_key, algorithm):
        """Constructor for EcdsaVerify.

    Args:
      pub_key: ec.EllipticCurvePublicKey, the Ecdsa public key.
      algorithm: string, Ecdsa algorithm as defined at
        https://tools.ietf.org/html/rfc7518#section-3.1.
    Raises:
      TypeError: if the public key is not an instance of
      ec.EllipticCurvePublicKey.
      UnsupportedAlgorithm: if the algorithm is not supported.
    """
        if not isinstance(pub_key, ec.EllipticCurvePublicKey):
            raise TypeError(
                "The public key must be an instance of ec.EllipticCurvePublicKey"
            )
        self.pub_key = pub_key
        curve_name = ""
        if algorithm == "ES256":
            self.hash = hashes.SHA256()
            curve_name = "secp256r1"
        elif algorithm == "ES384":
            self.hash = hashes.SHA384()
            curve_name = "secp384r1"
        elif algorithm == "ES521":
            self.hash = hashes.SHA512()
            curve_name = "secp521r1"
        else:
            raise exceptions.UnsupportedAlgorithm("Unknown algorithm : %s" %
                                                  (algorithm))
        # In Ecdsa, both the key and the algorithm define the curve. Therefore, we
        # must cross check them to make sure they're the same.
        if curve_name != pub_key.curve.name:
            raise exceptions.UnsupportedAlgorithm(
                "The curve in public key %s and in algorithm % don't match" %
                (pub_key.curve.name, curve_name))
        self.algorithm = algorithm
Esempio n. 11
0
    def __init__(self, jwk_set):
        """Constructor for JwsMacAuthenticator.

    Args:
      jwk_set: a JwkSet.

    Raises:
      UnsupportedAlgorithm: if the key.algorihtm is not defined at
      https://tools.ietf.org/html/rfc7518#section-3.1 or if jwk is not symmetric
      Hmac key.
    """
        if len(jwk_set.keys) != 1:
            raise exceptions.UnsupportedAlgorithm(
                "Do not support multiple keys in authenticator")
        key = jwk_set.keys[0]
        if key.key_type == "oct":
            self.mac = Hmac(key.sym_key, key.algorithm)
        else:
            raise exceptions.UnsupportedAlgorithm(
                "Unknown key type: %s or algorithm: %s" %
                (key.key_type, key.algorithm))
        if hasattr(key, "kid"):
            self.kid = key.kid
        self.algorithm = key.algorithm
Esempio n. 12
0
    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)
Esempio n. 13
0
 def test_verify_signature_unsupported_algorithm(self, mock_get_pub_key):
     public_key = TEST_RSA_PRIVATE_KEY.public_key()
     public_key.verifier = mock.MagicMock(
         side_effect=crypto_exception.UnsupportedAlgorithm(
             "When OpenSSL is older than 1.0.1 then only SHA1 is "
             "supported with MGF1.",
             crypto_exception._Reasons.UNSUPPORTED_HASH))
     mock_get_pub_key.return_value = public_key
     image_properties = {
         CERT_UUID: 'fea14bc2-d75f-4ba5-bccc-b5c924ad0693',
         HASH_METHOD: 'SHA-256',
         KEY_TYPE: 'RSA-PSS',
         SIGNATURE: 'BLAH'
     }
     self.assertRaisesRegexp(
         exception.SignatureVerificationError,
         'Unable to verify signature since the '
         'algorithm is unsupported on this system',
         signature_utils.get_verifier, None, image_properties)
Esempio n. 14
0
    def __init__(self, jwk_set):
        """Constructor for JwsMacVerify.

    Args:
      jwk_set: a JwkSet.

    Raises:
      UnsupportedAlgorithm: if the algorihtm is not defined at
      https://tools.ietf.org/html/rfc7518#section-3.1 or if jwk is symmetric
      Hmac key.
    """
        self.verifiers = []
        for key in jwk_set.keys:
            if key.key_type == "oct":
                self.verifiers.append((Hmac(key.sym_key,
                                            key.algorithm), key.kid))
            else:
                raise exceptions.UnsupportedAlgorithm(
                    "Unsupported key type: %s or unrecognized algorithm: %s" %
                    (key.key_type, key.algorithm))
Esempio n. 15
0
    def __init__(self, jwk_set):
        """Constructor for JwsPublicKeyVerify.

    Args:
      jwk_set: a JwkSet.

    Raises:
      UnsupportedAlgorithm: if the algorihtm is not defined at
      https://tools.ietf.org/html/rfc7518#section-3.1 or if jwk is not Rsa or
      Ecdsa key.
    """
        self.verifiers = []
        for key in jwk_set.keys:
            if key.key_type == "RSA":
                self.verifiers.append((RsaVerify(key.pub_key,
                                                 key.algorithm), key.kid))
            elif key.key_type == "EC":
                self.verifiers.append((EcdsaVerify(key.pub_key,
                                                   key.algorithm), key.kid))
            else:
                raise exceptions.UnsupportedAlgorithm(
                    "Unsupported key type: %s" % (key.key_type))
Esempio n. 16
0
    def _read_single_json_key(cls, parsed_key):
        """Reads a parsed json key and transform it to Jwk key.

    Args:
      parsed_key: a Python reprenstation of Json object.

    Raises:
      UnsupportedAlgorithm: if the key type is not supported.

    Returns:
      A Jwk key.
    """

        key_type = parsed_key["kty"]
        algorithm = parsed_key.get("alg", "")

        if not algorithm:
            raise exceptions.UnsupportedAlgorithm("Alg field is missing")

        if algorithm not in [
                "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "ES256",
                "ES384", "ES512", "PS256", "PS384", "PS512"
        ]:
            raise exceptions.UnsupportedAlgorithm("Unknown algorithm: %s" %
                                                  (algorithm))

        if key_type == "RSA":
            rsa_pub_numbers = rsa.RSAPublicNumbers(
                jwsutil.b64_to_int(parsed_key["e"]),
                jwsutil.b64_to_int(parsed_key["n"]))
            if parsed_key.get("p", None) is not None:
                # Rsa private key.
                rsa_priv_numbers = rsa.RSAPrivateNumbers(
                    jwsutil.b64_to_int(parsed_key["p"]),
                    jwsutil.b64_to_int(parsed_key["q"]),
                    jwsutil.b64_to_int(parsed_key["d"]),
                    jwsutil.b64_to_int(parsed_key["dp"]),
                    jwsutil.b64_to_int(parsed_key["dq"]),
                    jwsutil.b64_to_int(parsed_key["qi"]), rsa_pub_numbers)
                priv_key = rsa_priv_numbers.private_key(
                    backends.default_backend())
                return Jwk(key_type, parsed_key.get("kid", ""), algorithm,
                           None, priv_key, priv_key.public_key())
            else:
                # Rsa public key.
                return Jwk(
                    key_type, parsed_key.get("kid", ""), algorithm, None, None,
                    rsa_pub_numbers.public_key(backends.default_backend()))
        elif key_type == "EC":
            if parsed_key["crv"] == "P-256":
                curve = ec.SECP256R1()
            elif parsed_key["crv"] == "P-384":
                curve = ec.SECP384R1()
            elif parsed_key["crv"] == "P-521":
                curve = ec.SECP521R1()
            else:
                raise exceptions.UnsupportedAlgorithm("Unknown curve: %s" %
                                                      (parsed_key["crv"]))
            if parsed_key.get("d", None) is not None:
                # Ecdsa private key.
                priv_key = ec.derive_private_key(
                    jwsutil.b64_to_int(parsed_key["d"]), curve,
                    backends.default_backend())
                return Jwk(key_type, parsed_key.get("kid", ""), algorithm,
                           None, priv_key, priv_key.public_key())
            else:
                # Ecdsa public key.
                ec_pub_numbers = ec.EllipticCurvePublicNumbers(
                    jwsutil.b64_to_int(parsed_key["x"]),
                    jwsutil.b64_to_int(parsed_key["y"]), curve)
                pub_key = ec_pub_numbers.public_key(backends.default_backend())
                return Jwk(key_type, parsed_key.get("kid", ""), algorithm,
                           None, None, pub_key)
        elif key_type == "oct":
            sym_key = jwsutil.urlsafe_b64decode(parsed_key["k"])
            return Jwk(key_type, parsed_key.get("kid", ""), algorithm, sym_key)
        else:
            raise exceptions.UnsupportedAlgorithm("Unsupported key type: %s" %
                                                  (key_type))
Esempio n. 17
0
    def sign_cert(cls, csr, validity, ca_cert=None, ca_key=None,
                  ca_key_pass=None, ca_digest=None):
        """Signs a certificate using our private CA based on the specified CSR

        The signed certificate will be valid from now until <validity> seconds
        from now.

        :param csr: A Certificate Signing Request
        :param validity: Valid for <validity> seconds from the current time
        :param ca_cert: Signing Certificate (default: config)
        :param ca_key: Signing Certificate Key (default: config)
        :param ca_key_pass: Signing Certificate Key Pass (default: config)
        :param ca_digest: Digest method to use for signing (default: config)

        :return: Signed certificate
        :raises Exception: if certificate signing fails
        """
        LOG.info("Signing a certificate request using OpenSSL locally.")
        cls._validate_cert(ca_cert, ca_key, ca_key_pass)
        if not ca_digest:
            ca_digest = CONF.certificates.signing_digest
        try:
            algorithm = getattr(hashes, ca_digest.upper())()
        except AttributeError:
            raise crypto_exceptions.UnsupportedAlgorithm(
                "Supplied digest method not found: %s" % ca_digest
            )

        if not ca_cert:
            with open(CONF.certificates.ca_certificate, 'rb') as f:
                ca_cert = f.read()
        if not ca_key:
            with open(CONF.certificates.ca_private_key, 'rb') as f:
                ca_key = f.read()
        if not ca_key_pass:
            ca_key_pass = CONF.certificates.ca_private_key_passphrase
            if ca_key_pass is not None:
                ca_key_pass = ca_key_pass.encode('utf-8')

        try:
            lo_cert = x509.load_pem_x509_certificate(
                data=ca_cert, backend=backends.default_backend())
            lo_key = serialization.load_pem_private_key(
                data=ca_key, password=ca_key_pass,
                backend=backends.default_backend())
            lo_req = x509.load_pem_x509_csr(data=csr,
                                            backend=backends.default_backend())
            new_cert = x509.CertificateBuilder()
            new_cert = new_cert.serial_number(cls._new_serial())
            valid_from_datetime = datetime.datetime.utcnow()
            valid_to_datetime = (datetime.datetime.utcnow() +
                                 datetime.timedelta(seconds=validity))
            new_cert = new_cert.not_valid_before(valid_from_datetime)
            new_cert = new_cert.not_valid_after(valid_to_datetime)
            new_cert = new_cert.issuer_name(lo_cert.subject)
            new_cert = new_cert.subject_name(lo_req.subject)
            new_cert = new_cert.public_key(lo_req.public_key())
            new_cert = new_cert.add_extension(
                x509.BasicConstraints(ca=False, path_length=None),
                critical=True
            )
            cn_str = lo_req.subject.get_attributes_for_oid(
                x509.oid.NameOID.COMMON_NAME)[0].value
            new_cert = new_cert.add_extension(
                x509.SubjectAlternativeName([x509.DNSName(cn_str)]),
                critical=False
            )
            new_cert = new_cert.add_extension(
                x509.KeyUsage(
                    digital_signature=True,
                    key_encipherment=True,
                    data_encipherment=True,
                    key_agreement=True,
                    content_commitment=False,
                    key_cert_sign=False,
                    crl_sign=False,
                    encipher_only=False,
                    decipher_only=False
                ),
                critical=True
            )
            new_cert = new_cert.add_extension(
                x509.ExtendedKeyUsage([
                    x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
                    x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH
                ]),
                critical=True
            )
            signed_cert = new_cert.sign(private_key=lo_key,
                                        algorithm=algorithm,
                                        backend=backends.default_backend())
            return signed_cert.public_bytes(
                encoding=serialization.Encoding.PEM)
        except Exception as e:
            LOG.error("Unable to sign certificate.")
            raise exceptions.CertificateGenerationException(msg=e)