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 9 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)