Skip to content

Commit 5d5fba9

Browse files
committed
Added methods that will tell you if a key is public/private.
Symmetric keys are both/neither.
1 parent 4503b77 commit 5d5fba9

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

src/cryptojwt/jwk.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def der_cert(der_data):
129129
"""
130130
Load a DER encoded certificate
131131
132-
@param der: DER-encoded certificate
132+
@param der_data: DER-encoded certificate
133133
@return: RSA instance
134134
"""
135135
if isinstance(der_data, str):
@@ -496,6 +496,16 @@ def add_kid(self):
496496
"""
497497
self.kid = b64e(self.thumbprint('SHA-256')).decode('utf8')
498498

499+
def is_private_key(self):
500+
for p in self.members:
501+
if p not in self.public_members:
502+
if getattr(self, p):
503+
return True
504+
return False
505+
506+
def is_public_key(self):
507+
return not self.is_private_key()
508+
499509

500510
def deser(val):
501511
"""
@@ -570,13 +580,13 @@ class RSAKey(Key):
570580
571581
Parameters according to https://tools.ietf.org/html/rfc7518#section-6.3
572582
"""
573-
members = Key.members
583+
members = Key.members[:]
574584
# These are the RSA key specific parameters, they are always supposed to
575585
# be strings or bytes
576586
members.extend(["n", "e", "d", "p", "q"])
577587
# The parameters that represent long ints in the key instances
578588
longs = ["n", "e", "d", "p", "q", "dp", "dq", "di", "qi"]
579-
public_members = Key.public_members
589+
public_members = Key.public_members[:]
580590
# the public members of the key
581591
public_members.extend(["n", "e"])
582592
required = ['kty', 'n', 'e']
@@ -813,11 +823,12 @@ class ECKey(Key):
813823
814824
Parameters according to https://tools.ietf.org/html/rfc7518#section-6.2
815825
"""
816-
members = Key.members
826+
members = Key.members[:]
817827
# The elliptic curve specific attributes
818828
members.extend(["crv", "x", "y", "d"])
819829
longs = ['x', 'y', 'd']
820-
public_members = ["kty", "alg", "use", "kid", "crv", "x", "y"]
830+
public_members = Key.public_members[:]
831+
public_members.extend(["kty", "alg", "use", "kid", "crv", "x", "y"])
821832
required = ['crv', 'key', 'x', 'y']
822833

823834
def __init__(self, kty="EC", alg="", use="", kid="", key=None,
@@ -992,8 +1003,9 @@ class SYMKey(Key):
9921003
}
9931004
9941005
"""
995-
members = ["kty", "alg", "use", "kid", "k"]
996-
public_members = members[:]
1006+
members = Key.members[:]
1007+
members.extend(["kty", "alg", "use", "kid", "k"])
1008+
public_members = Key.public_members[:]
9971009
required = ['k', 'kty']
9981010

9991011
def __init__(self, kty="oct", alg="", use="", kid="", key=None,
@@ -1046,6 +1058,12 @@ def encryption_key(self, alg, **kwargs):
10461058

10471059
return _enc_key
10481060

1061+
def is_private_key(self):
1062+
return True
1063+
1064+
def is_public_key(self):
1065+
return True
1066+
10491067

10501068
# -----------------------------------------------------------------------------
10511069

@@ -1181,7 +1199,7 @@ def __getitem__(self, item):
11811199
"""
11821200
Get all keys of a specific key type
11831201
1184-
:param kty: Key type
1202+
:param item: Key type
11851203
:return: list of keys
11861204
"""
11871205
kty = item.lower()

src/cryptojwt/jws.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from cryptojwt.exception import UnSupported
4040
from cryptojwt.exception import WrongNumberOfParts
4141

42-
from cryptojwt.jwk import load_x509_cert
42+
from cryptojwt.jwk import load_x509_cert, SYMKey
4343
from cryptojwt.jwk import KEYS
4444
from cryptojwt.jwk import sha256_digest
4545
from cryptojwt.jwk import sha384_digest
@@ -156,9 +156,12 @@ def verify(self, msg, signature, key):
156156
self.hash_algorithm())
157157
except InvalidSignature as err:
158158
raise BadSignature(str(err))
159+
except AttributeError: # If private key
160+
return False
159161
else:
160162
return True
161163

164+
162165
class DSASigner(Signer):
163166
def __init__(self, algorithm='SHA256'):
164167
if algorithm == 'SHA256':
@@ -595,6 +598,11 @@ def verify_compact_verbose(self, jws, keys=None, allow_none=False,
595598
verifier = SIGNER_ALGS[_alg]
596599

597600
for key in _keys:
601+
# Can not use asymmetric private key for verifying
602+
if not isinstance(key, SYMKey):
603+
if key.is_private_key():
604+
continue
605+
598606
try:
599607
verifier.verify(jwt.sign_input(), jwt.signature(),
600608
key.get_key(alg=_alg, private=False))

tests/test_2_jwk.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ def test_kspec():
9797
assert jwk["e"] == JWK["keys"][0]["e"]
9898
assert jwk["n"] == JWK["keys"][0]["n"]
9999

100+
assert not _key.is_private_key()
101+
100102

101103
def test_loads_0():
102104
keys = KEYS()
@@ -198,6 +200,8 @@ def test_serialize_rsa_priv_key():
198200
restored_key = RSAKey(**d_rsakey)
199201

200202
assert restored_key == rsakey
203+
assert rsakey.is_private_key()
204+
assert restored_key.is_private_key()
201205

202206

203207
ECKEY = {

0 commit comments

Comments
 (0)