Browse Source

Deduplicate AES code

master
Kristaps Kaupe 2 years ago
parent
commit
e4f74b56f3
No known key found for this signature in database
GPG Key ID: 33E472FE870C7E5D
  1. 2
      jmbase/jmbase/__init__.py
  2. 15
      jmbase/jmbase/crypto.py
  3. 2
      jmbase/setup.py
  4. 25
      jmbitcoin/jmbitcoin/secp256k1_ecies.py
  5. 2
      jmbitcoin/setup.py
  6. 19
      jmclient/jmclient/storage.py
  7. 2
      jmclient/setup.py

2
jmbase/jmbase/__init__.py

@ -15,4 +15,4 @@ from .twisted_utils import (stop_reactor, is_hs_uri, get_tor_agent,
JMHTTPResource, set_custom_stop_reactor)
from .bytesprod import BytesProducer
from .commands import *
from .crypto import aes_cbc_encrypt, aes_cbc_decrypt

15
jmbase/jmbase/crypto.py

@ -0,0 +1,15 @@
import pyaes
def aes_cbc_encrypt(key: bytes, data: bytes, iv: bytes) -> bytes:
encrypter = pyaes.Encrypter(
pyaes.AESModeOfOperationCBC(key, iv=iv))
enc_data = encrypter.feed(data)
enc_data += encrypter.feed()
return enc_data
def aes_cbc_decrypt(key: bytes, data: bytes, iv: bytes) -> bytes:
decrypter = pyaes.Decrypter(
pyaes.AESModeOfOperationCBC(key, iv=iv))
dec_data = decrypter.feed(data)
dec_data += decrypter.feed()
return dec_data

2
jmbase/setup.py

@ -10,6 +10,6 @@ setup(name='joinmarketbase',
license='GPL',
packages=['jmbase'],
install_requires=['twisted==22.4.0', 'service-identity==21.1.0',
'chromalog==1.0.5'],
'chromalog==1.0.5', 'pyaes==1.6.1'],
python_requires='>=3.6',
zip_safe=False)

25
jmbitcoin/jmbitcoin/secp256k1_ecies.py

@ -1,9 +1,9 @@
import base64
import hmac
import hashlib
import pyaes
import os
import jmbitcoin as btc
from jmbase import aes_cbc_encrypt, aes_cbc_decrypt
from bitcointx.core.key import CPubKey
ECIES_MAGIC_BYTES = b'BIE1'
@ -11,25 +11,12 @@ ECIES_MAGIC_BYTES = b'BIE1'
class ECIESDecryptionError(Exception):
pass
# AES primitives. See BIP-SNICKER for specification.
def aes_encrypt(key, data, iv):
encrypter = pyaes.Encrypter(
pyaes.AESModeOfOperationCBC(key, iv=iv))
enc_data = encrypter.feed(data)
enc_data += encrypter.feed()
return enc_data
def aes_decrypt(key, data, iv):
decrypter = pyaes.Decrypter(
pyaes.AESModeOfOperationCBC(key, iv=iv))
def _ecies_aes_decrypt(key, data, iv):
try:
dec_data = decrypter.feed(data)
dec_data += decrypter.feed()
return aes_cbc_decrypt(key, data, iv)
except ValueError:
# note decryption errors can come from PKCS7 padding errors
raise ECIESDecryptionError()
return dec_data
def ecies_encrypt(message, pubkey):
""" Take a message in bytes and a secp256k1 public key
@ -53,10 +40,10 @@ def ecies_encrypt(message, pubkey):
ecdh_key = btc.multiply(r, pubkey)
key = hashlib.sha512(ecdh_key).digest()
iv, key_e, key_m = key[0:16], key[16:32], key[32:]
ciphertext = aes_encrypt(key_e, message, iv=iv)
ciphertext = aes_cbc_encrypt(key_e, message, iv=iv)
encrypted = ECIES_MAGIC_BYTES + R + ciphertext
mac = hmac.new(key_m, encrypted, hashlib.sha256).digest()
return base64.b64encode(encrypted + mac)
return base64.b64encode(encrypted + mac)
def ecies_decrypt(privkey, encrypted):
if len(privkey) == 33 and privkey[-1] == 1:
@ -78,5 +65,5 @@ def ecies_decrypt(privkey, encrypted):
iv, key_e, key_m = key[0:16], key[16:32], key[32:]
if mac != hmac.new(key_m, encrypted[:-32], hashlib.sha256).digest():
raise ECIESDecryptionError()
return aes_decrypt(key_e, ciphertext, iv=iv)
return _ecies_aes_decrypt(key_e, ciphertext, iv=iv)

2
jmbitcoin/setup.py

@ -10,5 +10,5 @@ setup(name='joinmarketbitcoin',
license='GPL',
packages=['jmbitcoin'],
python_requires='>=3.6',
install_requires=['python-bitcointx==1.1.3', 'pyaes==1.6.1'],
install_requires=['python-bitcointx==1.1.3'],
zip_safe=False)

19
jmclient/jmclient/storage.py

@ -2,9 +2,9 @@ import os
import shutil
import atexit
import bencoder
import pyaes
from hashlib import sha256
from argon2 import low_level
from jmbase import aes_cbc_encrypt, aes_cbc_decrypt
from .support import get_random_bytes
@ -252,20 +252,13 @@ class Storage(object):
return self._decrypt(container[b'data'], container[b'enc'][b'iv'])
def _encrypt(self, data, iv):
encrypter = pyaes.Encrypter(
pyaes.AESModeOfOperationCBC(self._hash.hash, iv=iv))
enc_data = encrypter.feed(self.MAGIC_DETECT_ENC + data)
enc_data += encrypter.feed()
def _encrypt(self, data: bytes, iv: bytes) -> bytes:
return aes_cbc_encrypt(self._hash.hash,
self.MAGIC_DETECT_ENC + data, iv)
return enc_data
def _decrypt(self, data, iv):
decrypter = pyaes.Decrypter(
pyaes.AESModeOfOperationCBC(self._hash.hash, iv=iv))
def _decrypt(self, data: bytes, iv: bytes) -> bytes:
try:
dec_data = decrypter.feed(data)
dec_data += decrypter.feed()
dec_data = aes_cbc_decrypt(self._hash.hash, data, iv)
except ValueError:
# in most "wrong password" cases the pkcs7 padding will be wrong
raise StoragePasswordError("Wrong password.")

2
jmclient/setup.py

@ -11,7 +11,7 @@ setup(name='joinmarketclient',
packages=['jmclient'],
install_requires=['joinmarketbase==0.9.10dev', 'mnemonic==0.20',
'argon2_cffi==21.3.0', 'bencoder.pyx==3.0.1',
'pyaes==1.6.1', 'klein==20.6.0', 'pyjwt==2.4.0',
'klein==20.6.0', 'pyjwt==2.4.0',
'autobahn==20.12.3', 'werkzeug==2.2.3'],
python_requires='>=3.6',
zip_safe=False)

Loading…
Cancel
Save