Guest User

Untitled

a guest
Jun 8th, 2023
358
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.79 KB | None | 0 0
  1. import hmac
  2. import hashlib
  3. import struct
  4. import base64
  5.  
  6. def pbkdf2(digestmod, password: 'bytes', salt, count, dk_length) -> 'bytes':
  7.     '''
  8.    PBKDF2, from PKCS #5 v2.0:
  9.        http://tools.ietf.org/html/rfc2898
  10.  
  11.    For proper usage, see NIST Special Publication 800-132:
  12.        http://csrc.nist.gov/publications/PubsSPs.html
  13.  
  14.    The arguments for this function are:
  15.  
  16.        digestmod
  17.            a crypographic hash constructor, such as hashlib.sha256
  18.            which will be used as an argument to the hmac function.
  19.            Note that the performance difference between sha1 and
  20.            sha256 is not very big. New applications should choose
  21.            sha256 or better.
  22.  
  23.        password
  24.            The arbitrary-length password (passphrase) (bytes)
  25.  
  26.        salt
  27.            A bunch of random bytes, generated using a cryptographically
  28.            strong random number generator (such as os.urandom()). NIST
  29.            recommend the salt be _at least_ 128bits (16 bytes) long.
  30.  
  31.        count
  32.            The iteration count. Set this value as large as you can
  33.            tolerate. NIST recommend that the absolute minimum value
  34.            be 1000. However, it should generally be in the range of
  35.            tens of thousands, or however many cause about a half-second
  36.            delay to the user.
  37.  
  38.        dk_length
  39.            The lenght of the desired key in bytes. This doesn't need
  40.            to be the same size as the hash functions digest size, but
  41.            it makes sense to use a larger digest hash function if your
  42.            key size is large.
  43.  
  44.    '''
  45.     def pbkdf2_function(pw, salt, count, i):
  46.         # in the first iteration, the hmac message is the salt
  47.         # concatinated with the block number in the form of \x00\x00\x00\x01
  48.         r = u = hmac.new(pw, salt + struct.pack(">i", i), digestmod).digest()
  49.         for i in range(2, count + 1):
  50.             # in subsequent iterations, the hmac message is the
  51.             # previous hmac digest. The key is always the users password
  52.             # see the hmac specification for notes on padding and stretching
  53.             u = hmac.new(pw, u, digestmod).digest()
  54.             # this is the exclusive or of the two byte-strings
  55.             r = bytes(i ^ j for i, j in zip(r, u))
  56.         return r
  57.     dk, h_length = b'', digestmod().digest_size
  58.     # we generate as many blocks as are required to
  59.     # concatinate to the desired key size:
  60.     blocks = (dk_length // h_length) + (1 if dk_length % h_length else 0)
  61.     for i in range(1, blocks + 1):
  62.         dk += pbkdf2_function(password, salt, count, i)
  63.     # The length of the key wil be dk_length to the nearest
  64.     # hash block size, i.e. larger than or equal to it. We
  65.     # slice it to the desired length befor returning it.
  66.     return dk[:dk_length]
  67.  
  68.  
  69. def test():
  70.     '''
  71.    PBKDF2 HMAC-SHA1 Test Vectors:
  72.        http://tools.ietf.org/html/rfc6070
  73.  
  74.    '''
  75.     # One of the test vectors has been removed because it takes
  76.     # too long to calculate. This was a test vector of 2^24 iterations.
  77.     # Since there is no difference between integers and long integers
  78.     # in python3, this will work as well as the others.
  79.     rfc6070_test_vectors = (
  80.         (b"password", b"salt", 1, 20),
  81.         (b"password", b"salt", 2, 20),
  82.         (b"password", b"salt", 4096, 20),
  83.         (b"passwordPASSWORDpassword",
  84.             b"saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25),
  85.         (b"pass\0word", b"sa\0lt", 4096, 16),
  86.     )
  87.     rfc6070_results = (
  88.         b"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24\xaf\x60\x12\x06"
  89.             b"\x2f\xe0\x37\xa6",
  90.         b"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a\xce\x1d\x41\xf0"
  91.             b"\xd8\xde\x89\x57",
  92.         b"\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26\xf7\x21\xd0"
  93.             b"\x65\xa4\x29\xc1",
  94.         b"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62\xc0\xe4\x4a"
  95.             b"\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38",
  96.         b"\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34\x25\xe0\xc3",
  97.     )
  98.     for v, r in zip(rfc6070_test_vectors, rfc6070_results):
  99.         assert pbkdf2(hashlib.sha1, *v) == r, v
  100.     print('* PBKDF2: all tests passed *\n')
  101.  
  102. test()
  103.  
  104. #######################################################################################
  105. # LIBRARY ABOVE
  106. #######################################################################################
  107.  
  108. Email = str.encode("user@example.com")
  109. MasterPassword =  str.encode("password123")
  110. ExpectedMasterKey = base64.b64decode('9N4OEZb/LoCsMnNF2eA13btvuMYSms3xy/mZHGPxY3A='.encode())
  111. ExpectedMasterPasswordHash = base64.b64decode('k0RkDBmMolfrjoHHCPODs93Fgk+v+AzDCsnxVemZiUA='.encode())
  112.  
  113. # The following values should be from db.sqlite3 'salt' and 'password_hash' columns and then they fail to match
  114. RandomSalt = str.encode('THISISSOMESALT')
  115. ExpectedPasswordHash = bytes.fromhex('449bd0e122c8f6f5056f3cf0cf38639624d1bce9ccf957d62e6928679fbb6ed5')
  116.  
  117. MasterKey = pbkdf2(hashlib.sha256, MasterPassword, Email, 100000, 32)
  118. print ("                 MasterKey: ", MasterKey.hex())
  119. print ("         ExpectedMasterKey: ", ExpectedMasterKey.hex())
  120. print ("           MasterKey Match: ", (MasterKey == ExpectedMasterKey))
  121.  
  122. MasterPasswordHash = pbkdf2(hashlib.sha256, MasterKey, MasterPassword, 1, 32)
  123. print ("        MasterPasswordHash: ", MasterPasswordHash.hex())
  124. print ("ExpectedMasterPasswordHash: ", ExpectedMasterPasswordHash.hex())
  125. print ("  MasterPasswordHash Match: ", (MasterPasswordHash == ExpectedMasterPasswordHash))
  126.  
  127. PasswordHash = pbkdf2(hashlib.sha512, MasterPasswordHash, RandomSalt, 100000, 32)
  128. print ("              PasswordHash: ", PasswordHash.hex())
  129. print ("      ExpectedPasswordHash: ", ExpectedPasswordHash.hex())
  130. print ("        PasswordHash Match: ", (PasswordHash == ExpectedPasswordHash))
Add Comment
Please, Sign In to add comment