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