Skip to content

Commit

Permalink
Merge 5283187 into fdd477a
Browse files Browse the repository at this point in the history
  • Loading branch information
esneider committed May 13, 2015
2 parents fdd477a + 5283187 commit efe5b5d
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 35 deletions.
12 changes: 10 additions & 2 deletions jwt/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from .compat import constant_time_compare, string_types, text_type
from .exceptions import InvalidKeyError
from .utils import der_to_raw_signature, raw_to_der_signature

try:
from cryptography.hazmat.primitives import hashes
Expand Down Expand Up @@ -233,10 +234,17 @@ def sign(self, msg, key):
signer = key.signer(ec.ECDSA(self.hash_alg()))

signer.update(msg)
return signer.finalize()
der_sig = signer.finalize()

return der_to_raw_signature(der_sig, key.curve)

def verify(self, msg, key, sig):
verifier = key.verifier(sig, ec.ECDSA(self.hash_alg()))
try:
der_sig = raw_to_der_signature(sig, key.curve)
except ValueError:
return False

verifier = key.verifier(der_sig, ec.ECDSA(self.hash_alg()))

verifier.update(msg)

Expand Down
6 changes: 3 additions & 3 deletions jwt/contrib/algorithms/py_ecdsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ def prepare_key(self, key):

def sign(self, msg, key):
return key.sign(msg, hashfunc=self.hash_alg,
sigencode=ecdsa.util.sigencode_der)
sigencode=ecdsa.util.sigencode_string)

def verify(self, msg, key, sig):
try:
return key.verify(sig, msg, hashfunc=self.hash_alg,
sigdecode=ecdsa.util.sigdecode_der)
except ecdsa.der.UnexpectedDER:
sigdecode=ecdsa.util.sigdecode_string)
except AssertionError:
return False
40 changes: 40 additions & 0 deletions jwt/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import base64
import binascii

try:
from cryptography.hazmat.primitives.asymmetric.utils import (
decode_rfc6979_signature, encode_rfc6979_signature
)
except ImportError:
pass


def base64url_decode(input):
Expand All @@ -25,3 +33,35 @@ def merge_dict(original, updates):
raise TypeError('original and updates must be a dictionary: %s' % e)

return merged_options


def number_to_bytes(num, num_bytes):
padded_hex = '%0*x' % (2 * num_bytes, num)
big_endian = binascii.a2b_hex(padded_hex.encode('ascii'))
return big_endian


def bytes_to_number(string):
return int(binascii.b2a_hex(string), 16)


def der_to_raw_signature(der_sig, curve):
num_bits = curve.key_size
num_bytes = (num_bits + 7) // 8

r, s = decode_rfc6979_signature(der_sig)

return number_to_bytes(r, num_bytes) + number_to_bytes(s, num_bytes)


def raw_to_der_signature(raw_sig, curve):
num_bits = curve.key_size
num_bytes = (num_bits + 7) // 8

if len(raw_sig) != 2 * num_bytes:
raise ValueError('Invalid signature')

r = bytes_to_number(raw_sig[:num_bytes])
s = bytes_to_number(raw_sig[num_bytes:])

return encode_rfc6979_signature(r, s)
21 changes: 9 additions & 12 deletions tests/contrib/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,9 @@ def test_ec_sign_should_generate_correct_signature_value(self):
jwt_message = ensure_bytes('Hello World!')

expected_sig = base64.b64decode(ensure_bytes(
'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
'5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='))
'AC+m4Jf/xI3guAC6w0w37t5zRpSCF6F4udEz5LiMiTIjCS4vcVe6dDOxK+M'
'mvkF8PxJuvqxP2CO3TR3okDPCl/NjATTO1jE+qBZ966CRQSSzcCM+tzcHzw'
'LZS5kbvKu0Acd/K6Ol2/W3B1NeV5F/gjvZn/jOwaLgWEUYsg0o4XVrAg65'))

with open(key_path('testkey_ec'), 'r') as keyfile:
jwt_key = algo.prepare_key(keyfile.read())
Expand All @@ -151,10 +150,9 @@ def test_ec_verify_should_return_false_if_signature_invalid(self):
jwt_message = ensure_bytes('Hello World!')

jwt_sig = base64.b64decode(ensure_bytes(
'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
'5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='))
'AC+m4Jf/xI3guAC6w0w37t5zRpSCF6F4udEz5LiMiTIjCS4vcVe6dDOxK+M'
'mvkF8PxJuvqxP2CO3TR3okDPCl/NjATTO1jE+qBZ966CRQSSzcCM+tzcHzw'
'LZS5kbvKu0Acd/K6Ol2/W3B1NeV5F/gjvZn/jOwaLgWEUYsg0o4XVrAg65'))

jwt_sig += ensure_bytes('123') # Signature is now invalid

Expand All @@ -170,10 +168,9 @@ def test_ec_verify_should_return_true_if_signature_valid(self):
jwt_message = ensure_bytes('Hello World!')

jwt_sig = base64.b64decode(ensure_bytes(
'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
'5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='))
'AC+m4Jf/xI3guAC6w0w37t5zRpSCF6F4udEz5LiMiTIjCS4vcVe6dDOxK+M'
'mvkF8PxJuvqxP2CO3TR3okDPCl/NjATTO1jE+qBZ966CRQSSzcCM+tzcHzw'
'LZS5kbvKu0Acd/K6Ol2/W3B1NeV5F/gjvZn/jOwaLgWEUYsg0o4XVrAg65'))

with open(key_path('testkey_ec.pub'), 'r') as keyfile:
jwt_pub_key = algo.prepare_key(keyfile.read())
Expand Down
14 changes: 6 additions & 8 deletions tests/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,9 @@ def test_ec_verify_should_return_false_if_signature_invalid(self):

# Mess up the signature by replacing a known byte
sig = base64.b64decode(ensure_bytes(
'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
'5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='.replace('r', 's')))
'AC+m4Jf/xI3guAC6w0w37t5zRpSCF6F4udEz5LiMiTIjCS4vcVe6dDOxK+M'
'mvkF8PxJuvqxP2CO3TR3okDPCl/NjATTO1jE+qBZ966CRQSSzcCM+tzcHzw'
'LZS5kbvKu0Acd/K6Ol2/W3B1NeV5F/gjvZn/jOwaLgWEUYsg0o4XVrAg65'.replace('r', 's')))

with open(key_path('testkey_ec.pub'), 'r') as keyfile:
pub_key = algo.prepare_key(keyfile.read())
Expand All @@ -189,10 +188,9 @@ def test_ec_verify_should_return_true_if_signature_valid(self):
message = ensure_bytes('Hello World!')

sig = base64.b64decode(ensure_bytes(
'MIGIAkIB9vYz+inBL8aOTA4auYz/zVuig7TT1bQgKROIQX9YpViHkFa4DT5'
'5FuFKn9XzVlk90p6ldEj42DC9YecXHbC2t+cCQgCicY+8f3f/KCNtWK7cif'
'6vdsVwm6Lrjs0Ag6ZqCf+olN11hVt1qKBC4lXppqB1gNWEmNQaiz1z2QRyc'
'zJ8hSJmbw=='))
'AC+m4Jf/xI3guAC6w0w37t5zRpSCF6F4udEz5LiMiTIjCS4vcVe6dDOxK+M'
'mvkF8PxJuvqxP2CO3TR3okDPCl/NjATTO1jE+qBZ966CRQSSzcCM+tzcHzw'
'LZS5kbvKu0Acd/K6Ol2/W3B1NeV5F/gjvZn/jOwaLgWEUYsg0o4XVrAg65'))

with open(key_path('testkey_ec.pub'), 'r') as keyfile:
pub_key = algo.prepare_key(keyfile.read())
Expand Down
9 changes: 4 additions & 5 deletions tests/test_api_jws.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,10 @@ def test_decodes_valid_es384_jws(self, jws):
example_jws = (
b'eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9'
b'.eyJoZWxsbyI6IndvcmxkIn0'
b'.MIGHAkEdh2kR7IRu5w0tGuY6Xz3Vqa7PHHY2DgXWeee'
b'LXotEqpn9udp2NfVL-XFG0TDoCakzXbIGAWg42S69GFl'
b'KZzxhXAJCAPLPuJoKyAixFnXPBkvkti-UzSIj4s6DePe'
b'uTu7102G_QIXiijY5bx6mdmZa3xUuKeu-zobOIOqR8Zw'
b'FqGjBLZum')
b'.AGtlemKghaIaYh1yeeekFH9fRuNY7hCaw5hUgZ5aG1N'
b'2F8FIbiKLaZKr8SiFdTimXFVTEmxpBQ9sRmdsDsnrM-1'
b'HAG0_zxxu0JyINOFT2iqF3URYl9HZ8kZWMeZAtXmn6Cw'
b'PXRJD2f7N-f7bJ5JeL9VT5beI2XD3FlK3GgRvI-eE-2Ik')
decoded_payload = jws.decode(example_jws, example_pubkey)
json_payload = json.loads(ensure_unicode(decoded_payload))

Expand Down
9 changes: 4 additions & 5 deletions tests/test_api_jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,10 @@ def test_decodes_valid_es384_jwt(self, jwt):
example_jwt = (
b'eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9'
b'.eyJoZWxsbyI6IndvcmxkIn0'
b'.MIGHAkEdh2kR7IRu5w0tGuY6Xz3Vqa7PHHY2DgXWeee'
b'LXotEqpn9udp2NfVL-XFG0TDoCakzXbIGAWg42S69GFl'
b'KZzxhXAJCAPLPuJoKyAixFnXPBkvkti-UzSIj4s6DePe'
b'uTu7102G_QIXiijY5bx6mdmZa3xUuKeu-zobOIOqR8Zw'
b'FqGjBLZum')
b'.AddMgkmRhzqptDYqlmy_f2dzM6O9YZmVo-txs_CeAJD'
b'NoD8LN7YiPeLmtIhkO5_VZeHHKvtQcGc4lsq-Y72c4dK'
b'pANr1f6HEYhjpBc03u_bv06PYMcr5N2-9k97-qf-JCSb'
b'zqW6R250Q7gNCX5R7NrCl7MTM4DTBZkGbUlqsFUleiGlj')
decoded_payload = jwt.decode(example_jwt, example_pubkey)

assert decoded_payload == example_payload
Expand Down

0 comments on commit efe5b5d

Please sign in to comment.