diff options
Diffstat (limited to 'frozen_deps/Crypto/Signature/PKCS1_PSS.py')
-rw-r--r-- | frozen_deps/Crypto/Signature/PKCS1_PSS.py | 355 |
1 files changed, 0 insertions, 355 deletions
diff --git a/frozen_deps/Crypto/Signature/PKCS1_PSS.py b/frozen_deps/Crypto/Signature/PKCS1_PSS.py deleted file mode 100644 index 319851e..0000000 --- a/frozen_deps/Crypto/Signature/PKCS1_PSS.py +++ /dev/null @@ -1,355 +0,0 @@ -# -*- 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 - - -__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 range(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 range(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 range(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) - |