1# Copyright 2016 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Cryptography helpers for verifying and signing messages.
16
17The simplest way to verify signatures is using :func:`verify_signature`::
18
19    cert = open('certs.pem').read()
20    valid = crypt.verify_signature(message, signature, cert)
21
22If you're going to verify many messages with the same certificate, you can use
23:class:`RSAVerifier`::
24
25    cert = open('certs.pem').read()
26    verifier = crypt.RSAVerifier.from_string(cert)
27    valid = verifier.verify(message, signature)
28
29To sign messages use :class:`RSASigner` with a private key::
30
31    private_key = open('private_key.pem').read()
32    signer = crypt.RSASigner.from_string(private_key)
33    signature = signer.sign(message)
34
35The code above also works for :class:`ES256Signer` and :class:`ES256Verifier`.
36Note that these two classes are only available if your `cryptography` dependency
37version is at least 1.4.0.
38"""
39
40import six
41
42from google.auth.crypt import base
43from google.auth.crypt import rsa
44
45try:
46    from google.auth.crypt import es256
47except ImportError:  # pragma: NO COVER
48    es256 = None
49
50if es256 is not None:  # pragma: NO COVER
51    __all__ = [
52        "ES256Signer",
53        "ES256Verifier",
54        "RSASigner",
55        "RSAVerifier",
56        "Signer",
57        "Verifier",
58    ]
59else:  # pragma: NO COVER
60    __all__ = ["RSASigner", "RSAVerifier", "Signer", "Verifier"]
61
62
63# Aliases to maintain the v1.0.0 interface, as the crypt module was split
64# into submodules.
65Signer = base.Signer
66Verifier = base.Verifier
67RSASigner = rsa.RSASigner
68RSAVerifier = rsa.RSAVerifier
69
70if es256 is not None:  # pragma: NO COVER
71    ES256Signer = es256.ES256Signer
72    ES256Verifier = es256.ES256Verifier
73
74
75def verify_signature(message, signature, certs, verifier_cls=rsa.RSAVerifier):
76    """Verify an RSA or ECDSA cryptographic signature.
77
78    Checks that the provided ``signature`` was generated from ``bytes`` using
79    the private key associated with the ``cert``.
80
81    Args:
82        message (Union[str, bytes]): The plaintext message.
83        signature (Union[str, bytes]): The cryptographic signature to check.
84        certs (Union[Sequence, str, bytes]): The certificate or certificates
85            to use to check the signature.
86        verifier_cls (Optional[~google.auth.crypt.base.Signer]): Which verifier
87            class to use for verification. This can be used to select different
88            algorithms, such as RSA or ECDSA. Default value is :class:`RSAVerifier`.
89
90    Returns:
91        bool: True if the signature is valid, otherwise False.
92    """
93    if isinstance(certs, (six.text_type, six.binary_type)):
94        certs = [certs]
95
96    for cert in certs:
97        verifier = verifier_cls.from_string(cert)
98        if verifier.verify(message, signature):
99            return True
100    return False
101