Browse Source

use hashlib.pbkdf2_hmac from py stdlib instead of own openssl wrapper

this is available in python 3.4+.

note:
before removing the pbkdf tests, i ran them with the pbkdf from stdlib to make sure it gives same result.
long term testing of this now belongs into stdlib tests, not into borg.
Thomas Waldmann 10 years ago
parent
commit
3ade3d8a41
3 changed files with 5 additions and 34 deletions
  1. 1 22
      borg/crypto.pyx
  2. 3 3
      borg/key.py
  3. 1 9
      borg/testsuite/crypto.py

+ 1 - 22
borg/crypto.pyx

@@ -1,7 +1,6 @@
 """A thin OpenSSL wrapper
 
-This could be replaced by PyCrypto or something similar when the performance
-of their PBKDF2 implementation is comparable to the OpenSSL version.
+This could be replaced by PyCrypto maybe?
 """
 from libc.stdlib cimport malloc, free
 
@@ -21,7 +20,6 @@ cdef extern from "openssl/evp.h":
         pass
     ctypedef struct ENGINE:
         pass
-    const EVP_MD *EVP_sha256()
     const EVP_CIPHER *EVP_aes_256_ctr()
     void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a)
     void EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a)
@@ -37,10 +35,6 @@ cdef extern from "openssl/evp.h":
     int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
     int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 
-    int PKCS5_PBKDF2_HMAC(const char *password, int passwordlen,
-                          const unsigned char *salt, int saltlen, int iter,
-                          const EVP_MD *digest,
-                          int keylen, unsigned char *out)
 
 import struct
 
@@ -59,21 +53,6 @@ def num_aes_blocks(int length):
     return (length + 15) // 16
 
 
-def pbkdf2_sha256(password, salt, iterations, size):
-    """Password based key derivation function 2 (RFC2898)
-    """
-    cdef unsigned char *key = <unsigned char *>malloc(size)
-    if not key:
-        raise MemoryError
-    try:
-        rv = PKCS5_PBKDF2_HMAC(password, len(password), salt, len(salt), iterations, EVP_sha256(), size, key)
-        if not rv:
-            raise Exception('PKCS5_PBKDF2_HMAC failed')
-        return key[:size]
-    finally:
-        free(key)
-
-
 def get_random_bytes(n):
     """Return n cryptographically strong pseudo-random bytes
     """

+ 3 - 3
borg/key.py

@@ -5,13 +5,13 @@ import os
 import sys
 import textwrap
 from hmac import HMAC, compare_digest
-from hashlib import sha256
+from hashlib import sha256, pbkdf2_hmac
 
 from .helpers import IntegrityError, get_keys_dir, Error
 from .logger import create_logger
 logger = create_logger()
 
-from .crypto import pbkdf2_sha256, get_random_bytes, AES, bytes_to_long, long_to_bytes, bytes_to_int, num_aes_blocks
+from .crypto import get_random_bytes, AES, bytes_to_long, long_to_bytes, bytes_to_int, num_aes_blocks
 from .compress import Compressor, COMPR_BUFFER
 import msgpack
 
@@ -199,7 +199,7 @@ class Passphrase(str):
         return '<Passphrase "***hidden***">'
 
     def kdf(self, salt, iterations, length):
-        return pbkdf2_sha256(self.encode('utf-8'), salt, iterations, length)
+        return pbkdf2_hmac('sha256', self.encode('utf-8'), salt, iterations, length)
 
 
 class PassphraseKey(AESKeyBase):

+ 1 - 9
borg/testsuite/crypto.py

@@ -1,6 +1,6 @@
 from binascii import hexlify
 
-from ..crypto import AES, bytes_to_long, bytes_to_int, long_to_bytes, pbkdf2_sha256, get_random_bytes
+from ..crypto import AES, bytes_to_long, bytes_to_int, long_to_bytes, get_random_bytes
 from . import BaseTestCase
 
 
@@ -13,14 +13,6 @@ class CryptoTestCase(BaseTestCase):
         self.assert_equal(bytes_to_long(b'\0\0\0\0\0\0\0\1'), 1)
         self.assert_equal(long_to_bytes(1), b'\0\0\0\0\0\0\0\1')
 
-    def test_pbkdf2_sha256(self):
-        self.assert_equal(hexlify(pbkdf2_sha256(b'password', b'salt', 1, 32)),
-                          b'120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b')
-        self.assert_equal(hexlify(pbkdf2_sha256(b'password', b'salt', 2, 32)),
-                          b'ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43')
-        self.assert_equal(hexlify(pbkdf2_sha256(b'password', b'salt', 4096, 32)),
-                          b'c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a')
-
     def test_get_random_bytes(self):
         bytes = get_random_bytes(10)
         bytes2 = get_random_bytes(10)