Index: third_party/google-endpoints/Crypto/Signature/PKCS1_PSS.py |
diff --git a/third_party/google-endpoints/Crypto/Signature/PKCS1_PSS.py b/third_party/google-endpoints/Crypto/Signature/PKCS1_PSS.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4f50eb854cc2b76f43da909b06fd81b3fb962437 |
--- /dev/null |
+++ b/third_party/google-endpoints/Crypto/Signature/PKCS1_PSS.py |
@@ -0,0 +1,355 @@ |
+# -*- coding: utf-8 -*- |
+# |
+# Signature/PKCS1_PSS.py : PKCS#1 PPS |
+# |
+# =================================================================== |
+# The contents of this file are dedicated to the public domain. To |
+# the extent that dedication to the public domain is not available, |
+# everyone is granted a worldwide, perpetual, royalty-free, |
+# non-exclusive license to exercise all rights associated with the |
+# contents of this file for any purpose whatsoever. |
+# No rights are reserved. |
+# |
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
+# SOFTWARE. |
+# =================================================================== |
+ |
+"""RSA digital signature protocol with appendix according to PKCS#1 PSS. |
+ |
+See RFC3447__ or the `original RSA Labs specification`__. |
+ |
+This scheme is more properly called ``RSASSA-PSS``. |
+ |
+For example, a sender may authenticate a message using SHA-1 and PSS like |
+this: |
+ |
+ >>> from Crypto.Signature import PKCS1_PSS |
+ >>> from Crypto.Hash import SHA |
+ >>> from Crypto.PublicKey import RSA |
+ >>> from Crypto import Random |
+ >>> |
+ >>> message = 'To be signed' |
+ >>> key = RSA.importKey(open('privkey.der').read()) |
+ >>> h = SHA.new() |
+ >>> h.update(message) |
+ >>> signer = PKCS1_PSS.new(key) |
+ >>> signature = PKCS1_PSS.sign(key) |
+ |
+At the receiver side, verification can be done like using the public part of |
+the RSA key: |
+ |
+ >>> key = RSA.importKey(open('pubkey.der').read()) |
+ >>> h = SHA.new() |
+ >>> h.update(message) |
+ >>> verifier = PKCS1_PSS.new(key) |
+ >>> if verifier.verify(h, signature): |
+ >>> print "The signature is authentic." |
+ >>> else: |
+ >>> print "The signature is not authentic." |
+ |
+:undocumented: __revision__, __package__ |
+ |
+.. __: http://www.ietf.org/rfc/rfc3447.txt |
+.. __: http://www.rsa.com/rsalabs/node.asp?id=2125 |
+""" |
+ |
+# Allow nested scopes in Python 2.1 |
+# See http://oreilly.com/pub/a/python/2001/04/19/pythonnews.html |
+from __future__ import nested_scopes |
+ |
+__revision__ = "$Id$" |
+__all__ = [ 'new', 'PSS_SigScheme' ] |
+ |
+from Crypto.Util.py3compat import * |
+if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
+ from Crypto.Util.py21compat import * |
+import Crypto.Util.number |
+from Crypto.Util.number import ceil_shift, ceil_div, long_to_bytes |
+from Crypto.Util.strxor import strxor |
+ |
+class PSS_SigScheme: |
+ """This signature scheme can perform PKCS#1 PSS RSA signature or verification.""" |
+ |
+ def __init__(self, key, mgfunc, saltLen): |
+ """Initialize this PKCS#1 PSS signature scheme object. |
+ |
+ :Parameters: |
+ key : an RSA key object |
+ If a private half is given, both signature and verification are possible. |
+ If a public half is given, only verification is possible. |
+ mgfunc : callable |
+ A mask generation function that accepts two parameters: a string to |
+ use as seed, and the lenth of the mask to generate, in bytes. |
+ saltLen : int |
+ Length of the salt, in bytes. |
+ """ |
+ self._key = key |
+ self._saltLen = saltLen |
+ self._mgfunc = mgfunc |
+ |
+ def can_sign(self): |
+ """Return True if this cipher object can be used for signing messages.""" |
+ return self._key.has_private() |
+ |
+ def sign(self, mhash): |
+ """Produce the PKCS#1 PSS signature of a message. |
+ |
+ This function is named ``RSASSA-PSS-SIGN``, and is specified in |
+ section 8.1.1 of RFC3447. |
+ |
+ :Parameters: |
+ mhash : hash object |
+ The hash that was carried out over the message. This is an object |
+ belonging to the `Crypto.Hash` module. |
+ |
+ :Return: The PSS signature encoded as a string. |
+ :Raise ValueError: |
+ If the RSA key length is not sufficiently long to deal with the given |
+ hash algorithm. |
+ :Raise TypeError: |
+ If the RSA key has no private half. |
+ |
+ :attention: Modify the salt length and the mask generation function only |
+ if you know what you are doing. |
+ The receiver must use the same parameters too. |
+ """ |
+ # TODO: Verify the key is RSA |
+ |
+ randfunc = self._key._randfunc |
+ |
+ # Set defaults for salt length and mask generation function |
+ if self._saltLen == None: |
+ sLen = mhash.digest_size |
+ else: |
+ sLen = self._saltLen |
+ if self._mgfunc: |
+ mgf = self._mgfunc |
+ else: |
+ mgf = lambda x,y: MGF1(x,y,mhash) |
+ |
+ modBits = Crypto.Util.number.size(self._key.n) |
+ |
+ # See 8.1.1 in RFC3447 |
+ k = ceil_div(modBits,8) # Convert from bits to bytes |
+ # Step 1 |
+ em = EMSA_PSS_ENCODE(mhash, modBits-1, randfunc, mgf, sLen) |
+ # Step 2a (OS2IP) and 2b (RSASP1) |
+ m = self._key.decrypt(em) |
+ # Step 2c (I2OSP) |
+ S = bchr(0x00)*(k-len(m)) + m |
+ return S |
+ |
+ def verify(self, mhash, S): |
+ """Verify that a certain PKCS#1 PSS signature is authentic. |
+ |
+ This function checks if the party holding the private half of the given |
+ RSA key has really signed the message. |
+ |
+ This function is called ``RSASSA-PSS-VERIFY``, and is specified in section |
+ 8.1.2 of RFC3447. |
+ |
+ :Parameters: |
+ mhash : hash object |
+ The hash that was carried out over the message. This is an object |
+ belonging to the `Crypto.Hash` module. |
+ S : string |
+ The signature that needs to be validated. |
+ |
+ :Return: True if verification is correct. False otherwise. |
+ """ |
+ # TODO: Verify the key is RSA |
+ |
+ # Set defaults for salt length and mask generation function |
+ if self._saltLen == None: |
+ sLen = mhash.digest_size |
+ else: |
+ sLen = self._saltLen |
+ if self._mgfunc: |
+ mgf = self._mgfunc |
+ else: |
+ mgf = lambda x,y: MGF1(x,y,mhash) |
+ |
+ modBits = Crypto.Util.number.size(self._key.n) |
+ |
+ # See 8.1.2 in RFC3447 |
+ k = ceil_div(modBits,8) # Convert from bits to bytes |
+ # Step 1 |
+ if len(S) != k: |
+ return False |
+ # Step 2a (O2SIP), 2b (RSAVP1), and partially 2c (I2OSP) |
+ # Note that signature must be smaller than the module |
+ # but RSA.py won't complain about it. |
+ # TODO: Fix RSA object; don't do it here. |
+ em = self._key.encrypt(S, 0)[0] |
+ # Step 2c |
+ emLen = ceil_div(modBits-1,8) |
+ em = bchr(0x00)*(emLen-len(em)) + em |
+ # Step 3 |
+ try: |
+ result = EMSA_PSS_VERIFY(mhash, em, modBits-1, mgf, sLen) |
+ except ValueError: |
+ return False |
+ # Step 4 |
+ return result |
+ |
+def MGF1(mgfSeed, maskLen, hash): |
+ """Mask Generation Function, described in B.2.1""" |
+ T = b("") |
+ for counter in xrange(ceil_div(maskLen, hash.digest_size)): |
+ c = long_to_bytes(counter, 4) |
+ T = T + hash.new(mgfSeed + c).digest() |
+ assert(len(T)>=maskLen) |
+ return T[:maskLen] |
+ |
+def EMSA_PSS_ENCODE(mhash, emBits, randFunc, mgf, sLen): |
+ """ |
+ Implement the ``EMSA-PSS-ENCODE`` function, as defined |
+ in PKCS#1 v2.1 (RFC3447, 9.1.1). |
+ |
+ The original ``EMSA-PSS-ENCODE`` actually accepts the message ``M`` as input, |
+ and hash it internally. Here, we expect that the message has already |
+ been hashed instead. |
+ |
+ :Parameters: |
+ mhash : hash object |
+ The hash object that holds the digest of the message being signed. |
+ emBits : int |
+ Maximum length of the final encoding, in bits. |
+ randFunc : callable |
+ An RNG function that accepts as only parameter an int, and returns |
+ a string of random bytes, to be used as salt. |
+ mgf : callable |
+ A mask generation function that accepts two parameters: a string to |
+ use as seed, and the lenth of the mask to generate, in bytes. |
+ sLen : int |
+ Length of the salt, in bytes. |
+ |
+ :Return: An ``emLen`` byte long string that encodes the hash |
+ (with ``emLen = \ceil(emBits/8)``). |
+ |
+ :Raise ValueError: |
+ When digest or salt length are too big. |
+ """ |
+ |
+ emLen = ceil_div(emBits,8) |
+ |
+ # Bitmask of digits that fill up |
+ lmask = 0 |
+ for i in xrange(8*emLen-emBits): |
+ lmask = lmask>>1 | 0x80 |
+ |
+ # Step 1 and 2 have been already done |
+ # Step 3 |
+ if emLen < mhash.digest_size+sLen+2: |
+ raise ValueError("Digest or salt length are too long for given key size.") |
+ # Step 4 |
+ salt = b("") |
+ if randFunc and sLen>0: |
+ salt = randFunc(sLen) |
+ # Step 5 and 6 |
+ h = mhash.new(bchr(0x00)*8 + mhash.digest() + salt) |
+ # Step 7 and 8 |
+ db = bchr(0x00)*(emLen-sLen-mhash.digest_size-2) + bchr(0x01) + salt |
+ # Step 9 |
+ dbMask = mgf(h.digest(), emLen-mhash.digest_size-1) |
+ # Step 10 |
+ maskedDB = strxor(db,dbMask) |
+ # Step 11 |
+ maskedDB = bchr(bord(maskedDB[0]) & ~lmask) + maskedDB[1:] |
+ # Step 12 |
+ em = maskedDB + h.digest() + bchr(0xBC) |
+ return em |
+ |
+def EMSA_PSS_VERIFY(mhash, em, emBits, mgf, sLen): |
+ """ |
+ Implement the ``EMSA-PSS-VERIFY`` function, as defined |
+ in PKCS#1 v2.1 (RFC3447, 9.1.2). |
+ |
+ ``EMSA-PSS-VERIFY`` actually accepts the message ``M`` as input, |
+ and hash it internally. Here, we expect that the message has already |
+ been hashed instead. |
+ |
+ :Parameters: |
+ mhash : hash object |
+ The hash object that holds the digest of the message to be verified. |
+ em : string |
+ The signature to verify, therefore proving that the sender really signed |
+ the message that was received. |
+ emBits : int |
+ Length of the final encoding (em), in bits. |
+ mgf : callable |
+ A mask generation function that accepts two parameters: a string to |
+ use as seed, and the lenth of the mask to generate, in bytes. |
+ sLen : int |
+ Length of the salt, in bytes. |
+ |
+ :Return: 0 if the encoding is consistent, 1 if it is inconsistent. |
+ |
+ :Raise ValueError: |
+ When digest or salt length are too big. |
+ """ |
+ |
+ emLen = ceil_div(emBits,8) |
+ |
+ # Bitmask of digits that fill up |
+ lmask = 0 |
+ for i in xrange(8*emLen-emBits): |
+ lmask = lmask>>1 | 0x80 |
+ |
+ # Step 1 and 2 have been already done |
+ # Step 3 |
+ if emLen < mhash.digest_size+sLen+2: |
+ return False |
+ # Step 4 |
+ if ord(em[-1:])!=0xBC: |
+ return False |
+ # Step 5 |
+ maskedDB = em[:emLen-mhash.digest_size-1] |
+ h = em[emLen-mhash.digest_size-1:-1] |
+ # Step 6 |
+ if lmask & bord(em[0]): |
+ return False |
+ # Step 7 |
+ dbMask = mgf(h, emLen-mhash.digest_size-1) |
+ # Step 8 |
+ db = strxor(maskedDB, dbMask) |
+ # Step 9 |
+ db = bchr(bord(db[0]) & ~lmask) + db[1:] |
+ # Step 10 |
+ if not db.startswith(bchr(0x00)*(emLen-mhash.digest_size-sLen-2) + bchr(0x01)): |
+ return False |
+ # Step 11 |
+ salt = b("") |
+ if sLen: salt = db[-sLen:] |
+ # Step 12 and 13 |
+ hp = mhash.new(bchr(0x00)*8 + mhash.digest() + salt).digest() |
+ # Step 14 |
+ if h!=hp: |
+ return False |
+ return True |
+ |
+def new(key, mgfunc=None, saltLen=None): |
+ """Return a signature scheme object `PSS_SigScheme` that |
+ can be used to perform PKCS#1 PSS signature or verification. |
+ |
+ :Parameters: |
+ key : RSA key object |
+ The key to use to sign or verify the message. This is a `Crypto.PublicKey.RSA` object. |
+ Signing is only possible if *key* is a private RSA key. |
+ mgfunc : callable |
+ A mask generation function that accepts two parameters: a string to |
+ use as seed, and the lenth of the mask to generate, in bytes. |
+ If not specified, the standard MGF1 is used. |
+ saltLen : int |
+ Length of the salt, in bytes. If not specified, it matches the output |
+ size of the hash function. |
+ |
+ """ |
+ return PSS_SigScheme(key, mgfunc, saltLen) |
+ |