Skip to content

Instantly share code, notes, and snippets.

@dahlia
Last active October 17, 2018 10:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dahlia/795b4bd95ddfe6329a723cd2869220ae to your computer and use it in GitHub Desktop.
Save dahlia/795b4bd95ddfe6329a723cd2869220ae to your computer and use it in GitHub Desktop.
ECIES + secp256k1, using coincurve (secp256k1 ECDH) and cryptography (AES-GCM)
import os
from coincurve import PrivateKey, PublicKey # type: ignore
from cryptography.hazmat.primitives.ciphers.aead import AESGCM # type: ignore
__all__ = 'decrypt', 'encrypt'
def encrypt(public_key: PublicKey, message: bytes) -> bytes:
disposable_priv_key: PrivateKey = PrivateKey()
aes_key: bytes = disposable_priv_key.ecdh(
public_key.format(compressed=True)
)
assert len(aes_key) in (16, 24, 32)
aesgcm: AESGCM = AESGCM(aes_key)
nonce = os.urandom(16)
pub_key: bytes = disposable_priv_key.public_key.format(compressed=True)
ciphertext: bytes = aesgcm.encrypt(nonce, message, pub_key)
return pub_key + nonce + ciphertext
def decrypt(private_key: PrivateKey, encrypted: bytes) -> bytes:
disposable_pub_key: bytes = encrypted[:33]
nonce: bytes = encrypted[33:33 + 16]
ciphertext: bytes = encrypted[33 + 16:]
aes_key: bytes = private_key.ecdh(disposable_pub_key)
assert len(aes_key) in (16, 24, 32)
aesgcm: AESGCM = AESGCM(aes_key)
return aesgcm.decrypt(nonce, ciphertext, disposable_pub_key)
import os
from coincurve import PrivateKey # type: ignore
from pytest import mark # type: ignore
from ..encrypt import decrypt, encrypt
@mark.parametrize('key', [PrivateKey() for _ in range(3)])
@mark.parametrize('message', [os.urandom(7 * s) for s in range(10)])
def test_encrypt_decrypt(key: PrivateKey, message: bytes):
ciphertext: bytes = encrypt(key.public_key, message)
decrypted: bytes = decrypt(key, ciphertext)
assert message == decrypted
def test_decrypt():
key: PrivateKey = PrivateKey(
b'\xfb\xc2\x00\x42\xb3\xa7\x07\xa7\xd5\xa1\xfa\x57\x71\x71\xf4\x9c'
b'\xd3\xa9\xe6\x7a\xb9\x29\x57\x57\xc7\x14\xe3\xf2\xf8\xc2\xd5\x73'
)
ciphertext: bytes = (
b'\x03\xe3\x1a\x0d\xea\x31\xe2\xb1\x32\x7b\xd8\x70\x0a\xd3\x57\xcc'
b'\x69\x31\x4e\xca\xd7\x0a\xe2\xe4\xfa\x55\x17\xa3\x3b\x67\xcf\xb1'
b'\xc4\xfa\xa1\x10\xd4\xd2\x73\x11\xef\xf1\x47\x99\xd7\x3d\x3c\xaa'
b'\xa2\x0e\x35\x7c\x41\xc8\x8e\x14\x22\xc7\x64\xed\xcc\xe0\x6c\x06'
b'\xb5\x86\x44\xc1\x68\xa5\xab\xf3\x9d\xcb\x46\xb6\xe2'
)
msg: bytes = decrypt(key, ciphertext)
assert msg == b'test message'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment