Implemented AES256

This commit is contained in:
tcsenpai 2024-02-10 22:40:45 +01:00
parent 018bcadd34
commit 1e6baf57f6
3 changed files with 91 additions and 10 deletions

View File

@ -1,5 +1,19 @@
# hmacrypt
encryption / decryption / signing / verifying using RSA and ECDSA a deterministic Key Derivation from password+hmac_secret by an hardware key.
encryption / decryption / signing / verifying using RSA, AES and ECDSA a deterministic Key Derivation from password+hmac_secret by an hardware key.
## Supported algorithms
- RSA (deterministic with keyfile, password and hw device)
- ECDSA (deterministic with keyfile, password and hw device)
- AES 256 (deterministic with keyfile, password and hw device)
## Tested devices
- Thetis FIDO2
### Should also work with
Any FIDO2/U2F key having hmac_secrets extension
## Requirements (BEFORE everything else) & Credits
@ -36,6 +50,7 @@ On Ubuntu 23.10 (untested on other platforms and flavors):
- 2fa encryption/decryption using RSA deterministic Key Derivation
- 2fa signing/verifying using ECDSA deterministic Key Derivation
- 2fa AES cipher encryption/decryption using SHA256
- Possibility to use the same or different keyfiles to enhance security
- Consequently, supports for a wide range of hardware keys as long as they are compatible with libfido2
- Low footprint: requires just two (or three) python library and a single system library
@ -96,6 +111,27 @@ Or the path you used for the library.
*If you REALLY have to change the src directory name, please correct the various paths inside.*
#### encrypt_aes
Definition:
def encrypt_aes(message)
Parameters:
- message; data (string preferrable) to be encrypted
#### decrypt_aes
Definition:
def decrypt_aes(encrypted)
Parameters:
- encrypted; (usually) bytes to be decrypted
#### inferECDSAKeys
Definition:

View File

@ -1,6 +1,7 @@
import subprocess
from src.libs.seedable_rsa import decrypt, encrypt, generate_rsa_key
from src.libs.seedable_ecdsa import generate_ecdsa_key, sign, verify
from src.libs.seedable_aes import self_encrypt_aes, self_decrypt_aes
# INFO This method derives the HMAC secret from the hardware key and the stored secret
def getHMACSecret(keyfilePath="src/bins/.keyfile"):
@ -15,6 +16,17 @@ def getHMACSecret(keyfilePath="src/bins/.keyfile"):
hmac_secret = hmac_secret.strip()
return hmac_secret
# INFO The following methods are proxies to the AES methods
# NOTE The AES methods generate a cipher on the fly based on the getHMACSecret method
def encrypt_aes(message):
seed = getHMACSecret()
return self_encrypt_aes(seed, message)
def decrypt_aes(encrypted):
seed = getHMACSecret()
return self_decrypt_aes(seed, encrypted)
# INFO This method derives an ECDSA keypair from the stored secret and the hardware key
def inferECDSAKeys(hidePrivate=False, savePublic=False):
hmac_secret = getHMACSecret()
@ -108,12 +120,3 @@ def self_decrypt_file(filepath, outpath):
# TODO LARGE FILES
# Self testing
if __name__ == "__main__":
private_key, public_key = inferRSAKeys()
secret = encrypt("secret message", public_key)
print(secret)
decrypted = decrypt(secret, private_key)
print(decrypted)

42
src/libs/seedable_aes.py Normal file
View File

@ -0,0 +1,42 @@
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key.encode()).digest()
def encrypt(self, raw):
raw = self._pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return base64.b64encode(iv + cipher.encrypt(raw.encode()))
def decrypt(self, enc):
enc = base64.b64decode(enc)
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return AESCipher._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
# Implementable methods
# NOTE The cipher is initialized on the fly, so the seed is not stored
def self_encrypt_aes(seed, message):
cipher = AESCipher(seed)
encrypted = cipher.encrypt(message)
return encrypted
def self_decrypt_aes(seed, encrypted):
cipher = AESCipher(seed)
decrypted = cipher.decrypt(encrypted)
return decrypted