1# ===================================================================
2#
3# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in
14#    the documentation and/or other materials provided with the
15#    distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29# ===================================================================
30
31import Crypto.Util.number
32from Crypto.Util.number import ceil_div, bytes_to_long, long_to_bytes
33from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId
34
35class PKCS115_SigScheme:
36    """A signature object for ``RSASSA-PKCS1-v1_5``.
37    Do not instantiate directly.
38    Use :func:`Crypto.Signature.pkcs1_15.new`.
39    """
40
41    def __init__(self, rsa_key):
42        """Initialize this PKCS#1 v1.5 signature scheme object.
43
44        :Parameters:
45          rsa_key : an RSA key object
46            Creation of signatures is only possible if this is a *private*
47            RSA key. Verification of signatures is always possible.
48        """
49        self._key = rsa_key
50
51    def can_sign(self):
52        """Return ``True`` if this object can be used to sign messages."""
53        return self._key.has_private()
54
55    def sign(self, msg_hash):
56        """Create the PKCS#1 v1.5 signature of a message.
57
58        This function is also called ``RSASSA-PKCS1-V1_5-SIGN`` and
59        it is specified in
60        `section 8.2.1 of RFC8017 <https://tools.ietf.org/html/rfc8017#page-36>`_.
61
62        :parameter msg_hash:
63            This is an object from the :mod:`Crypto.Hash` package.
64            It has been used to digest the message to sign.
65        :type msg_hash: hash object
66
67        :return: the signature encoded as a *byte string*.
68        :raise ValueError: if the RSA key is not long enough for the given hash algorithm.
69        :raise TypeError: if the RSA key has no private half.
70        """
71
72        # See 8.2.1 in RFC3447
73        modBits = Crypto.Util.number.size(self._key.n)
74        k = ceil_div(modBits,8) # Convert from bits to bytes
75
76        # Step 1
77        em = _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k)
78        # Step 2a (OS2IP)
79        em_int = bytes_to_long(em)
80        # Step 2b (RSASP1)
81        m_int = self._key._decrypt(em_int)
82        # Step 2c (I2OSP)
83        signature = long_to_bytes(m_int, k)
84        return signature
85
86    def verify(self, msg_hash, signature):
87        """Check if the  PKCS#1 v1.5 signature over a message is valid.
88
89        This function is also called ``RSASSA-PKCS1-V1_5-VERIFY`` and
90        it is specified in
91        `section 8.2.2 of RFC8037 <https://tools.ietf.org/html/rfc8017#page-37>`_.
92
93        :parameter msg_hash:
94            The hash that was carried out over the message. This is an object
95            belonging to the :mod:`Crypto.Hash` module.
96        :type parameter: hash object
97
98        :parameter signature:
99            The signature that needs to be validated.
100        :type signature: byte string
101
102        :raise ValueError: if the signature is not valid.
103        """
104
105        # See 8.2.2 in RFC3447
106        modBits = Crypto.Util.number.size(self._key.n)
107        k = ceil_div(modBits, 8) # Convert from bits to bytes
108
109        # Step 1
110        if len(signature) != k:
111            raise ValueError("Invalid signature")
112        # Step 2a (O2SIP)
113        signature_int = bytes_to_long(signature)
114        # Step 2b (RSAVP1)
115        em_int = self._key._encrypt(signature_int)
116        # Step 2c (I2OSP)
117        em1 = long_to_bytes(em_int, k)
118        # Step 3
119        try:
120            possible_em1 = [ _EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, True) ]
121            # MD2/4/5 hashes always require NULL params in AlgorithmIdentifier.
122            # For all others, it is optional.
123            try:
124                algorithm_is_md = msg_hash.oid.startswith('1.2.840.113549.2.')
125            except AttributeError:
126                algorithm_is_md = False
127            if not algorithm_is_md:  # MD2/MD4/MD5
128                possible_em1.append(_EMSA_PKCS1_V1_5_ENCODE(msg_hash, k, False))
129        except ValueError:
130            raise ValueError("Invalid signature")
131        # Step 4
132        # By comparing the full encodings (as opposed to checking each
133        # of its components one at a time) we avoid attacks to the padding
134        # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptography@metzdowd.com/msg06537).
135        #
136        if em1 not in possible_em1:
137            raise ValueError("Invalid signature")
138        pass
139
140
141def _EMSA_PKCS1_V1_5_ENCODE(msg_hash, emLen, with_hash_parameters=True):
142    """
143    Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
144    in PKCS#1 v2.1 (RFC3447, 9.2).
145
146    ``_EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input,
147    and hash it internally. Here, we expect that the message has already
148    been hashed instead.
149
150    :Parameters:
151     msg_hash : hash object
152            The hash object that holds the digest of the message being signed.
153     emLen : int
154            The length the final encoding must have, in bytes.
155     with_hash_parameters : bool
156            If True (default), include NULL parameters for the hash
157            algorithm in the ``digestAlgorithm`` SEQUENCE.
158
159    :attention: the early standard (RFC2313) stated that ``DigestInfo``
160        had to be BER-encoded. This means that old signatures
161        might have length tags in indefinite form, which
162        is not supported in DER. Such encoding cannot be
163        reproduced by this function.
164
165    :Return: An ``emLen`` byte long string that encodes the hash.
166    """
167
168    # First, build the ASN.1 DER object DigestInfo:
169    #
170    #   DigestInfo ::= SEQUENCE {
171    #       digestAlgorithm AlgorithmIdentifier,
172    #       digest OCTET STRING
173    #   }
174    #
175    # where digestAlgorithm identifies the hash function and shall be an
176    # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms.
177    #
178    #   PKCS1-v1-5DigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
179    #       { OID id-md2 PARAMETERS NULL    }|
180    #       { OID id-md5 PARAMETERS NULL    }|
181    #       { OID id-sha1 PARAMETERS NULL   }|
182    #       { OID id-sha256 PARAMETERS NULL }|
183    #       { OID id-sha384 PARAMETERS NULL }|
184    #       { OID id-sha512 PARAMETERS NULL }
185    #   }
186    #
187    # Appendix B.1 also says that for SHA-1/-2 algorithms, the parameters
188    # should be omitted. They may be present, but when they are, they shall
189    # have NULL value.
190
191    digestAlgo = DerSequence([ DerObjectId(msg_hash.oid).encode() ])
192
193    if with_hash_parameters:
194        digestAlgo.append(DerNull().encode())
195
196    digest      = DerOctetString(msg_hash.digest())
197    digestInfo  = DerSequence([
198                    digestAlgo.encode(),
199                    digest.encode()
200                    ]).encode()
201
202    # We need at least 11 bytes for the remaining data: 3 fixed bytes and
203    # at least 8 bytes of padding).
204    if emLen<len(digestInfo)+11:
205        raise TypeError("Selected hash algorithm has a too long digest (%d bytes)." % len(digest))
206    PS = b'\xFF' * (emLen - len(digestInfo) - 3)
207    return b'\x00\x01' + PS + b'\x00' + digestInfo
208
209def new(rsa_key):
210    """Create a signature object for creating
211    or verifying PKCS#1 v1.5 signatures.
212
213    :parameter rsa_key:
214      The RSA key to use for signing or verifying the message.
215      This is a :class:`Crypto.PublicKey.RSA` object.
216      Signing is only possible when ``rsa_key`` is a **private** RSA key.
217    :type rsa_key: RSA object
218
219    :return: a :class:`PKCS115_SigScheme` signature object
220    """
221    return PKCS115_SigScheme(rsa_key)
222
223