Skip to content

Commit

Permalink
Merge pull request #143 from andrewwhitehead/pynacl-support
Browse files Browse the repository at this point in the history
Switch to PyNaCl instead of pysodium; update dependencies
  • Loading branch information
swcurran authored Aug 14, 2019
2 parents 02050bd + 5fc8b60 commit 3081f10
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 52 deletions.
10 changes: 5 additions & 5 deletions aries_cloudagent/messaging/agent_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def __init__(self, *args, **kwargs):
self._signatures = {}

@pre_load
def extract_decorators(self, data):
def extract_decorators(self, data, **kwargs):
"""
Pre-load hook to extract the decorators and check the signed fields.
Expand Down Expand Up @@ -364,7 +364,7 @@ def extract_decorators(self, data):
return processed

@post_load
def populate_decorators(self, obj):
def populate_decorators(self, obj, **kwargs):
"""
Post-load hook to populate decorators on the message.
Expand All @@ -379,7 +379,7 @@ def populate_decorators(self, obj):
return obj

@pre_dump
def check_dump_decorators(self, obj):
def check_dump_decorators(self, obj, **kwargs):
"""
Pre-dump hook to validate and load the message decorators.
Expand Down Expand Up @@ -410,7 +410,7 @@ def check_dump_decorators(self, obj):
return obj

@post_dump
def dump_decorators(self, data):
def dump_decorators(self, data, **kwargs):
"""
Post-dump hook to write the decorators to the serialized output.
Expand All @@ -430,7 +430,7 @@ def dump_decorators(self, data):
return result

@post_dump
def replace_signatures(self, data):
def replace_signatures(self, data, **kwargs):
"""
Post-dump hook to write the signatures to the serialized output.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class Meta:
image_url = fields.Str(data_key="imageUrl", required=False, allow_none=True)

@validates_schema
def validate_fields(self, data):
def validate_fields(self, data, **kwargs):
"""
Validate schema fields.
Expand Down
6 changes: 3 additions & 3 deletions aries_cloudagent/messaging/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def Model(self) -> type:
return self._get_model_class()

@pre_load
def skip_dump_only(self, data):
def skip_dump_only(self, data, **kwargs):
"""
Skip fields that are only expected during serialization.
Expand All @@ -265,7 +265,7 @@ def skip_dump_only(self, data):
return data

@post_load
def make_model(self, data: dict):
def make_model(self, data: dict, **kwargs):
"""
Return model instance after loading.
Expand All @@ -276,7 +276,7 @@ def make_model(self, data: dict):
return self.Model(**data)

@post_dump
def remove_skipped_values(self, data):
def remove_skipped_values(self, data, **kwargs):
"""
Remove values that are are marked to skip.
Expand Down
82 changes: 44 additions & 38 deletions aries_cloudagent/wallet/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

from marshmallow import fields, Schema, ValidationError
import msgpack
import pysodium
import nacl.bindings
import nacl.exceptions
import nacl.utils

from .error import WalletError
from .util import bytes_to_b58, bytes_to_b64, b64_to_bytes, b58_to_bytes
Expand Down Expand Up @@ -58,7 +60,7 @@ def create_keypair(seed: bytes = None) -> (bytes, bytes):
"""
if not seed:
seed = random_seed()
pk, sk = pysodium.crypto_sign_seed_keypair(seed)
pk, sk = nacl.bindings.crypto_sign_seed_keypair(seed)
return pk, sk


Expand All @@ -70,7 +72,7 @@ def random_seed() -> bytes:
A new random seed
"""
return pysodium.randombytes(pysodium.crypto_secretbox_KEYBYTES)
return nacl.utils.random(nacl.bindings.crypto_box_SEEDBYTES)


def seed_to_did(seed: str) -> str:
Expand Down Expand Up @@ -127,8 +129,8 @@ def sign_message(message: bytes, secret: bytes) -> bytes:
The signature
"""
result = pysodium.crypto_sign(message, secret)
sig = result[: pysodium.crypto_sign_BYTES]
result = nacl.bindings.crypto_sign(message, secret)
sig = result[: nacl.bindings.crypto_sign_BYTES]
return sig


Expand All @@ -145,8 +147,8 @@ def verify_signed_message(signed: bytes, verkey: bytes) -> bool:
"""
try:
pysodium.crypto_sign_open(signed, verkey)
except ValueError:
nacl.bindings.crypto_sign_open(signed, verkey)
except nacl.exceptions.BadSignatureError:
return False
return True

Expand All @@ -163,8 +165,8 @@ def anon_crypt_message(message: bytes, to_verkey: bytes) -> bytes:
The anon encrypted message
"""
pk = pysodium.crypto_sign_pk_to_box_pk(to_verkey)
enc_message = pysodium.crypto_box_seal(message, pk)
pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(to_verkey)
enc_message = nacl.bindings.crypto_box_seal(message, pk)
return enc_message


Expand All @@ -181,10 +183,10 @@ def anon_decrypt_message(enc_message: bytes, secret: bytes) -> bytes:
"""
sign_pk, sign_sk = create_keypair(secret)
pk = pysodium.crypto_sign_pk_to_box_pk(sign_pk)
sk = pysodium.crypto_sign_sk_to_box_sk(sign_sk)
pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(sign_pk)
sk = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sign_sk)

message = pysodium.crypto_box_seal_open(enc_message, pk, sk)
message = nacl.bindings.crypto_box_seal_open(enc_message, pk, sk)
return message


Expand All @@ -201,11 +203,11 @@ def auth_crypt_message(message: bytes, to_verkey: bytes, from_secret: bytes) ->
The encrypted message
"""
nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES)
target_pk = pysodium.crypto_sign_pk_to_box_pk(to_verkey)
nonce = nacl.utils.random(nacl.bindings.crypto_box_NONCEBYTES)
target_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(to_verkey)
sender_pk, sender_sk = create_keypair(from_secret)
sk = pysodium.crypto_sign_sk_to_box_sk(sender_sk)
enc_body = pysodium.crypto_box(message, nonce, target_pk, sk)
sk = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sender_sk)
enc_body = nacl.bindings.crypto_box(message, nonce, target_pk, sk)
combo_box = OrderedDict(
[
("msg", bytes_to_b64(enc_body)),
Expand All @@ -214,7 +216,7 @@ def auth_crypt_message(message: bytes, to_verkey: bytes, from_secret: bytes) ->
]
)
combo_box_bin = msgpack.packb(combo_box, use_bin_type=True)
enc_message = pysodium.crypto_box_seal(combo_box_bin, target_pk)
enc_message = nacl.bindings.crypto_box_seal(combo_box_bin, target_pk)
return enc_message


Expand All @@ -231,16 +233,18 @@ def auth_decrypt_message(enc_message: bytes, secret: bytes) -> (bytes, str):
"""
sign_pk, sign_sk = create_keypair(secret)
pk = pysodium.crypto_sign_pk_to_box_pk(sign_pk)
sk = pysodium.crypto_sign_sk_to_box_sk(sign_sk)
body = pysodium.crypto_box_seal_open(enc_message, pk, sk)
pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(sign_pk)
sk = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sign_sk)
body = nacl.bindings.crypto_box_seal_open(enc_message, pk, sk)

unpacked = msgpack.unpackb(body, raw=False)
sender_vk = unpacked["sender"]
nonce = b64_to_bytes(unpacked["nonce"])
enc_message = b64_to_bytes(unpacked["msg"])
sender_pk = pysodium.crypto_sign_pk_to_box_pk(b58_to_bytes(sender_vk))
message = pysodium.crypto_box_open(enc_message, nonce, sender_pk, sk)
sender_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(
b58_to_bytes(sender_vk)
)
message = nacl.bindings.crypto_box_open(enc_message, nonce, sender_pk, sk)
return message, sender_vk


Expand All @@ -258,23 +262,23 @@ def prepare_pack_recipient_keys(
A tuple of (json result, key)
"""
cek = pysodium.crypto_secretstream_xchacha20poly1305_keygen()
cek = nacl.bindings.crypto_secretstream_xchacha20poly1305_keygen()
recips = []

for target_vk in to_verkeys:
target_pk = pysodium.crypto_sign_pk_to_box_pk(target_vk)
target_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(target_vk)
if from_secret:
sender_pk, sender_sk = create_keypair(from_secret)
sender_vk = bytes_to_b58(sender_pk).encode("ascii")
enc_sender = pysodium.crypto_box_seal(sender_vk, target_pk)
sk = pysodium.crypto_sign_sk_to_box_sk(sender_sk)
enc_sender = nacl.bindings.crypto_box_seal(sender_vk, target_pk)
sk = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(sender_sk)

nonce = pysodium.randombytes(pysodium.crypto_box_NONCEBYTES)
enc_cek = pysodium.crypto_box(cek, nonce, target_pk, sk)
nonce = nacl.utils.random(nacl.bindings.crypto_box_NONCEBYTES)
enc_cek = nacl.bindings.crypto_box(cek, nonce, target_pk, sk)
else:
enc_sender = None
nonce = None
enc_cek = pysodium.crypto_box_seal(cek, target_pk)
enc_cek = nacl.bindings.crypto_box_seal(cek, target_pk)

recips.append(
OrderedDict(
Expand Down Expand Up @@ -346,8 +350,8 @@ def locate_pack_recipient_key(
not_found.append(recip_vk_b58)
continue
recip_vk = b58_to_bytes(recip_vk_b58)
pk = pysodium.crypto_sign_pk_to_box_pk(recip_vk)
sk = pysodium.crypto_sign_sk_to_box_sk(secret)
pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(recip_vk)
sk = nacl.bindings.crypto_sign_ed25519_sk_to_curve25519(secret)

encrypted_key = b64_to_bytes(recip["encrypted_key"], urlsafe=True)

Expand All @@ -357,13 +361,15 @@ def locate_pack_recipient_key(
enc_sender = b64_to_bytes(sender_b64, urlsafe=True) if sender_b64 else None

if nonce and enc_sender:
sender_vk_bin = pysodium.crypto_box_seal_open(enc_sender, pk, sk)
sender_vk_bin = nacl.bindings.crypto_box_seal_open(enc_sender, pk, sk)
sender_vk = sender_vk_bin.decode("ascii")
sender_pk = pysodium.crypto_sign_pk_to_box_pk(b58_to_bytes(sender_vk_bin))
cek = pysodium.crypto_box_open(encrypted_key, nonce, sender_pk, sk)
sender_pk = nacl.bindings.crypto_sign_ed25519_pk_to_curve25519(
b58_to_bytes(sender_vk_bin)
)
cek = nacl.bindings.crypto_box_open(encrypted_key, nonce, sender_pk, sk)
else:
sender_vk = None
cek = pysodium.crypto_box_seal_open(encrypted_key, pk, sk)
cek = nacl.bindings.crypto_box_seal_open(encrypted_key, pk, sk)
return cek, sender_vk, recip_vk_b58
raise ValueError("No corresponding recipient key found in {}".format(not_found))

Expand All @@ -383,9 +389,9 @@ def encrypt_plaintext(
A tuple of (ciphertext, nonce, tag)
"""
nonce = pysodium.randombytes(pysodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
nonce = nacl.utils.random(nacl.bindings.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
message_bin = message.encode("ascii")
output = pysodium.crypto_aead_chacha20poly1305_ietf_encrypt(
output = nacl.bindings.crypto_aead_chacha20poly1305_ietf_encrypt(
message_bin, add_data, nonce, key
)
mlen = len(message)
Expand All @@ -410,7 +416,7 @@ def decrypt_plaintext(
The decrypted string
"""
output = pysodium.crypto_aead_chacha20poly1305_ietf_decrypt(
output = nacl.bindings.crypto_aead_chacha20poly1305_ietf_decrypt(
ciphertext, recips_bin, nonce, key
)
return output.decode("ascii")
Expand Down
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
aiohttp~=3.5.4
aiohttp-apispec~=1.1.2
aiohttp-cors~=0.7.0
base58
Markdown>=3.1.1
marshmallow==3.0.0rc3
msgpack>=0.6.1<0.7
base58~=1.0.3
Markdown~=3.1.1
marshmallow==3.0.0rc9
msgpack~=0.6.1
prompt_toolkit~=2.0.9
pysodium>=0.7.1<0.8
pynacl~=1.3.0

0 comments on commit 3081f10

Please sign in to comment.