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
187
venv/Lib/site-packages/jws/algos.py
Normal file
187
venv/Lib/site-packages/jws/algos.py
Normal file
|
@ -0,0 +1,187 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
import re
|
||||
|
||||
from .exceptions import SignatureError, RouteMissingError, RouteEndpointError
|
||||
from .utils import to_bytes_2and3, constant_time_compare
|
||||
|
||||
class AlgorithmBase(object):
|
||||
"""Base for algorithm support classes."""
|
||||
pass
|
||||
|
||||
class HasherBase(AlgorithmBase):
|
||||
"""
|
||||
Base for algos which need a hash function. The ``bits`` param can be
|
||||
passed in from the capturing group of the routing regexp
|
||||
"""
|
||||
supported_bits = (256, 384, 512)
|
||||
def __init__(self, bits):
|
||||
"""
|
||||
Determine if the algorithm supports the requested bit depth and set up
|
||||
matching hash method from ``hashlib`` if necessary.
|
||||
"""
|
||||
self.bits = int(bits)
|
||||
if self.bits not in self.supported_bits:
|
||||
raise NotImplementedError("%s implements %s bit algorithms (given %d)" %
|
||||
(self.__class__, ', '.join(self.supported_bits), self.bits))
|
||||
if not getattr(self, 'hasher', None):
|
||||
import hashlib
|
||||
self.hasher = getattr(hashlib, 'sha%d' % self.bits)
|
||||
|
||||
class HMAC(HasherBase):
|
||||
"""
|
||||
Support for HMAC signing.
|
||||
"""
|
||||
def sign(self, msg, key):
|
||||
import hmac
|
||||
if sys.version < '3':
|
||||
utfkey = unicode(key).encode('utf8')
|
||||
else:
|
||||
utfkey = to_bytes_2and3(key)
|
||||
msg = to_bytes_2and3(msg)
|
||||
return hmac.new(utfkey, msg, self.hasher).digest()
|
||||
|
||||
def verify(self, msg, crypto, key):
|
||||
if not constant_time_compare(self.sign(msg, key), crypto):
|
||||
raise SignatureError("Could not validate signature")
|
||||
return True
|
||||
|
||||
class RSABase(HasherBase):
|
||||
"""
|
||||
Support for RSA signing.
|
||||
|
||||
The ``Crypto`` package >= 2.5 is required.
|
||||
|
||||
"""
|
||||
supported_bits = (256,384,512,) #:Seems to worka > 256
|
||||
|
||||
def __init__(self, padder, bits):
|
||||
super(RSABase,self).__init__(bits)
|
||||
self.padder = padder
|
||||
from Crypto.Hash import SHA256,SHA384,SHA512
|
||||
self.hashm = __import__('Crypto.Hash.SHA%d'%self.bits, globals(), locals(), ['*']).new()
|
||||
|
||||
def sign(self, msg, key):
|
||||
"""
|
||||
Signs a message with an RSA PrivateKey and hash method
|
||||
"""
|
||||
import Crypto.PublicKey.RSA as RSA
|
||||
|
||||
self.hashm.update(msg.encode('UTF-8'))
|
||||
## assume we are dealing with a real key
|
||||
# private_key = RSA.importKey(key)
|
||||
return self.padder.new(key).sign(self.hashm) # pycrypto 2.5
|
||||
|
||||
def verify(self, msg, crypto, key):
|
||||
"""
|
||||
Verifies a message using RSA cryptographic signature and key.
|
||||
|
||||
``crypto`` is the cryptographic signature
|
||||
``key`` is the verifying key. Can be a real key object or a string.
|
||||
"""
|
||||
import Crypto.PublicKey.RSA as RSA
|
||||
|
||||
self.hashm.update(msg.encode('UTF-8'))
|
||||
private_key = key
|
||||
if not isinstance(key, RSA._RSAobj):
|
||||
private_key = RSA.importKey(key)
|
||||
if not self.padder.new( private_key ).verify(self.hashm, crypto): #:pycrypto 2.5
|
||||
raise SignatureError("Could not validate signature")
|
||||
return True
|
||||
|
||||
class RSA_PKCS1_5(RSABase):
|
||||
def __init__(self, bits):
|
||||
import Crypto.Signature.PKCS1_v1_5 as PKCS
|
||||
super(RSA_PKCS1_5,self).__init__(PKCS, bits)
|
||||
|
||||
class RSA_PSS(RSABase):
|
||||
def __init__(self, bits):
|
||||
import Crypto.Signature.PKCS1_PSS as PSS
|
||||
super(RSA_PSS,self).__init__(PSS, bits)
|
||||
|
||||
class ECDSA(HasherBase):
|
||||
"""
|
||||
Support for ECDSA signing. This is the preferred algorithm for private/public key
|
||||
verification.
|
||||
|
||||
The ``ecdsa`` package is required. ``pip install ecdsa``
|
||||
"""
|
||||
bits_to_curve = {
|
||||
256: 'NIST256p',
|
||||
384: 'NIST384p',
|
||||
512: 'NIST521p',
|
||||
}
|
||||
def sign(self, msg, key):
|
||||
"""
|
||||
Signs a message with an ECDSA SigningKey and hash method matching the
|
||||
bit depth of curve algorithm.
|
||||
"""
|
||||
import ecdsa
|
||||
## assume the signing key is already a real key
|
||||
# curve = getattr(ecdsa, self.bits_to_curve[self.bits])
|
||||
# signing_key = ecdsa.SigningKey.from_string(key, curve=curve)
|
||||
msg = to_bytes_2and3(msg)
|
||||
return key.sign(msg, hashfunc=self.hasher)
|
||||
|
||||
def verify(self, msg, crypto, key):
|
||||
"""
|
||||
Verifies a message using ECDSA cryptographic signature and key.
|
||||
|
||||
``crypto`` is the cryptographic signature
|
||||
``key`` is the verifying key. Can be a real key object or a string.
|
||||
"""
|
||||
import ecdsa
|
||||
curve = getattr(ecdsa, self.bits_to_curve[self.bits])
|
||||
vk = key
|
||||
if not isinstance(vk, ecdsa.VerifyingKey):
|
||||
vk = ecdsa.VerifyingKey.from_string(key, curve=curve)
|
||||
try:
|
||||
vk.verify(crypto, to_bytes_2and3(msg), hashfunc=self.hasher)
|
||||
except ecdsa.BadSignatureError:
|
||||
raise SignatureError("Could not validate signature")
|
||||
except AssertionError:
|
||||
raise SignatureError("Could not validate signature")
|
||||
return True
|
||||
|
||||
# algorithm routing
|
||||
def route(name):
|
||||
return resolve(*find(name))
|
||||
|
||||
def find(name):
|
||||
# TODO: more error checking around custom algorithms
|
||||
algorithms = CUSTOM + list(DEFAULT)
|
||||
for (route, endpoint) in algorithms:
|
||||
match = re.match(route, name)
|
||||
if match:
|
||||
return (endpoint, match)
|
||||
raise RouteMissingError('endpoint matching %s could not be found' % name)
|
||||
|
||||
def resolve(endpoint, match):
|
||||
if callable(endpoint):
|
||||
# send result back through
|
||||
return resolve(endpoint(**match.groupdict()), match)
|
||||
|
||||
# get the sign and verify methods from dict or obj
|
||||
try:
|
||||
crypt = { 'sign': endpoint['sign'], 'verify': endpoint['verify'] }
|
||||
except TypeError:
|
||||
try:
|
||||
crypt = { 'sign': endpoint.sign, 'verify': endpoint.verify }
|
||||
except AttributeError as e:
|
||||
raise RouteEndpointError('route enpoint must have sign, verify as attributes or items of dict')
|
||||
# verify callability
|
||||
try:
|
||||
assert callable(crypt['sign'])
|
||||
assert callable(crypt['verify'])
|
||||
except AssertionError as e:
|
||||
raise RouteEndpointError('sign, verify of endpoint must be callable')
|
||||
return crypt
|
||||
|
||||
DEFAULT = (
|
||||
(r'^HS(?P<bits>256|384|512)$', HMAC),
|
||||
(r'^RS(?P<bits>256|384|512)$', RSA_PKCS1_5),
|
||||
(r'^PS(?P<bits>256|384|512)$', RSA_PSS),
|
||||
(r'^ES(?P<bits>256|384|512)$', ECDSA),
|
||||
)
|
||||
CUSTOM = []
|
Loading…
Add table
Add a link
Reference in a new issue