aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cryptech/libhal.py27
-rwxr-xr-xcryptech_backup16
-rw-r--r--unit-tests.py72
3 files changed, 60 insertions, 55 deletions
diff --git a/cryptech/libhal.py b/cryptech/libhal.py
index 102e663..105dd02 100644
--- a/cryptech/libhal.py
+++ b/cryptech/libhal.py
@@ -347,7 +347,8 @@ class LocalDigest(object):
"""
def __init__(self, hsm, handle, algorithm, key):
- from Crypto.Hash import HMAC, SHA, SHA224, SHA256, SHA384, SHA512
+ from Cryptodome.Hash import HMAC, SHA1, SHA224, SHA256, SHA384, SHA512
+ from Cryptodome.Util.asn1 import DerObjectId
from struct import pack
self.hsm = hsm
self.handle = handle
@@ -356,16 +357,22 @@ class LocalDigest(object):
h = self._algorithms[algorithm]
except AttributeError:
self._algorithms = {
- HAL_DIGEST_ALGORITHM_SHA1 : SHA.SHA1Hash,
- HAL_DIGEST_ALGORITHM_SHA224 : SHA224.SHA224Hash,
- HAL_DIGEST_ALGORITHM_SHA256 : SHA256.SHA256Hash,
- HAL_DIGEST_ALGORITHM_SHA384 : SHA384.SHA384Hash,
- HAL_DIGEST_ALGORITHM_SHA512 : SHA512.SHA512Hash
+ HAL_DIGEST_ALGORITHM_SHA1 : SHA1,
+ HAL_DIGEST_ALGORITHM_SHA224 : SHA224,
+ HAL_DIGEST_ALGORITHM_SHA256 : SHA256,
+ HAL_DIGEST_ALGORITHM_SHA384 : SHA384,
+ HAL_DIGEST_ALGORITHM_SHA512 : SHA512
}
h = self._algorithms[algorithm]
self.digest_length = h.digest_size
- self.algorithm_id = pack("BB", 0x30, 2 + len(h.oid)) + h.oid
- self._context = HMAC.HMAC(key = key, digestmod = h) if key else h()
+ if key:
+ self._context = HMAC.new(key = key, digestmod = h)
+ oid = h.new().oid
+ else:
+ self._context = h.new()
+ oid = self._context.oid
+ self.oid = DerObjectId(oid).encode()
+ self.algorithm_id = pack("BB", 0x30, 2 + len(self.oid)) + self.oid
def update(self, data):
self._context.update(data)
@@ -377,8 +384,8 @@ class LocalDigest(object):
if pkey.key_type not in (HAL_KEY_TYPE_RSA_PRIVATE, HAL_KEY_TYPE_RSA_PUBLIC):
return self.finalize()
# PKCS #1.5 requires the digest to be wrapped up in an ASN.1 DigestInfo object.
- from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString
- return DerSequence([DerSequence([self._context.oid, DerNull().encode()]).encode(),
+ from Cryptodome.Util.asn1 import DerSequence, DerNull, DerOctetString
+ return DerSequence([DerSequence([self.oid, DerNull().encode()]).encode(),
DerOctetString(self.finalize()).encode()]).encode()
diff --git a/cryptech_backup b/cryptech_backup
index a15c9c0..99d2c38 100755
--- a/cryptech_backup
+++ b/cryptech_backup
@@ -21,7 +21,7 @@ We also implement a software-based variant on this backup mechanism,
for cases where there is no second HSM. The protocol is much the
same, but the KEKEK is generated in software and encrypted using a
symmetric key derived from a passphrase using PBKDF2. This requires
-the PyCrypto library, and is only as secure as memory on the machine
+the PyCryptodome library, and is only as secure as memory on the machine
where you're running it (so it's theoretically vulnerable to root or
anybody with access to /dev/mem). Don't use this mode unless you
understand the risks, and see the "NOTE WELL" above.
@@ -305,7 +305,7 @@ class AESKeyWrapWithPadding(object):
"Something went wrong during unwrap."
def __init__(self, key):
- from Crypto.Cipher import AES
+ from Cryptodome.Cipher import AES
self.ctx = AES.new(key, AES.MODE_ECB)
def _encrypt(self, b1, b2):
@@ -391,7 +391,7 @@ class SoftKEKEK(object):
time.clock = time.process_time
def parse_EncryptedPrivateKeyInfo(self, der):
- from Crypto.Util.asn1 import DerObject, DerSequence, DerOctetString, DerObjectId
+ from Cryptodome.Util.asn1 import DerObject, DerSequence, DerOctetString, DerObjectId
encryptedPrivateKeyInfo = DerSequence()
encryptedPrivateKeyInfo.decode(der)
encryptionAlgorithm = DerSequence()
@@ -405,7 +405,7 @@ class SoftKEKEK(object):
return encryptedData.payload
def encode_EncryptedPrivateKeyInfo(self, der):
- from Crypto.Util.asn1 import DerSequence, DerOctetString
+ from Cryptodome.Util.asn1 import DerSequence, DerOctetString
return DerSequence([
DerSequence([
struct.pack("BB", 0x06, len(self.oid_aesKeyWrap)) + self.oid_aesKeyWrap
@@ -414,12 +414,12 @@ class SoftKEKEK(object):
]).encode()
def gen_salt(self, bytes = 16):
- from Crypto import Random
+ from Cryptodome import Random
return Random.new().read(bytes)
def wrapper(self, salt, keylen = 256, iterations = 8000):
- from Crypto.Protocol.KDF import PBKDF2
- from Crypto.Hash import SHA256, HMAC
+ from Cryptodome.Protocol.KDF import PBKDF2
+ from Cryptodome.Hash import SHA256, HMAC
return AESKeyWrapWithPadding(PBKDF2(
password = getpass.getpass("KEKEK Passphrase: "),
salt = salt,
@@ -433,7 +433,7 @@ class SoftKEKEK(object):
@classmethod
def generate(cls, args, result):
- from Crypto.PublicKey import RSA
+ from Cryptodome.PublicKey import RSA
self = cls()
k = RSA.generate(args.keylen)
salt = self.gen_salt()
diff --git a/unit-tests.py b/unit-tests.py
index 526379c..bdb6f77 100644
--- a/unit-tests.py
+++ b/unit-tests.py
@@ -49,19 +49,17 @@ from struct import pack, unpack
from cryptech.libhal import *
try:
- from Crypto.Util.number import inverse
- from Crypto.PublicKey import RSA
- from Crypto.Cipher import AES
- from Crypto.Cipher.PKCS1_v1_5 import PKCS115_Cipher
- from Crypto.Signature.PKCS1_v1_5 import PKCS115_SigScheme
- from Crypto.Hash.SHA256 import SHA256Hash as SHA256
- from Crypto.Hash.SHA384 import SHA384Hash as SHA384
- from Crypto.Hash.SHA512 import SHA512Hash as SHA512
+ from Cryptodome.Util.number import inverse
+ from Cryptodome.PublicKey import RSA
+ from Cryptodome.Cipher import AES, PKCS1_v1_5
+ from Cryptodome.Signature import pkcs1_15
+ from Cryptodome.Hash.SHA256 import new as SHA256
+ from Cryptodome.Hash.SHA384 import new as SHA384
+ from Cryptodome.Hash.SHA512 import new as SHA512
pycrypto_loaded = True
except ImportError:
pycrypto_loaded = False
-
try:
from ecdsa import der as ECDSA_DER
from ecdsa.keys import SigningKey as ECDSA_SigningKey
@@ -998,15 +996,15 @@ class TestPKeyHashing(TestCaseLoggedIn):
k1.verify(signature = sig, hash = self.h(alg, mixed_mode = True))
k2.verify(signature = sig, hash = self.h(alg, mixed_mode = True))
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_1024_sha256_data(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA256, 1024, self.sign_verify_data)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_2048_sha384_data(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA384, 2048, self.sign_verify_data)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_4096_sha512_data(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA512, 4096, self.sign_verify_data)
@@ -1022,15 +1020,15 @@ class TestPKeyHashing(TestCaseLoggedIn):
def test_load_sign_verify_ecdsa_p521_sha512_data(self):
self.load_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA512, HAL_CURVE_P521, self.sign_verify_data)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_1024_sha256_remote_remote(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA256, 1024, self.sign_verify_remote_remote)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_2048_sha384_remote_remote(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA384, 2048, self.sign_verify_remote_remote)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_4096_sha512_remote_remote(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA512, 4096, self.sign_verify_remote_remote)
@@ -1046,15 +1044,15 @@ class TestPKeyHashing(TestCaseLoggedIn):
def test_load_sign_verify_ecdsa_p521_sha512_remote_remote(self):
self.load_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA512, HAL_CURVE_P521, self.sign_verify_remote_remote)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_1024_sha256_remote_local(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA256, 1024, self.sign_verify_remote_local)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_2048_sha384_remote_local(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA384, 2048, self.sign_verify_remote_local)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_4096_sha512_remote_local(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA512, 4096, self.sign_verify_remote_local)
@@ -1070,15 +1068,15 @@ class TestPKeyHashing(TestCaseLoggedIn):
def test_load_sign_verify_ecdsa_p521_sha512_remote_local(self):
self.load_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA512, HAL_CURVE_P521, self.sign_verify_remote_local)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_1024_sha256_local_remote(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA256, 1024, self.sign_verify_local_remote)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_2048_sha384_local_remote(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA384, 2048, self.sign_verify_local_remote)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_4096_sha512_local_remote(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA512, 4096, self.sign_verify_local_remote)
@@ -1094,15 +1092,15 @@ class TestPKeyHashing(TestCaseLoggedIn):
def test_load_sign_verify_ecdsa_p521_sha512_local_remote(self):
self.load_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA512, HAL_CURVE_P521, self.sign_verify_local_remote)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_1024_sha256_local_local(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA256, 1024, self.sign_verify_local_local)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_2048_sha384_local_local(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA384, 2048, self.sign_verify_local_local)
- @unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+ @unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
def test_load_sign_verify_rsa_4096_sha512_local_local(self):
self.load_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA512, 4096, self.sign_verify_local_local)
@@ -1131,7 +1129,7 @@ class TestPKeyHashing(TestCaseLoggedIn):
self.gen_sign_verify_hashsig(1, HAL_LMS_SHA256_N32_H5, HAL_LMOTS_SHA256_N32_W4, 2352, self.sign_verify_local_local)
-@unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+@unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
class TestPKeyRSAInterop(TestCaseLoggedIn):
@staticmethod
@@ -1575,7 +1573,7 @@ class TestPkeyECDSAVerificationNIST(TestCaseLoggedIn):
py_hash = SHA384)
-@unittest.skipUnless(pycrypto_loaded, "Requires Python Crypto package")
+@unittest.skipUnless(pycrypto_loaded, "Requires Python Cryptodome package")
class TestPKeyBackup(TestCaseLoggedIn):
oid_rsaEncryption = b"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01"
@@ -1583,7 +1581,7 @@ class TestPKeyBackup(TestCaseLoggedIn):
@staticmethod
def parse_EncryptedPrivateKeyInfo(der, oid):
- from Crypto.Util.asn1 import DerObject, DerSequence, DerOctetString, DerObjectId
+ from Cryptodome.Util.asn1 import DerObject, DerSequence, DerOctetString, DerObjectId
encryptedPrivateKeyInfo = DerSequence()
encryptedPrivateKeyInfo.decode(der)
encryptionAlgorithm = DerSequence()
@@ -1606,7 +1604,7 @@ class TestPKeyBackup(TestCaseLoggedIn):
@staticmethod
def encode_EncryptedPrivateKeyInfo(der, oid):
- from Crypto.Util.asn1 import DerSequence, DerOctetString
+ from Cryptodome.Util.asn1 import DerSequence, DerOctetString
return DerSequence([
DerSequence([pack("BB", 0x06, len(oid)) + oid]).encode(),
DerOctetString(der).encode()
@@ -1614,15 +1612,15 @@ class TestPKeyBackup(TestCaseLoggedIn):
@staticmethod
def make_kek():
- import Crypto.Random
- return Crypto.Random.new().read(256//8)
+ import Cryptodome.Random
+ return Cryptodome.Random.new().read(256//8)
def sig_check(self, pkey, der):
- from Crypto.Util.asn1 import DerSequence, DerNull, DerOctetString
- p115 = PKCS115_SigScheme(RSA.importKey(der))
+ from Cryptodome.Util.asn1 import DerSequence, DerNull, DerOctetString, DerObjectId
+ p115 = pkcs1_15.new(RSA.importKey(der))
hash = SHA256("Your mother was a hamster".encode())
data = DerSequence([
- DerSequence([hash.oid, DerNull().encode()]).encode(),
+ DerSequence([DerObjectId(hash.oid).encode(), DerNull().encode()]).encode(),
DerOctetString(hash.digest()).encode()
]).encode()
sig1 = p115.sign(hash)
@@ -1643,7 +1641,7 @@ class TestPKeyBackup(TestCaseLoggedIn):
flags = HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | HAL_KEY_FLAG_EXPORTABLE)
self.addCleanup(pkey.delete)
pkcs8_der, kek_der = kekek.export_pkey(pkey)
- kek = PKCS115_Cipher(PreloadedKey.db[HAL_KEY_TYPE_RSA_PRIVATE, 1024].obj).decrypt(
+ kek = PKCS1_v1_5.new(PreloadedKey.db[HAL_KEY_TYPE_RSA_PRIVATE, 1024].obj).decrypt(
self.parse_EncryptedPrivateKeyInfo(kek_der, self.oid_rsaEncryption),
self.make_kek())
der = AESKeyWrapWithPadding(kek).unwrap(
@@ -1662,7 +1660,7 @@ class TestPKeyBackup(TestCaseLoggedIn):
AESKeyWrapWithPadding(kek).wrap(der),
self.oid_aesKeyWrap),
kek = self.encode_EncryptedPrivateKeyInfo(
- PKCS115_Cipher(RSA.importKey(kekek.public_key)).encrypt(kek),
+ PKCS1_v1_5.new(RSA.importKey(kekek.public_key)).encrypt(kek),
self.oid_rsaEncryption),
flags = HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE)
self.addCleanup(pkey.delete)
@@ -1800,10 +1798,10 @@ class PreloadedRSAKey(PreloadedKey):
k2, k2.exportKey(format = "DER" ), keylen = keylen)
def sign(self, text, hash):
- return PKCS115_SigScheme(self.obj).sign(hash(text))
+ return pkcs1_15.new(self.obj).sign(hash(text))
def verify(self, text, hash, signature):
- return PKCS115_SigScheme(self.obj).verify(hash(text), signature)
+ return pkcs1_15.new(self.obj).verify(hash(text), signature)
class PreloadedECKey(PreloadedKey):