Switch to sslcrypto for cryptography tasks (#2338)

* Use sslcrypto instead of pyelliptic and pybitcointools

* Fix CryptMessage

* Support Python 3.4

* Fix user creation

* Get rid of pyelliptic and pybitcointools

* Fix typo

* Delete test file

* Add sslcrypto to tree

* Update sslcrypto

* Add pyaes to src/lib

* Fix typo in tests

* Update sslcrypto version

* Use privatekey_bin instead of privatekey for bytes objects

* Fix sslcrypto

* Fix Benchmark plugin

* Don't calculate the same thing twice

* Only import sslcrypto once

* Handle fallback sslcrypto implementation during tests

* Fix sslcrypto fallback implementation selection
This commit is contained in:
Ivanq 2019-12-15 14:46:06 +03:00 committed by ZeroNet
parent 28fcf3c1ea
commit fbc7b6fc4f
55 changed files with 3748 additions and 7287 deletions

View file

@ -5,24 +5,22 @@ import gevent
from Plugin import PluginManager
from Crypt import CryptBitcoin, CryptHash
import lib.pybitcointools as btctools
from Config import config
import sslcrypto
from . import CryptMessage
curve = sslcrypto.ecc.get_curve("secp256k1")
@PluginManager.registerTo("UiWebsocket")
class UiWebsocketPlugin(object):
def eciesDecrypt(self, encrypted, privatekey):
back = CryptMessage.getEcc(privatekey).decrypt(encrypted)
return back.decode("utf8")
# - Actions -
# Returns user's public key unique to site
# Return: Public key
def actionUserPublickey(self, to, index=0):
publickey = self.user.getEncryptPublickey(self.site.address, index)
self.response(to, publickey)
self.response(to, self.user.getEncryptPublickey(self.site.address, index))
# Encrypt a text using the publickey or user's sites unique publickey
# Return: Encrypted text using base64 encoding
@ -55,23 +53,16 @@ class UiWebsocketPlugin(object):
# Encrypt a text using AES
# Return: Iv, AES key, Encrypted text
def actionAesEncrypt(self, to, text, key=None, iv=None):
from lib import pyelliptic
def actionAesEncrypt(self, to, text, key=None):
if key:
key = base64.b64decode(key)
else:
key = os.urandom(32)
if iv: # Generate new AES key if not definied
iv = base64.b64decode(iv)
else:
iv = pyelliptic.Cipher.gen_IV('aes-256-cbc')
key = sslcrypto.aes.new_key()
if text:
encrypted = pyelliptic.Cipher(key, iv, 1, ciphername='aes-256-cbc').ciphering(text.encode("utf8"))
encrypted, iv = sslcrypto.aes.encrypt(text.encode("utf8"), key)
else:
encrypted = b""
encrypted, iv = b"", b""
res = [base64.b64encode(item).decode("utf8") for item in [key, iv, encrypted]]
self.response(to, res)
@ -79,8 +70,6 @@ class UiWebsocketPlugin(object):
# Decrypt a text using AES
# Return: Decrypted text
def actionAesDecrypt(self, to, *args):
from lib import pyelliptic
if len(args) == 3: # Single decrypt
encrypted_texts = [(args[0], args[1])]
keys = [args[2]]
@ -93,9 +82,8 @@ class UiWebsocketPlugin(object):
iv = base64.b64decode(iv)
text = None
for key in keys:
ctx = pyelliptic.Cipher(base64.b64decode(key), iv, 0, ciphername='aes-256-cbc')
try:
decrypted = ctx.ciphering(encrypted_text)
decrypted = sslcrypto.aes.decrypt(encrypted_text, iv, base64.b64decode(key))
if decrypted and decrypted.decode("utf8"): # Valid text decoded
text = decrypted.decode("utf8")
except Exception as err:
@ -122,12 +110,11 @@ class UiWebsocketPlugin(object):
# Gets the publickey of a given privatekey
def actionEccPrivToPub(self, to, privatekey):
self.response(to, btctools.privtopub(privatekey))
self.response(to, curve.private_to_public(curve.wif_to_private(privatekey)))
# Gets the address of a given publickey
def actionEccPubToAddr(self, to, publickey):
address = btctools.pubtoaddr(btctools.decode_pubkey(publickey))
self.response(to, address)
self.response(to, curve.public_to_address(bytes.fromhex(publickey)))
@PluginManager.registerTo("User")
@ -163,7 +150,7 @@ class UserPlugin(object):
if "encrypt_publickey_%s" % index not in site_data:
privatekey = self.getEncryptPrivatekey(address, param_index)
publickey = btctools.encode_pubkey(btctools.privtopub(privatekey), "bin_compressed")
publickey = curve.private_to_public(curve.wif_to_private(privatekey))
site_data["encrypt_publickey_%s" % index] = base64.b64encode(publickey).decode("utf8")
return site_data["encrypt_publickey_%s" % index]
@ -200,8 +187,8 @@ class ActionsPlugin:
aes_key, encrypted = CryptMessage.eciesEncrypt(self.utf8_text.encode("utf8"), self.publickey)
for i in range(num_run):
assert len(aes_key) == 32
ecc = CryptMessage.getEcc(self.privatekey)
assert ecc.decrypt(encrypted) == self.utf8_text.encode("utf8"), "%s != %s" % (ecc.decrypt(encrypted), self.utf8_text.encode("utf8"))
decrypted = CryptMessage.eciesDecrypt(base64.b64encode(encrypted), self.privatekey)
assert decrypted == self.utf8_text.encode("utf8"), "%s != %s" % (decrypted, self.utf8_text.encode("utf8"))
yield "."
def testCryptEciesDecryptMulti(self, num_run=1):
@ -223,23 +210,16 @@ class ActionsPlugin:
gevent.joinall(threads)
def testCryptAesEncrypt(self, num_run=1):
from lib import pyelliptic
for i in range(num_run):
key = os.urandom(32)
iv = pyelliptic.Cipher.gen_IV('aes-256-cbc')
encrypted = pyelliptic.Cipher(key, iv, 1, ciphername='aes-256-cbc').ciphering(self.utf8_text.encode("utf8"))
encrypted = sslcrypto.aes.encrypt(self.utf8_text.encode("utf8"), key)
yield "."
def testCryptAesDecrypt(self, num_run=1):
from lib import pyelliptic
key = os.urandom(32)
iv = pyelliptic.Cipher.gen_IV('aes-256-cbc')
encrypted_text = pyelliptic.Cipher(key, iv, 1, ciphername='aes-256-cbc').ciphering(self.utf8_text.encode("utf8"))
encrypted_text, iv = sslcrypto.aes.encrypt(self.utf8_text.encode("utf8"), key)
for i in range(num_run):
ctx = pyelliptic.Cipher(key, iv, 0, ciphername='aes-256-cbc')
decrypted = ctx.ciphering(encrypted_text).decode("utf8")
decrypted = sslcrypto.aes.decrypt(encrypted_text, iv, key).decode("utf8")
assert decrypted == self.utf8_text
yield "."