Skip to content

Commit

Permalink
More work
Browse files Browse the repository at this point in the history
  • Loading branch information
atombrella committed Jul 10, 2021
1 parent f7ee455 commit b81faf6
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 46 deletions.
35 changes: 14 additions & 21 deletions src/josepy/jwa.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
"""
import abc
import logging
from typing import Dict, Type, Union
from typing import Dict, Type

import cryptography.exceptions
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import hmac
from cryptography.hazmat.primitives.asymmetric import ec, x25519, x448
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives.asymmetric import ed448
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature
Expand Down Expand Up @@ -233,20 +231,15 @@ def __init__(self, name, hash_):
super().__init__(name)
self.hash = hash_()

def sign(self, key: Union[
ed25519.Ed25519PrivateKey,
ed448.Ed448PrivateKey,
x25519.X25519PrivateKey,
x448.X448PrivateKey,
], msg: bytes):
@classmethod
def register(cls, signature_cls):
# might need to overwrite this, so I can get the argument in
return super().register(signature_cls)

def sign(self, key, msg: bytes):
return key.sign(msg)

def verify(self, key: Union[
ed25519.Ed25519PublicKey,
ed448.Ed448PublicKey,
x25519.X25519PrivateKey,
x448.X448PrivateKey,
], msg: bytes, sig: bytes):
def verify(self, key, msg: bytes, sig: bytes):
try:
key.verify(signature=sig, data=msg)
except cryptography.exceptions.InvalidSignature as error:
Expand Down Expand Up @@ -287,8 +280,8 @@ def verify(self, key: Union[
#: Ed25519 uses SHA512
ES25519 = JWASignature.register(_JWAOKP('ES25519', hashes.SHA512))
#: Ed448 uses SHA3/SHAKE256
ES448 = JWASignature.register(_JWAOKP('ES448', hashes.SHAKE256))
#: X25519 uses
X22519 = JWASignature.register(_JWAOKP('X22519', hashes.SHAKE256))
#: X448 uses
X448 = JWASignature.register(_JWAOKP('X448', hashes.SHAKE256))
# ES448 = JWASignature.register(_JWAOKP('ES448', hashes.SHAKE256))
# #: X25519 uses SHA3/SHAKE256
# X22519 = JWASignature.register(_JWAOKP('X22519', hashes.SHAKE256))
# #: X448 uses SHA3/SHAKE256
# X448 = JWASignature.register(_JWAOKP('X448', hashes.SHAKE256))
25 changes: 12 additions & 13 deletions src/josepy/jwa_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from unittest import mock

from josepy import errors, test_util
from josepy.jwa import ES25519

RSA256_KEY = test_util.load_rsa_private_key('rsa256_key.pem')
RSA512_KEY = test_util.load_rsa_private_key('rsa512_key.pem')
Expand Down Expand Up @@ -231,18 +230,18 @@ def test_signature_size(self):
self.assertEqual(len(sig), 2 * 66)


class JWAOKPTests(JWASignatureTest):
# look up the signature sizes in the RFC

def test_sign_no_private_part(self):
from josepy.jwa import ES25519
self.assertRaises(errors.Error, ES25519.sign, OKP_ED25519_KEY, b'foo')

def test_can_size_ed25519(self):
ES25519.sign(b'foo'), OKP_ED25519_KEY,

def test_signature_size(self):
pass
# class JWAOKPTests(JWASignatureTest):
# # look up the signature sizes in the RFC
#
# def test_sign_no_private_part(self):
# from josepy.jwa import ES25519
# self.assertRaises(errors.Error, ES25519.sign, OKP_ED25519_KEY, b'foo')
#
# # def test_can_size_ed25519(self):
# # ES25519.sign(b'foo'), OKP_ED25519_KEY,
#
# def test_signature_size(self):
# pass


if __name__ == '__main__':
Expand Down
16 changes: 8 additions & 8 deletions src/josepy/jwk.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import logging
import math

from typing import Dict, Optional, Sequence, Tuple, Type, Union
from typing import Dict, Optional, Sequence, Type, Union

import cryptography.exceptions
from cryptography.hazmat.backends import default_backend
Expand Down Expand Up @@ -402,7 +402,7 @@ class JWKOKP(JWK):
x448.X448PrivateKey, x448.X448PublicKey,
)
required = ('crv', JWK.type_field_name, 'x')
crv_to_pub_priv: Dict[str, Tuple] = {
crv_to_pub_priv = {
"Ed25519": (ed25519.Ed25519PublicKey, ed25519.Ed25519PrivateKey),
"Ed448": (ed448.Ed448PublicKey, ed448.Ed448PrivateKey),
"X25519": (x25519.X25519PublicKey, x25519.X25519PrivateKey),
Expand Down Expand Up @@ -442,8 +442,8 @@ def fields_to_partial_json(self) -> Dict:
)
else:
params['x'] = json_util.encode_b64jose(self.key.public_bytes(
serialization.Encoding.Raw,
serialization.PublicFormat.Raw,
encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw,
))
params['crv'] = self._key_to_crv()
return params
Expand Down Expand Up @@ -473,21 +473,21 @@ def fields_from_json(cls, jobj):

try:
if "d" not in obj: # public key
pub_class: Union[
pub_class: Type[Union[
ed25519.Ed25519PublicKey,
ed448.Ed448PublicKey,
x25519.X25519PublicKey,
x448.X448PublicKey,
] = cls.crv_to_pub_priv[curve][0]
]] = cls.crv_to_pub_priv[curve][0]
return cls(key=pub_class.from_public_bytes(x))
else: # private key
d = json_util.decode_b64jose(obj.get("d"))
priv_key_class: Union[
priv_key_class: Type[Union[
ed25519.Ed25519PrivateKey,
ed448.Ed448PrivateKey,
x25519.X25519PrivateKey,
x448.X448PrivateKey,
] = cls.crv_to_pub_priv[curve][1]
]] = cls.crv_to_pub_priv[curve][1]
return cls(key=priv_key_class.from_private_bytes(d))
except ValueError as err:
raise errors.DeserializationError("Invalid key parameter") from err
12 changes: 9 additions & 3 deletions src/josepy/jwk_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,14 @@ def test_encode_ed25519(self):
x = josepy.json_util.encode_b64jose(data['x'])
self.assertEqual(x, "9ujoz88QZL05w2lhaqUbBaBpwmM12Y7Y8Ybfwjibk-I")

def test_from_json_ed25519(self):
def test_from_json(self):
from josepy.jwk import JWK
key = JWK.from_json(self.jwked25519json)
with self.subTest(key=[
self.jwked448json, self.jwked25519json,
self.jwkx25519json, self.jwkx448json,
self.jwked448json,
self.jwked25519json,
self.jwkx25519json,
self.jwkx448json,
]):
self.assertIsInstance(key.key, util.ComparableOKPKey)

Expand All @@ -419,6 +421,10 @@ def test_unknown_crv_name(self):
}
)

def test_from_json_hashable(self):
from josepy.jwk import JWK
hash(JWK.from_json(self.jwked25519json))


if __name__ == '__main__':
unittest.main() # pragma: no cover
12 changes: 11 additions & 1 deletion src/josepy/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import OpenSSL
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import (
ec,
ed25519, ed448,
Expand Down Expand Up @@ -178,7 +179,16 @@ class ComparableOKPKey(ComparableKey):
"""

def __hash__(self):
return hash((self.__class__, self._wrapped.curve.name, self._wrapped.x))
if self.is_private():
priv = self._wrapped.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
)
pub = priv.public_key
return hash((self.__class__, pub.curve.name, priv))
else:
pub = self._wrapped.public_key()
return hash((self.__class__, pub.curve.name, pub))

def is_private(self) -> bool:
return isinstance(
Expand Down

0 comments on commit b81faf6

Please sign in to comment.