diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/CryptoUtils.py b/virtualsmartcard/src/vpicc/virtualsmartcard/CryptoUtils.py index 275bc07..b1112ee 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/CryptoUtils.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/CryptoUtils.py @@ -203,11 +203,12 @@ def protect_string(string, password, cipherspec=None): #Derive a key and a salt from password pbk = crypt(password) - regex = re.compile('\$p5k2\$\$[\w./]*\$') + regex = re.compile('\$p5k2\$(\d*)\$([\w./]*)\$([\w./]*)') match = regex.match(pbk) if match != None: - salt = pbk[7:match.end()-1] - key = pbk[match.end():] + iterations = match.group(1) + salt = match.group(2) + key = match.group(3) else: raise ValueError @@ -231,11 +232,11 @@ def read_protected_string(string, password, cipherspec=None): hmac_length = 32 #FIXME: Ugly #Check if the string has the structure, that is generated by protect_string - regex = re.compile('\$p5k2\$\$[\w./]*\$') + regex = re.compile('\$p5k2\$\$([\w./]*)\$') match = regex.match(string) if match != None: + salt = match.group(1) crypted = string[match.end():len(string) - hmac_length] - salt = string[7:match.end() - 1] hmac = string[len(string) - hmac_length:] else: raise ValueError("Wrong string format") @@ -323,8 +324,7 @@ def crypt(word, salt=None, iterations=None): else: salt = "$p5k2$%x$%s" % (iterations, salt) rawhash = pbkdf2_hmac('sha1', salt, word, iterations, 24) - # return salt + "$" + b64encode(rawhash, "./") DO: Original return line - return salt + "$" + rawhash + return salt + "$" + b64encode(rawhash, "./") def _makesalt(): """Return a 48-bit pseudorandom salt for crypt(). diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/tests/CryptoUtils_test.py b/virtualsmartcard/src/vpicc/virtualsmartcard/tests/CryptoUtils_test.py index 5f3ffc7..9ba7c32 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/tests/CryptoUtils_test.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/tests/CryptoUtils_test.py @@ -30,9 +30,10 @@ class TestCryptoUtils(unittest.TestCase): # The data generated by protect_string should actually consist of # printable characters only but that would break backwards # compatibility with the (buggy) legacy implementation - self.protectedTestString = "2470356b322424504f63775949487224ffa330e33b2d76b82e91a4c88ff722414d3522bcbdb8a4a45cd7c61963b52825e1361354d5b5efbcfeabfb66fa3f97dfecd5e57617b8e0172017785f4001e9653366363763323639363965313261386363623738326435326639653563633339".decode('hex') + self.protectedTestString = "2470356b32242478424f50746f6d712448b8f6285ac8462fffc6aef921f2ad84855219c5aaafb39c4cc9e54d1634c60cfc9347c67fa55967c5b0130469c96a44f0b73c53f5ddfc43cd8c1ef68965ebb23330393265383732333937353465653838643135363830666637336134316532".decode('hex') self.salt = "POcwYIHr" - self.cryptedWord = "2470356b322424504f63775949487224993c1d36e308d941d0fa240d18f4097ce8d0995226f04800".decode('hex') + self.cryptedWord = "$p5k2$$POcwYIHr$SPaWqD3NpmLZc6gXbeybnAoCxo7Oc//K" + self.cryptedWordThousandIterations = "$p5k2$3e8$POcwYIHr$f/mEOCulo6v7Nq2ooS3480xTet6zdGbI" def test_padding(self): padded = append_padding(16, self.teststring) @@ -49,8 +50,12 @@ class TestCryptoUtils(unittest.TestCase): self.assertEqual(unprotectedString, self.teststring) def test_crypt(self): - cryptedWord = crypt(self.teststring, self.salt, 400) + cryptedWord = crypt(self.teststring, self.salt) self.assertEqual(cryptedWord, self.cryptedWord) + def test_crypt_non_default_iterations(self): + cryptedWord = crypt(self.teststring, self.salt, 1000) + self.assertEqual(cryptedWord, self.cryptedWordThousandIterations) + if __name__ == "__main__": unittest.main()