Updated DB_Helper by adding firebase methods.
This commit is contained in:
parent
485cc3bbba
commit
c82121d036
1810 changed files with 537281 additions and 1 deletions
383
venv/Lib/site-packages/Crypto/Signature/pss.py
Normal file
383
venv/Lib/site-packages/Crypto/Signature/pss.py
Normal file
|
@ -0,0 +1,383 @@
|
|||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""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``.
|
||||
|
||||
The following example shows how the sender can create the signatue of
|
||||
a message using their private key:
|
||||
|
||||
>>> from Crypto.Signature import pss
|
||||
>>> from Crypto.Hash import SHA256
|
||||
>>> from Crypto.PublicKey import RSA
|
||||
>>> from Crypto import Random
|
||||
>>>
|
||||
>>> message = 'To be signed'
|
||||
>>> key = RSA.importKey(open('privkey.der').read())
|
||||
>>> h = SHA256.new(message)
|
||||
>>> signature = pss.new(key).sign(h)
|
||||
|
||||
At the receiver side, verification can be done using the public RSA key:
|
||||
|
||||
>>> key = RSA.importKey(open('pubkey.der').read())
|
||||
>>> h = SHA256.new(message)
|
||||
>>> verifier = pss.new(key)
|
||||
>>> try:
|
||||
>>> verifier.verify(h, signature):
|
||||
>>> print "The signature is authentic."
|
||||
>>> except (ValueError, TypeError):
|
||||
>>> print "The signature is not authentic."
|
||||
|
||||
:undocumented: __package__
|
||||
|
||||
.. __: http://www.ietf.org/rfc/rfc3447.txt
|
||||
.. __: http://www.rsa.com/rsalabs/node.asp?id=2125
|
||||
"""
|
||||
|
||||
from Crypto.Util.py3compat import b, bchr, bord
|
||||
import Crypto.Util.number
|
||||
from Crypto.Util.number import (ceil_div,
|
||||
long_to_bytes,
|
||||
bytes_to_long
|
||||
)
|
||||
from Crypto.Util.strxor import strxor
|
||||
from Crypto import Random
|
||||
|
||||
|
||||
class PSS_SigScheme:
|
||||
"""An instance of the PKCS#1 PSS signature scheme for a specific RSA key."""
|
||||
|
||||
def __init__(self, key, mgfunc, saltLen, randfunc):
|
||||
"""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 : integer
|
||||
Length of the salt, in bytes.
|
||||
randfunc : callable
|
||||
A function that returns random bytes.
|
||||
"""
|
||||
|
||||
self._key = key
|
||||
self._saltLen = saltLen
|
||||
self._mgfunc = mgfunc
|
||||
self._randfunc = randfunc
|
||||
|
||||
def can_sign(self):
|
||||
"""Return True if this cipher object can be used
|
||||
or signing messages."""
|
||||
return self._key.has_private()
|
||||
|
||||
def sign(self, msg_hash):
|
||||
"""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:
|
||||
msg_hash : 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 byte 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.
|
||||
"""
|
||||
|
||||
# Set defaults for salt length and mask generation function
|
||||
if self._saltLen is None:
|
||||
sLen = msg_hash.digest_size
|
||||
else:
|
||||
sLen = self._saltLen
|
||||
|
||||
if self._mgfunc is None:
|
||||
mgf = lambda x, y: MGF1(x, y, msg_hash)
|
||||
else:
|
||||
mgf = self._mgfunc
|
||||
|
||||
modBits = Crypto.Util.number.size(self._key.n)
|
||||
|
||||
# See 8.1.1 in RFC3447
|
||||
k = ceil_div(modBits, 8) # k is length in bytes of the modulus
|
||||
# Step 1
|
||||
em = _EMSA_PSS_ENCODE(msg_hash, modBits-1, self._randfunc, mgf, sLen)
|
||||
# Step 2a (OS2IP)
|
||||
em_int = bytes_to_long(em)
|
||||
# Step 2b (RSASP1)
|
||||
m_int = self._key._decrypt(em_int)
|
||||
# Step 2c (I2OSP)
|
||||
signature = long_to_bytes(m_int, k)
|
||||
return signature
|
||||
|
||||
def verify(self, msg_hash, signature):
|
||||
"""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:
|
||||
msg_hash : hash object
|
||||
The cryptographic hash computed over the message.
|
||||
This is an object belonging to the `Crypto.Hash` module.
|
||||
signature : byte string
|
||||
The signature that needs to be validated.
|
||||
|
||||
:Raise ValueError:
|
||||
if the signature is incorrect.
|
||||
"""
|
||||
|
||||
# Set defaults for salt length and mask generation function
|
||||
if self._saltLen is None:
|
||||
sLen = msg_hash.digest_size
|
||||
else:
|
||||
sLen = self._saltLen
|
||||
if self._mgfunc:
|
||||
mgf = self._mgfunc
|
||||
else:
|
||||
mgf = lambda x, y: MGF1(x, y, msg_hash)
|
||||
|
||||
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(signature) != k:
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 2a (O2SIP)
|
||||
signature_int = bytes_to_long(signature)
|
||||
# Step 2b (RSAVP1)
|
||||
em_int = self._key._encrypt(signature_int)
|
||||
# Step 2c (I2OSP)
|
||||
emLen = ceil_div(modBits - 1, 8)
|
||||
em = long_to_bytes(em_int, emLen)
|
||||
# Step 3/4
|
||||
_EMSA_PSS_VERIFY(msg_hash, em, modBits-1, mgf, sLen)
|
||||
|
||||
|
||||
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)
|
||||
hobj = hash.new()
|
||||
hobj.update(mgfSeed + c)
|
||||
T = T + hobj.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 = randFunc(sLen)
|
||||
# Step 5
|
||||
m_prime = bchr(0)*8 + mhash.digest() + salt
|
||||
# Step 6
|
||||
h = mhash.new()
|
||||
h.update(m_prime)
|
||||
# Step 7
|
||||
ps = bchr(0)*(emLen-sLen-mhash.digest_size-2)
|
||||
# Step 8
|
||||
db = ps + bchr(1) + 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.
|
||||
|
||||
:Raise ValueError:
|
||||
When the encoding is inconsistent, or the digest or salt lengths
|
||||
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:
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 5
|
||||
maskedDB = em[:emLen-mhash.digest_size-1]
|
||||
h = em[emLen-mhash.digest_size-1:-1]
|
||||
# Step 6
|
||||
if lmask & bord(em[0]):
|
||||
raise ValueError("Incorrect signature")
|
||||
# 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(0)*(emLen-mhash.digest_size-sLen-2) + bchr(1)):
|
||||
raise ValueError("Incorrect signature")
|
||||
# Step 11
|
||||
if sLen > 0:
|
||||
salt = db[-sLen:]
|
||||
else:
|
||||
salt = b("")
|
||||
# Step 12
|
||||
m_prime = bchr(0)*8 + mhash.digest() + salt
|
||||
# Step 13
|
||||
hobj = mhash.new()
|
||||
hobj.update(m_prime)
|
||||
hp = hobj.digest()
|
||||
# Step 14
|
||||
if h != hp:
|
||||
raise ValueError("Incorrect signature")
|
||||
|
||||
|
||||
def new(rsa_key, **kwargs):
|
||||
"""Return a signature scheme object `PSS_SigScheme` that
|
||||
can be used to perform PKCS#1 PSS signature or verification.
|
||||
|
||||
:Parameters:
|
||||
rsa_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.
|
||||
:Keywords:
|
||||
mask_func : callable
|
||||
A mask generation function that accepts two parameters: a string to
|
||||
use as seed, and the length of the mask in bytes to generate.
|
||||
If not specified, the standard MGF1 is used.
|
||||
salt_bytes : int
|
||||
Length of the salt, in bytes.
|
||||
If not specified, it matches the output size of the hash function.
|
||||
If zero, the signature scheme becomes deterministic.
|
||||
rand_func : callable
|
||||
A function that returns random bytes.
|
||||
The default is `Crypto.Random.get_random_bytes`.
|
||||
"""
|
||||
|
||||
mask_func = kwargs.pop("mask_func", None)
|
||||
salt_len = kwargs.pop("salt_bytes", None)
|
||||
rand_func = kwargs.pop("rand_func", None)
|
||||
if rand_func is None:
|
||||
rand_func = Random.get_random_bytes
|
||||
if kwargs:
|
||||
raise ValueError("Unknown keywords: " + str(list(kwargs.keys())))
|
||||
return PSS_SigScheme(rsa_key, mask_func, salt_len, rand_func)
|
Loading…
Add table
Add a link
Reference in a new issue