diff --git a/borg/crypto.pyx b/borg/crypto.pyx index 293096078e7..070a292d9b7 100644 --- a/borg/crypto.pyx +++ b/borg/crypto.pyx @@ -103,7 +103,7 @@ cdef class AES_CTR_256_HMAC_SHA_256_legacy: if iv is not None: self.iv = iv - def __cinit__(self, mac_key, enc_key, iv): + def __cinit__(self, mac_key, enc_key, iv=None): EVP_CIPHER_CTX_init(&self.ctx) HMAC_CTX_init(&self.hmac_ctx) @@ -227,7 +227,7 @@ cdef class AES_GCM_256_GMAC: @property def current_iv(self): - return self.ctx.iv[:12] + raise NotImplemented # gcm mode does not maintain/increment the counter in self.ctx.iv def encrypt(self, data, aad=b''): cdef Py_buffer idata = ro_buffer(data) diff --git a/borg/testsuite/crypto.py b/borg/testsuite/crypto.py index e3eff8becc9..9f75edb4725 100644 --- a/borg/testsuite/crypto.py +++ b/borg/testsuite/crypto.py @@ -1,6 +1,6 @@ from binascii import hexlify, unhexlify -from ..crypto import AES, bytes_to_long, bytes_to_int, long_to_bytes, hmac_sha256 +from ..crypto import AES_CTR_256_HMAC_SHA_256_legacy, AES_GCM_256_GMAC, bytes_to_long, bytes_to_int, long_to_bytes, hmac_sha256 from . import BaseTestCase # Note: these tests are part of the self test, do not use or import py.test functionality here. @@ -16,21 +16,45 @@ def test_bytes_to_long(self): 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_aes(self): - key = b'X' * 32 + def test_AES_CTR_256_HMAC_SHA_256_legacy(self): + mac_key = b'Y' * 32 + enc_key = b'X' * 32 + iv = b'\0' * 16 data = b'foo' * 10 - # encrypt - aes = AES(is_encrypt=True, key=key) - self.assert_equal(bytes_to_long(aes.iv, 8), 0) - cdata = aes.encrypt(data) + # encrypt-then-mac + cs = AES_CTR_256_HMAC_SHA_256_legacy(mac_key, enc_key, iv) + mac_iv_cdata = cs.encrypt(data) + mac = mac_iv_cdata[0:32] + iv = mac_iv_cdata[32:40] + cdata = mac_iv_cdata[40:] + self.assert_equal(hexlify(mac), b'af90b488b0cc4a8f768fe2d6814fa65aec66b148135e54f7d4d29a27f22f57a8') + self.assert_equal(hexlify(iv), b'0000000000000000') self.assert_equal(hexlify(cdata), b'c6efb702de12498f34a2c2bbc8149e759996d08bf6dc5c610aefc0c3a466') - self.assert_equal(bytes_to_long(aes.iv, 8), 2) - # decrypt - aes = AES(is_encrypt=False, key=key) - self.assert_equal(bytes_to_long(aes.iv, 8), 0) - pdata = aes.decrypt(cdata) + self.assert_equal(hexlify(cs.current_iv), b'00000000000000000000000000000002') + # auth-then-decrypt + cs = AES_CTR_256_HMAC_SHA_256_legacy(mac_key, enc_key) + pdata = cs.decrypt(mac_iv_cdata) + self.assert_equal(data, pdata) + self.assert_equal(hexlify(cs.current_iv), b'00000000000000000000000000000002') + + def test_AES_GCM_256_GMAC(self): + mac_key = None + enc_key = b'X' * 32 + iv = b'\0' * 12 + data = b'foo' * 10 + # encrypt-then-mac + cs = AES_GCM_256_GMAC(mac_key, enc_key, iv) + mac_iv_cdata = cs.encrypt(data) + mac = mac_iv_cdata[0:16] + iv = mac_iv_cdata[16:28] + cdata = mac_iv_cdata[28:] + self.assert_equal(hexlify(mac), b'66a438843aa41a087d6a7ed1dc1f3c4c') + self.assert_equal(hexlify(iv), b'000000000000000000000000') + self.assert_equal(hexlify(cdata), b'5bbb40be14e4bcbfc75715b77b1242d590d2bf9f7f8a8a910b4469888689') + # auth-then-decrypt + cs = AES_GCM_256_GMAC(mac_key, enc_key) + pdata = cs.decrypt(mac_iv_cdata) self.assert_equal(data, pdata) - self.assert_equal(bytes_to_long(aes.iv, 8), 2) def test_hmac_sha256(self): # RFC 4231 test vectors