mirror of
https://github.com/tcsenpai/hmacrypt.git
synced 2025-06-02 17:10:06 +00:00
Implemented AES256
This commit is contained in:
parent
018bcadd34
commit
1e6baf57f6
38
README.md
38
README.md
@ -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:
|
||||
|
@ -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
42
src/libs/seedable_aes.py
Normal 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
|
Loading…
x
Reference in New Issue
Block a user