add aes wrapper (#48)

This commit is contained in:
Dr. Marina Souza, PhD 2023-07-06 15:58:42 -07:00 committed by GitHub
parent 991bd7d262
commit abcc1d8aff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 821 additions and 574 deletions

View file

@ -43,9 +43,6 @@
<br>
* **[🧊 my (light) implementation of libp2p](https://github.com/go-outside-labs/libp2p-light-py)**
<br>
##### testing and linting

View file

@ -0,0 +1 @@
# -*- encoding: utf-8 -*-

View file

@ -0,0 +1,81 @@
# -*- encoding: utf-8 -*-
# aes_cipher.py
# This class implements methods for AES cipher standard.
from Crypto import Random
from Crypto.Cipher import AES
from math_utils import str_to_bytes, b64encode, b64decode, hash256
class AESWrapper():
def __init__(self, key: str, block_size=32) -> None:
self.block_size = block_size
# AES encryption needs a strong key. The stronger the key, the
# stronger the encryption (meaning not easily guessable and with
# enough entropy). The key is a string of 16, 24 or 32 bytes.
self.key = hash256(key)
#################
# Private methods
#################\
def _create_iv(self) -> str:
"""
AES needs an initialization vector (IV), which is generated
with every encryption, with the purpose to disallow cryptanalysis
of the ciphertext. The IV does not need to be kept secret.
"""
return Random.new().read(AES.block_size)
def _pad(self, data: str) -> str:
"""
AES is a block cipher, meaning that it encrypts data in blocks,
and the data must be padded to fit the block size. The padding
is done by adding bytes to the end of the data, with the value
of the number of bytes added.
"""
padding = (self.block_size - len(data) % self.block_size) * \
str_to_bytes(chr(self.block_size - len(data) % self.block_size))
return data + padding
def _unpad(self, data: str) -> str:
"""
Unpadding is done by removing the number of bytes at the
end of the data, with the value of the last byte.
"""
return data[:-ord(data[len(data) - 1:])]
#################
# Public methods
#################
def encrypt(self, raw: str) -> str:
"""Encrypt data."""
data = self._pad(str_to_bytes(raw))
iv = self._create_iv()
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return b64encode(iv + cipher.encrypt(data))
def decrypt(self, encrypted_data: str) -> str:
"""Decrypt data."""
data = b64decode(encrypted_data)
iv = data[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return self._unpad(cipher.decrypt(data[AES.block_size:])).decode('utf-8')
if __name__ == '__main__':
key = '12345678901234567890123456789012'
aes = AESWrapper(key)
data = 'hello world'
encrypted = aes.encrypt(data)
print('Encrypted:', encrypted)
decrypted = aes.decrypt(encrypted)
print('Decrypted:', decrypted)

View file

@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
# math_utils.py
# This class implements math methods used by the other classes.
import base64
import hashlib
def str_to_bytes(data):
"""Convert string to bytes."""
utype = type(b''.decode('utf8'))
if isinstance(data, utype):
return data.encode('utf8')
return data
def b64encode(data: str) -> str:
"""Encode data to base64."""
return base64.b64encode(data).decode('utf-8')
def b64decode(data: str) -> str:
"""Decode base64 data."""
return base64.b64decode(data)
def hash256(data: str) -> str:
"""Hash data with SHA-256."""
return hashlib.sha256(str_to_bytes(data)).digest()

1272
web3-toolkit/poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,16 +2,18 @@
name = "web3-python-toolkit"
version = "0.1.0"
description="toolkit for web3"
authors=["steinkirch"]
authors=["bt3gl"]
readme = "README.md"
packages = [{include = "scripts"}]
[tool.poetry.dependencies]
python = "3.11.1"
python = "3.11.4"
ethereum-etl = "2.1.2"
python-dotenv = "0.21.0"
web3 = "5.31.3"
pandas = "^1.5.2"
pycryptodome = "^3.18.0"
[tool.poetry.group.dev.dependencies]
tox = "^4.0.16"