Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: third_party/google-endpoints/Crypto/Signature/PKCS1_v1_5.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # -*- coding: utf-8 -*-
2 #
3 # Signature/PKCS1-v1_5.py : PKCS#1 v1.5
4 #
5 # ===================================================================
6 # The contents of this file are dedicated to the public domain. To
7 # the extent that dedication to the public domain is not available,
8 # everyone is granted a worldwide, perpetual, royalty-free,
9 # non-exclusive license to exercise all rights associated with the
10 # contents of this file for any purpose whatsoever.
11 # No rights are reserved.
12 #
13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
17 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 # SOFTWARE.
21 # ===================================================================
22
23 """
24 RSA digital signature protocol according to PKCS#1 v1.5
25
26 See RFC3447__ or the `original RSA Labs specification`__.
27
28 This scheme is more properly called ``RSASSA-PKCS1-v1_5``.
29
30 For example, a sender may authenticate a message using SHA-1 like
31 this:
32
33 >>> from Crypto.Signature import PKCS1_v1_5
34 >>> from Crypto.Hash import SHA
35 >>> from Crypto.PublicKey import RSA
36 >>>
37 >>> message = 'To be signed'
38 >>> key = RSA.importKey(open('privkey.der').read())
39 >>> h = SHA.new(message)
40 >>> signer = PKCS1_v1_5.new(key)
41 >>> signature = signer.sign(h)
42
43 At the receiver side, verification can be done using the public part of
44 the RSA key:
45
46 >>> key = RSA.importKey(open('pubkey.der').read())
47 >>> h = SHA.new(message)
48 >>> verifier = PKCS1_v1_5.new(key)
49 >>> if verifier.verify(h, signature):
50 >>> print "The signature is authentic."
51 >>> else:
52 >>> print "The signature is not authentic."
53
54 :undocumented: __revision__, __package__
55
56 .. __: http://www.ietf.org/rfc/rfc3447.txt
57 .. __: http://www.rsa.com/rsalabs/node.asp?id=2125
58 """
59
60 __revision__ = "$Id$"
61 __all__ = [ 'new', 'PKCS115_SigScheme' ]
62
63 import Crypto.Util.number
64 from Crypto.Util.number import ceil_div
65 from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString
66 from Crypto.Util.py3compat import *
67
68 class PKCS115_SigScheme:
69 """This signature scheme can perform PKCS#1 v1.5 RSA signature or verificati on."""
70
71 def __init__(self, key):
72 """Initialize this PKCS#1 v1.5 signature scheme object.
73
74 :Parameters:
75 key : an RSA key object
76 If a private half is given, both signature and verification are possib le.
77 If a public half is given, only verification is possible.
78 """
79 self._key = key
80
81 def can_sign(self):
82 """Return True if this cipher object can be used for signing messages."" "
83 return self._key.has_private()
84
85 def sign(self, mhash):
86 """Produce the PKCS#1 v1.5 signature of a message.
87
88 This function is named ``RSASSA-PKCS1-V1_5-SIGN``, and is specified in
89 section 8.2.1 of RFC3447.
90
91 :Parameters:
92 mhash : hash object
93 The hash that was carried out over the message. This is an objec t
94 belonging to the `Crypto.Hash` module.
95
96 :Return: The signature encoded as a string.
97 :Raise ValueError:
98 If the RSA key length is not sufficiently long to deal with the give n
99 hash algorithm.
100 :Raise TypeError:
101 If the RSA key has no private half.
102 """
103 # TODO: Verify the key is RSA
104
105 # See 8.2.1 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 em = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
111 # Step 2a (OS2IP) and 2b (RSASP1)
112 m = self._key.decrypt(em)
113 # Step 2c (I2OSP)
114 S = bchr(0x00)*(k-len(m)) + m
115 return S
116
117 def verify(self, mhash, S):
118 """Verify that a certain PKCS#1 v1.5 signature is authentic.
119
120 This function checks if the party holding the private half of the key
121 really signed the message.
122
123 This function is named ``RSASSA-PKCS1-V1_5-VERIFY``, and is specified in
124 section 8.2.2 of RFC3447.
125
126 :Parameters:
127 mhash : hash object
128 The hash that was carried out over the message. This is an objec t
129 belonging to the `Crypto.Hash` module.
130 S : string
131 The signature that needs to be validated.
132
133 :Return: True if verification is correct. False otherwise.
134 """
135 # TODO: Verify the key is RSA
136
137 # See 8.2.2 in RFC3447
138 modBits = Crypto.Util.number.size(self._key.n)
139 k = ceil_div(modBits,8) # Convert from bits to bytes
140
141 # Step 1
142 if len(S) != k:
143 return 0
144 # Step 2a (O2SIP) and 2b (RSAVP1)
145 # Note that signature must be smaller than the module
146 # but RSA.py won't complain about it.
147 # TODO: Fix RSA object; don't do it here.
148 m = self._key.encrypt(S, 0)[0]
149 # Step 2c (I2OSP)
150 em1 = bchr(0x00)*(k-len(m)) + m
151 # Step 3
152 try:
153 em2 = EMSA_PKCS1_V1_5_ENCODE(mhash, k)
154 except ValueError:
155 return 0
156 # Step 4
157 # By comparing the full encodings (as opposed to checking each
158 # of its components one at a time) we avoid attacks to the padding
159 # scheme like Bleichenbacher's (see http://www.mail-archive.com/cryptogr aphy@metzdowd.com/msg06537).
160 #
161 return em1==em2
162
163 def EMSA_PKCS1_V1_5_ENCODE(hash, emLen):
164 """
165 Implement the ``EMSA-PKCS1-V1_5-ENCODE`` function, as defined
166 in PKCS#1 v2.1 (RFC3447, 9.2).
167
168 ``EMSA-PKCS1-V1_5-ENCODE`` actually accepts the message ``M`` as input,
169 and hash it internally. Here, we expect that the message has already
170 been hashed instead.
171
172 :Parameters:
173 hash : hash object
174 The hash object that holds the digest of the message being signed.
175 emLen : int
176 The length the final encoding must have, in bytes.
177
178 :attention: the early standard (RFC2313) stated that ``DigestInfo``
179 had to be BER-encoded. This means that old signatures
180 might have length tags in indefinite form, which
181 is not supported in DER. Such encoding cannot be
182 reproduced by this function.
183
184 :attention: the same standard defined ``DigestAlgorithm`` to be
185 of ``AlgorithmIdentifier`` type, where the PARAMETERS
186 item is optional. Encodings for ``MD2/4/5`` without
187 ``PARAMETERS`` cannot be reproduced by this function.
188
189 :Return: An ``emLen`` byte long string that encodes the hash.
190 """
191
192 # First, build the ASN.1 DER object DigestInfo:
193 #
194 # DigestInfo ::= SEQUENCE {
195 # digestAlgorithm AlgorithmIdentifier,
196 # digest OCTET STRING
197 # }
198 #
199 # where digestAlgorithm identifies the hash function and shall be an
200 # algorithm ID with an OID in the set PKCS1-v1-5DigestAlgorithms.
201 #
202 # PKCS1-v1-5DigestAlgorithms ALGORITHM-IDENTIFIER ::= {
203 # { OID id-md2 PARAMETERS NULL }|
204 # { OID id-md5 PARAMETERS NULL }|
205 # { OID id-sha1 PARAMETERS NULL }|
206 # { OID id-sha256 PARAMETERS NULL }|
207 # { OID id-sha384 PARAMETERS NULL }|
208 # { OID id-sha512 PARAMETERS NULL }
209 # }
210 #
211 digestAlgo = DerSequence([hash.oid, DerNull().encode()])
212 digest = DerOctetString(hash.digest())
213 digestInfo = DerSequence([
214 digestAlgo.encode(),
215 digest.encode()
216 ]).encode()
217
218 # We need at least 11 bytes for the remaining data: 3 fixed bytes and
219 # at least 8 bytes of padding).
220 if emLen<len(digestInfo)+11:
221 raise ValueError("Selected hash algorith has a too long digest (%d bytes )." % len(digest))
222 PS = bchr(0xFF) * (emLen - len(digestInfo) - 3)
223 return b("\x00\x01") + PS + bchr(0x00) + digestInfo
224
225 def new(key):
226 """Return a signature scheme object `PKCS115_SigScheme` that
227 can be used to perform PKCS#1 v1.5 signature or verification.
228
229 :Parameters:
230 key : RSA key object
231 The key to use to sign or verify the message. This is a `Crypto.PublicKey. RSA` object.
232 Signing is only possible if *key* is a private RSA key.
233
234 """
235 return PKCS115_SigScheme(key)
236
OLDNEW
« no previous file with comments | « third_party/google-endpoints/Crypto/Signature/PKCS1_PSS.py ('k') | third_party/google-endpoints/Crypto/Signature/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698