Package openid :: Module cryptutil
[frames] | no frames]

Source Code for Module openid.cryptutil

  1  """Module containing a cryptographic-quality source of randomness and 
  2  other cryptographically useful functionality 
  3   
  4  Python 2.4 needs no external support for this module, nor does Python 
  5  2.3 on a system with /dev/urandom. 
  6   
  7  Other configurations will need a quality source of random bytes and 
  8  access to a function that will convert binary strings to long 
  9  integers. This module will work with the Python Cryptography Toolkit 
 10  (pycrypto) if it is present. pycrypto can be found with a search 
 11  engine, but is currently found at: 
 12   
 13  http://www.amk.ca/python/code/crypto 
 14  """ 
 15   
 16  __all__ = [ 
 17      'base64ToLong', 
 18      'binaryToLong', 
 19      'hmacSha1', 
 20      'hmacSha256', 
 21      'longToBase64', 
 22      'longToBinary', 
 23      'randomString', 
 24      'randrange', 
 25      'sha1', 
 26      'sha256', 
 27      ] 
 28   
 29  import hmac 
 30  import os 
 31  import random 
 32   
 33  from openid.oidutil import toBase64, fromBase64 
 34   
 35  try: 
 36      import hashlib 
 37  except ImportError: 
 38      import sha as sha1_module 
 39   
 40      try: 
 41          from Crypto.Hash import SHA256 as sha256_module 
 42      except ImportError: 
 43          sha256_module = None 
 44   
 45  else: 
46 - class HashContainer(object):
47 - def __init__(self, hash_constructor):
48 self.new = hash_constructor 49 self.digest_size = hash_constructor().digest_size
50 51 sha1_module = HashContainer(hashlib.sha1) 52 sha256_module = HashContainer(hashlib.sha256) 53
54 -def hmacSha1(key, text):
55 return hmac.new(key, text, sha1_module).digest()
56
57 -def sha1(s):
58 return sha1_module.new(s).digest()
59 60 if sha256_module is not None:
61 - def hmacSha256(key, text):
62 return hmac.new(key, text, sha256_module).digest()
63
64 - def sha256(s):
65 return sha256_module.new(s).digest()
66 67 SHA256_AVAILABLE = True 68 69 else: 70 _no_sha256 = NotImplementedError( 71 'Use Python 2.5, install pycrypto or install hashlib to use SHA256') 72
73 - def hmacSha256(unused_key, unused_text):
74 raise _no_sha256
75
76 - def sha256(s):
77 raise _no_sha256
78 79 SHA256_AVAILABLE = False 80 81 try: 82 from Crypto.Util.number import long_to_bytes, bytes_to_long 83 except ImportError: 84 import pickle 85 try: 86 # Check Python compatiblity by raising an exception on import 87 # if the needed functionality is not present. Present in 88 # Python >= 2.3 89 pickle.encode_long 90 pickle.decode_long 91 except AttributeError: 92 raise ImportError( 93 'No functionality for serializing long integers found') 94 95 # Present in Python >= 2.4 96 try: 97 reversed 98 except NameError:
99 - def reversed(seq):
100 return map(seq.__getitem__, xrange(len(seq) - 1, -1, -1))
101
102 - def longToBinary(l):
103 if l == 0: 104 return '\x00' 105 106 return ''.join(reversed(pickle.encode_long(l)))
107
108 - def binaryToLong(s):
109 return pickle.decode_long(''.join(reversed(s)))
110 else: 111 # We have pycrypto 112
113 - def longToBinary(l):
114 if l < 0: 115 raise ValueError('This function only supports positive integers') 116 117 bytes = long_to_bytes(l) 118 if ord(bytes[0]) > 127: 119 return '\x00' + bytes 120 else: 121 return bytes
122
123 - def binaryToLong(bytes):
124 if not bytes: 125 raise ValueError('Empty string passed to strToLong') 126 127 if ord(bytes[0]) > 127: 128 raise ValueError('This function only supports positive integers') 129 130 return bytes_to_long(bytes)
131 132 # A cryptographically safe source of random bytes 133 try: 134 getBytes = os.urandom 135 except AttributeError: 136 try: 137 from Crypto.Util.randpool import RandomPool 138 except ImportError: 139 # Fall back on /dev/urandom, if present. It would be nice to 140 # have Windows equivalent here, but for now, require pycrypto 141 # on Windows. 142 try: 143 _urandom = file('/dev/urandom', 'rb') 144 except IOError: 145 raise ImportError('No adequate source of randomness found!') 146 else:
147 - def getBytes(n):
148 bytes = [] 149 while n: 150 chunk = _urandom.read(n) 151 n -= len(chunk) 152 bytes.append(chunk) 153 assert n >= 0 154 return ''.join(bytes)
155 else: 156 _pool = RandomPool()
157 - def getBytes(n, pool=_pool):
158 if pool.entropy < n: 159 pool.randomize() 160 return pool.get_bytes(n)
161 162 # A randrange function that works for longs 163 try: 164 randrange = random.SystemRandom().randrange 165 except AttributeError: 166 # In Python 2.2's random.Random, randrange does not support 167 # numbers larger than sys.maxint for randrange. For simplicity, 168 # use this implementation for any Python that does not have 169 # random.SystemRandom 170 from math import log, ceil 171 172 _duplicate_cache = {}
173 - def randrange(start, stop=None, step=1):
174 if stop is None: 175 stop = start 176 start = 0 177 178 r = (stop - start) // step 179 try: 180 (duplicate, nbytes) = _duplicate_cache[r] 181 except KeyError: 182 rbytes = longToBinary(r) 183 if rbytes[0] == '\x00': 184 nbytes = len(rbytes) - 1 185 else: 186 nbytes = len(rbytes) 187 188 mxrand = (256 ** nbytes) 189 190 # If we get a number less than this, then it is in the 191 # duplicated range. 192 duplicate = mxrand % r 193 194 if len(_duplicate_cache) > 10: 195 _duplicate_cache.clear() 196 197 _duplicate_cache[r] = (duplicate, nbytes) 198 199 while 1: 200 bytes = '\x00' + getBytes(nbytes) 201 n = binaryToLong(bytes) 202 # Keep looping if this value is in the low duplicated range 203 if n >= duplicate: 204 break 205 206 return start + (n % r) * step
207
208 -def longToBase64(l):
209 return toBase64(longToBinary(l))
210
211 -def base64ToLong(s):
212 return binaryToLong(fromBase64(s))
213
214 -def randomString(length, chrs=None):
215 """Produce a string of length random bytes, chosen from chrs.""" 216 if chrs is None: 217 return getBytes(length) 218 else: 219 n = len(chrs) 220 return ''.join([chrs[randrange(n)] for _ in xrange(length)])
221
222 -def const_eq(s1, s2):
223 if len(s1) != len(s2): 224 return False 225 226 result = True 227 for i in range(len(s1)): 228 result = result and (s1[i] == s2[i]) 229 230 return result
231