cryptutil.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. """Module containing a cryptographic-quality source of randomness and
  2. other cryptographically useful functionality
  3. Python 2.4 needs no external support for this module, nor does Python
  4. 2.3 on a system with /dev/urandom.
  5. Other configurations will need a quality source of random bytes and
  6. access to a function that will convert binary strings to long
  7. integers. This module will work with the Python Cryptography Toolkit
  8. (pycrypto) if it is present. pycrypto can be found with a search
  9. engine, but is currently found at:
  10. http://www.amk.ca/python/code/crypto
  11. """
  12. __all__ = [
  13. 'base64ToLong',
  14. 'binaryToLong',
  15. 'hmacSha1',
  16. 'hmacSha256',
  17. 'longToBase64',
  18. 'longToBinary',
  19. 'randomString',
  20. 'randrange',
  21. 'sha1',
  22. 'sha256',
  23. ]
  24. import hmac
  25. import os
  26. import random
  27. from openid.oidutil import toBase64, fromBase64
  28. import hashlib
  29. class HashContainer(object):
  30. def __init__(self, hash_constructor):
  31. self.new = hash_constructor
  32. self.digest_size = hash_constructor().digest_size
  33. sha1_module = HashContainer(hashlib.sha1)
  34. sha256_module = HashContainer(hashlib.sha256)
  35. def hmacSha1(key, text):
  36. if isinstance(key, str):
  37. key = bytes(key, encoding="utf-8")
  38. if isinstance(text, str):
  39. text = bytes(text, encoding="utf-8")
  40. return hmac.new(key, text, sha1_module).digest()
  41. def sha1(s):
  42. if isinstance(s, str):
  43. s = bytes(s, encoding="utf-8")
  44. return sha1_module.new(s).digest()
  45. def hmacSha256(key, text):
  46. if isinstance(key, str):
  47. key = bytes(key, encoding="utf-8")
  48. if isinstance(text, str):
  49. text = bytes(text, encoding="utf-8")
  50. return hmac.new(key, text, sha256_module).digest()
  51. def sha256(s):
  52. if isinstance(s, str):
  53. s = bytes(s, encoding="utf-8")
  54. return sha256_module.new(s).digest()
  55. SHA256_AVAILABLE = True
  56. try:
  57. from Crypto.Util.number import long_to_bytes, bytes_to_long
  58. except ImportError:
  59. # In the case where we don't have pycrypto installed, define substitute
  60. # functionality.
  61. import pickle
  62. def longToBinary(l):
  63. if l == 0:
  64. return b'\x00'
  65. b = bytearray(pickle.encode_long(l))
  66. b.reverse()
  67. return bytes(b)
  68. def binaryToLong(s):
  69. if isinstance(s, str):
  70. s = s.encode("utf-8")
  71. b = bytearray(s)
  72. b.reverse()
  73. return pickle.decode_long(bytes(b))
  74. else:
  75. # We have pycrypto, so wrap its functions instead.
  76. def longToBinary(l):
  77. if l < 0:
  78. raise ValueError('This function only supports positive integers')
  79. bytestring = long_to_bytes(l)
  80. if bytestring[0] > 127:
  81. return b'\x00' + bytestring
  82. else:
  83. return bytestring
  84. def binaryToLong(bytestring):
  85. if not bytestring:
  86. raise ValueError('Empty string passed to strToLong')
  87. if bytestring[0] > 127:
  88. raise ValueError('This function only supports positive integers')
  89. return bytes_to_long(bytestring)
  90. # A cryptographically safe source of random bytes
  91. getBytes = os.urandom
  92. # A randrange function that works for longs
  93. randrange = random.randrange
  94. def longToBase64(l):
  95. return toBase64(longToBinary(l))
  96. def base64ToLong(s):
  97. return binaryToLong(fromBase64(s))
  98. def randomString(length, chrs=None):
  99. """Produce a string of length random bytes, chosen from chrs."""
  100. if chrs is None:
  101. return getBytes(length)
  102. else:
  103. n = len(chrs)
  104. return ''.join([chrs[randrange(n)] for _ in range(length)])
  105. def const_eq(s1, s2):
  106. if len(s1) != len(s2):
  107. return False
  108. result = True
  109. for i in range(len(s1)):
  110. result = result and (s1[i] == s2[i])
  111. return result