def test_base64(self): ''' nose2 jose.tests.test_utils.TestBase64.test_base64 ''' self.assertEquals('QWxpY2U', base64.base64url_encode('Alice')) self.assertEquals('Qm9i', base64.base64url_encode('Bob')) self.assertEquals('Alice', base64.base64url_decode('QWxpY2U')) self.assertEquals('Bob', base64.base64url_decode('Qm9i')) self.assertEquals( '=', base64.base64url_decode(base64.base64url_encode('=')))
def render_protected(self): ''' convert "_protected" Jws object to "protected" in BASE64URL encoded string ''' if self._protected: self.protected = base64.base64url_encode( self._protected.to_json())
def wrap_command(): parser = ArgumentParser(description='PBES2 Key Derivation') parser.add_argument('command', help="wrap") parser.add_argument('password') parser.add_argument('cek', nargs='?', default=None, type=basestring) parser.add_argument('key_len', nargs='?', default=16, type=int) parser.add_argument('-f', '--foo') parser.add_argument('-s', '--salt', dest="salt", action="store", default=None, help='base64salt') parser.add_argument('-a', '--alg', dest="alg", action="store", default='HS256', help='HS256|HS384|HS512') parser.add_argument('-c', '--count', dest="count", action="store", type=int, default=1024, help='KDF2 counter') args = parser.parse_args() wrapper = dict( HS256=KeyEncEnum.PBES2_HS384_A192KW, HS348=KeyEncEnum.PBES2_HS384_A192KW, HS512=KeyEncEnum.PBES2_HS512_A256KW, )[args.alg].encryptor if args.cek: cek = base64.base64url_decode(args.cek) else: cek = Random.get_random_bytes(args.key_len) jwk = Jwk(kty=keys.KeyTypeEnum.OCT) if args.password == 'random': jwk.k = base64.base64url_encode( Random.get_random_bytes(wrapper.key_length())) elif args.password.startswith('b64url:'): jwk.k = args.password[6:] else: jwk.k = base64.base64url_encode(args.password) salt = args.salt or base64.base64url_encode( Random.get_random_bytes(wrapper.key_length())) assert len(jwk.key.shared_key) == wrapper.key_length() kek = wrapper.derive(jwk, salt, args.count) cek_ci = wrapper.encrypt(kek, cek) print "share key(b64url)=", base64.base64url_encode(jwk.k), print "cek(b64url)=", base64.base64url_encode(cek) print "salt(b64url)=", base64.base64url_encode(salt), print "kek(b64url)=", base64.base64url_encode(kek), print "warapped cek(b64url)=", base64.base64url_encode(cek_ci), print "key length=", args.key_len, print "alg=", args.alg, wrapper.__name__, print "count=", args.count
def test_hmac(self): jwk = Jwk( kty="oct", k=''.join([ 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75' 'aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow']) ) self.assertEqual(jwk.k, base64.base64url_encode(jwk.key.material)) msg = "Best of my life." for mac in [HS256, HS384, HS512]: sig = mac().sign(jwk, msg) self.assertTrue(mac().verify(jwk, msg, sig))
def derive_command(): parser = ArgumentParser(description='PBES2 Key Derivation') parser.add_argument('command') parser.add_argument('password') parser.add_argument('key_len', nargs='?', default=16, type=int) parser.add_argument('-f', '--foo') parser.add_argument('-d', '--digest', dest="digest", action="store", default='sha256', help='sha256|384|512') parser.add_argument('-s', '--salt', dest="salt", action="store", default=None, help='base64salt') args = parser.parse_args() klen = args.key_len digest = dict(sha256=SHA256, sha384=SHA384, sha512=SHA512)[args.digest] if args.password == 'random': key = Random.get_random_bytes(klen) elif args.password.startswith('b64url:'): key = base64.base64url_decode(args.password[6:]) else: key = args.password if isinstance(args.salt, basestring): salt = base64.base64url_decode(args.salt) else: salt = Random.get_random_bytes(32) key, derived_key, salt, count = derive( key, salt, klen=klen, digest=digest) print "passowrd(b64url)=", base64.base64url_encode(key), print "key(b64url)=", base64.base64url_encode(derived_key), print "salt(b64url)=", base64.base64url_encode(salt), print "key length=", klen, print "digest=", args.digest, print "count=", count
def sign(self, b64_payload, jwk): #: TODO: load key from store if signing_jwk is None #: only self._protected is used for Jwk parameter jws = self.all_header() if not jws.kid: if jwk.kid: self.header.kid = jwk.kid else: assert jws.kid == jwk.kid self.render_protected() s_input = self.signing_input(b64_payload) self.signature = base64.base64url_encode( jws.sign(s_input, jwk))
def _BE(s): # b64encode return base64.base64url_encode(s)
def test_rs256(self): ''' nose2 jose.tests.test_jws.TestJws.test_rs256''' ''' JWS A.2 ''' octes = [123, 34, 97, 108, 103, 34, 58, 34, 82, 83, 50, 53, 54, 34, 125] jws_str = ''.join(chr(i) for i in octes) self.assertEqual(jws_str, '{"alg":"RS256"}') jws_new = Jws.from_json(jws_str) self.assertEqual(jws_new.alg, SigEnum.RS256) b64_header = base64.base64url_encode(jws_str) self.assertEqual(b64_header, 'eyJhbGciOiJSUzI1NiJ9') b64_payload = ''.join([ 'eyJpc3MiOiJqb2UiLA0KICJleHAiOj', 'EzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt', 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ']) payload = base64.base64url_decode(b64_payload) jwt_new = Jwt.from_json(payload) self.assertEqual(jwt_new.iss, "joe") self.assertEqual(jwt_new.exp, 1300819380) self.assertEqual(jwt_new['http://example.com/is_root'], True) s_input = [ 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 122, 73, 49, 78, 105, 74, 57, 46, 101, 121, 74, 112, 99, 51, 77, 105, 79, 105, 74, 113, 98, 50, 85, 105, 76, 65, 48, 75, 73, 67, 74, 108, 101, 72, 65, 105, 79, 106, 69, 122, 77, 68, 65, 52, 77, 84, 107, 122, 79, 68, 65, 115, 68, 81, 111, 103, 73, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 108, 101, 71, 70, 116, 99, 71, 120, 108, 76, 109, 78, 118, 98, 83, 57, 112, 99, 49, 57, 121, 98, 50, 57, 48, 73, 106, 112, 48, 99, 110, 86, 108, 102, 81] s_input_str = "".join(chr(i) for i in s_input) self.assertEqual( s_input_str, ".".join([b64_header, b64_payload])) pri_json_dict = { "kty": "RSA", "n": "".join([ "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx", "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs", "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH", "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV", "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8", "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ"]), "e": "AQAB", "d": "".join([ "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I", "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0", "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn", "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT", "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh", "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ"]), } jwk = Jwk(**pri_json_dict) self.assertTrue(jwk.key.is_private) signer = jws_new.alg.signer from jose.jwa.rsa import RS256 self.assertEqual(signer, RS256) sig_calc = signer.sign(jwk, s_input_str) sig = [ 112, 46, 33, 137, 67, 232, 143, 209, 30, 181, 216, 45, 191, 120, 69, 243, 65, 6, 174, 27, 129, 255, 247, 115, 17, 22, 173, 209, 113, 125, 131, 101, 109, 66, 10, 253, 60, 150, 238, 221, 115, 162, 102, 62, 81, 102, 104, 123, 0, 11, 135, 34, 110, 1, 135, 237, 16, 115, 249, 69, 229, 130, 173, 252, 239, 22, 216, 90, 121, 142, 232, 198, 109, 219, 61, 184, 151, 91, 23, 208, 148, 2, 190, 237, 213, 217, 217, 112, 7, 16, 141, 178, 129, 96, 213, 248, 4, 12, 167, 68, 87, 98, 184, 31, 190, 127, 249, 217, 46, 10, 231, 111, 36, 242, 91, 51, 187, 230, 244, 74, 230, 30, 177, 4, 10, 203, 32, 4, 77, 62, 249, 18, 142, 212, 1, 48, 121, 91, 212, 189, 59, 65, 238, 202, 208, 102, 171, 101, 25, 129, 253, 228, 141, 247, 127, 55, 45, 195, 139, 159, 175, 221, 59, 239, 177, 139, 93, 163, 204, 60, 46, 176, 47, 158, 58, 65, 214, 18, 202, 173, 21, 145, 18, 115, 160, 95, 35, 185, 232, 56, 250, 175, 132, 157, 105, 132, 41, 239, 90, 30, 136, 121, 130, 54, 195, 212, 14, 96, 69, 34, 165, 68, 200, 242, 122, 122, 45, 184, 6, 99, 209, 108, 247, 202, 234, 86, 222, 64, 92, 178, 33, 90, 69, 178, 194, 85, 102, 181, 90, 193, 167, 72, 160, 112, 223, 200, 163, 42, 70, 149, 67, 208, 25, 238, 251, 71] self.assertEqual(sig, [ord(i) for i in sig_calc]) b64_sig = "".join([ 'cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7', 'AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4', 'BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K', '0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv', 'hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB', 'p0igcN_IoypGlUPQGe77Rw']) self.assertEqual(b64_sig, base64.base64url_encode(sig_calc)) ########################## # implementation jws_impl = Jws(alg='RS256') msg = Message(payload=_BE(payload)) msg.signatures.append(Signature(_protected=jws_impl)) token = msg.serialize_compact(jwk=jwk) items = token.split('.') self.assertEqual(len(msg.signatures), 1) self.assertEqual(msg.signatures[0]._protected.alg.value, 'RS256') self.assertEqual(len(items), 3) self.assertEqual(msg.signatures[0].protected, items[0]) self.assertEqual(msg.payload, items[1]) self.assertEqual(msg.signatures[0].signature, items[2]) #: restore token msg2 = Message.from_token(token, sender=None, receiver=None) self.assertEqual(len(msg2.signatures), 1) self.assertEqual(msg2.payload, _BE(payload)) self.assertEqual(msg2.payload, msg.payload) self.assertEqual(len(msg2.signatures), 1) self.assertEqual(msg2.signatures[0]._protected.alg.value, 'RS256') self.assertEqual(msg2.signatures[0].protected, items[0]) self.assertEqual(msg2.payload, items[1]) self.assertEqual(msg2.signatures[0].signature, items[2]) #: verify message s = msg2.signatures[0] self.assertTrue(s.verify(msg2.payload, jwk=jwk)) #: wrong key fails new_jwk = Jwk.generate(KeyTypeEnum.RSA) self.assertFalse(s.verify(msg2.payload, jwk=new_jwk)) #: Json Serialization json_str = msg.serialize_json(jwk, indent=2) msg3 = Message.from_token(json_str) self.assertEqual(len(msg3.signatures), 1) self.assertTrue( msg3.signatures[0].verify(msg3.payload, jwk.public_jwk)) self.assertFalse( msg3.signatures[0].verify(msg3.payload, new_jwk.public_jwk))
def to_b64u(self, *args, **kwargs): return base64.base64url_encode( self.to_json(*args, **kwargs))
def test_ecdh_check(self): ''' https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-23#appendix-C ''' v_stc_material = { "kty": "EC", "crv": "P-256", "x": "gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0", "y": "SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps", "d": "0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo" } u_epk_material = { "kty": "EC", "crv": "P-256", "x": "weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ", "y": "e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck", "d": "VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw" } import re def _to_pub(km): return ( int(re.search(r"P-(\d+)$", km['crv']).group(1)), (base64.long_from_b64(km['x']), base64.long_from_b64(km['y'])), ) def _to_pri(km): return ( int(re.search(r"P-(\d+)$", km['crv']).group(1)), base64.long_from_b64(km['d']), ) pub_tuple = _to_pub(v_stc_material) pri_tuple = _to_pri(v_stc_material) import pydoc curve = pydoc.locate('ecdsa.curves.NIST{0}p'.format(pub_tuple[0])) from ecdsa import ( SigningKey, VerifyingKey, ellipticcurve as ec) x, y = pub_tuple[1] v_pub = VerifyingKey.from_public_point( ec.Point(curve.curve, x, y, curve.order), curve, ) v_stc = SigningKey.from_secret_exponent(pri_tuple[1], curve) # Party U provides a ephemeral key pub_tuple = _to_pub(u_epk_material) pri_tuple = _to_pri(u_epk_material) x, y = pub_tuple[1] u_epk = SigningKey.from_secret_exponent(pri_tuple[1], curve) from jose.jwa.ec import ecdsa_dhZ # Party U compute shared_secret_u = ecdsa_dhZ(v_pub, u_epk) print("Aggreement:", base64.long_to_b64(shared_secret_u)) from Crypto.Util.number import long_to_bytes from math import ceil block_size = int(ceil(pub_tuple[0] / 8.0)) # bit number(512 ) / 8 -> octets Zu = long_to_bytes(shared_secret_u, block_size) Z_jwa = [158, 86, 217, 29, 129, 113, 53, 211, 114, 131, 66, 131, 191, 132, 38, 156, 251, 49, 110, 163, 218, 128, 106, 72, 246, 218, 167, 121, 140, 254, 144, 196] self.assertEqual(_ilist(Zu), Z_jwa) # Other Information used in Concat KDF # AlgorithmID || PartyUInfo || PartyVInfo || SuppPubInfo from struct import pack def _otherInfo(alg, pu, pv, klen): return b('').join([ pack("!I", len(alg)), alg, pack("!I", len(pu)), pu, pack("!I", len(pv)), pv, pack("!I", klen), ]) oi_u = _otherInfo( b("A128GCM"), b("Alice"), b("Bob"), 16 * 8, # A128GCM ) oi_jwa = [ 0, 0, 0, 7, 65, 49, 50, 56, 71, 67, 77, 0, 0, 0, 5, 65, 108, 105, 99, 101, 0, 0, 0, 3, 66, 111, 98, 0, 0, 0, 128] print(">>>>>>>", type(oi_u)) print("<<<<<<<", oi_u) self.assertEqual(_ilist(oi_u), oi_jwa) # Coccat KDF : NIST defines SHA256 from Crypto.Hash import SHA256 def _ConcatKDF(Z, dkLen, otherInfo, digest_method=SHA256): def _src(counter_bytes): return b("").join([counter_bytes, Z, otherInfo]) from math import ceil from struct import pack dkm = b'' # Derived Key Material counter = 0 klen = int(ceil(dkLen / 8.0)) while len(dkm) < klen: counter += 1 counter_b = pack("!I", counter) dkm += digest_method.new(_src(counter_b)).digest() return dkm[:klen] _derived_key_u = _ConcatKDF(Zu, 16 * 8, oi_u) # Party V recive Epemeral Public Key v_epk = u_epk.get_verifying_key() Zv = long_to_bytes(ecdsa_dhZ(v_epk, v_stc), block_size) _derived_key_v = _ConcatKDF(Zv, 16 * 8, oi_u) self.assertEqual(_derived_key_u, _derived_key_v) kd_jwa = [ 86, 170, 141, 234, 248, 35, 109, 32, 92, 34, 40, 205, 113, 167, 16, 26] self.assertEqual(_ilist(_derived_key_u), kd_jwa) self.assertEqual(b("VqqN6vgjbSBcIijNcacQGg"), base64.base64url_encode(_derived_key_u))
def test_jws_appendix_a4(self): header_str = '{"alg":"ES512"}' header_oct = [ 123, 34, 97, 108, 103, 34, 58, 34, 69, 83, 53, 49, 50, 34, 125] self.assertEqual( [isinstance(i, int) and i or ord(i[:1]) for i in b(header_str)], header_oct) header_b64 = 'eyJhbGciOiJFUzUxMiJ9' self.assertEqual( base64.base64url_encode(header_str), b(header_b64)) payload_str = "Payload" payload_oct = [ 80, 97, 121, 108, 111, 97, 100, ] self.assertEqual( [isinstance(i, int) and i or ord(i[:1]) for i in b(payload_str)], payload_oct) payload_b64 = "UGF5bG9hZA" self.assertEqual( base64.base64url_encode(payload_str), b(payload_b64)) signing_input_b64 = ".".join([header_b64, payload_b64]) signing_input_oct = [ 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 70, 85, 122, 85, 120, 77, 105, 74, 57, 46, 85, 71, 70, 53, 98, 71, 57, 104, 90, 65] self.assertEqual(_ilist(signing_input_b64), signing_input_oct) jwk_str = ''' {"kty":"EC", "crv":"P-521", "x":"AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk", "y":"ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDly79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2", "d":"AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPAxerEzgdRhajnu0ferB0d53vM9mE15j2C" }''' from jose.jwk import Jwk jwk = Jwk.from_json(jwk_str) import hashlib # Sign pri = jwk.key.private_key_tuple self.assertEqual(pri[0], 521) self.assertEqual( pri[1], base64.long_from_b64( 'AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPAxerEzgdRhajnu0ferB0d53vM9mE15j2C') # NOQA ) digest = int(hashlib.new('sha512', b(signing_input_b64)).hexdigest(), 16) signature = jwk.key.sign_longdigest(digest) self.assertEqual(type(signature), tuple) #: This signature changes everytime. self.assertTrue(isinstance(signature, tuple)) self.assertEqual(len(signature), 2) # Verify pub = jwk.key.public_key_tuple self.assertEqual(pub[0], 521) self.assertEqual(pub[1], base64.long_from_b64( "AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk" # NOQA ) ) self.assertEqual(pub[2], base64.long_from_b64( "ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDly79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2" # NOQA ) ) self.assertTrue(jwk.key.verify_longdigest(digest, signature)) sig_jws_oct = ( [1, 220, 12, 129, 231, 171, 194, 209, 232, 135, 233, 117, 247, 105, 122, 210, 26, 125, 192, 1, 217, 21, 82, 91, 45, 240, 255, 83, 19, 34, 239, 71, 48, 157, 147, 152, 105, 18, 53, 108, 163, 214, 68, 231, 62, 153, 150, 106, 194, 164, 246, 72, 143, 138, 24, 50, 129, 223, 133, 206, 209, 172, 63, 237, 119, 109], [0, 111, 6, 105, 44, 5, 41, 208, 128, 61, 152, 40, 92, 61, 152, 4, 150, 66, 60, 69, 247, 196, 170, 81, 193, 199, 78, 59, 194, 169, 16, 124, 9, 143, 42, 142, 131, 48, 206, 238, 34, 175, 83, 203, 220, 159, 3, 107, 155, 22, 27, 73, 111, 68, 68, 21, 238, 144, 229, 232, 148, 188, 222, 59, 242, 103] ) sig_jws_b64 = ''.join([ 'AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZq', 'wqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8Kp', 'EHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn', ]) sig_jws_str = base64.base64url_decode(sig_jws_b64) self.assertEqual(len(sig_jws_str), 66 * 2) from Crypto.Util.number import bytes_to_long sig_jws_tuple = (bytes_to_long(sig_jws_str[:66]), bytes_to_long(sig_jws_str[66:]),) self.assertTrue(jwk.key.verify_longdigest(digest, sig_jws_tuple))
def test_ecdh_impl(self): ''' https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-23#appendix-C python -m test_ec -q TestEcEcc.test_ecdh_impl ''' v_stc_material = { "kty": "EC", "crv": "P-256", "x": "gI0GAILBdu7T53akrFmMyGcsF3n5dO7MmwNBHKW5SV0", "y": "SLW_xSffzlPWrHEVI30DHM_4egVwt3NQqeUD7nMFpps", "d": "0_NxaRPUMQoAJt50Gz8YiTr8gRTwyEaCumd-MToTmIo" } u_epk_material = { "kty": "EC", "crv": "P-256", "x": "weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ", "y": "e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck", "d": "VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw" } from jose.jwk import Jwk v_stc_jwk = Jwk(**v_stc_material) u_epk_jwk = Jwk(**u_epk_material) #: Agreement Zu = u_epk_jwk.key.agreement_to(v_stc_jwk.key) Z_jwa = [158, 86, 217, 29, 129, 113, 53, 211, 114, 131, 66, 131, 191, 132, 38, 156, 251, 49, 110, 163, 218, 128, 106, 72, 246, 218, 167, 121, 140, 254, 144, 196] self.assertEqual(_ilist(Zu), Z_jwa) self.assertEqual(base64.base64url_encode(Zu), b('nlbZHYFxNdNyg0KDv4QmnPsxbqPagGpI9tqneYz-kMQ')) from jose.jwe import Jwe from jose.jwa.ec import ECDH_ES jwe = Jwe(enc='A128GCM', apu='Alice', apv='Bob') algid = jwe.enc.value klen = ECDH_ES.digest_key_bitlength(jwe.enc) oi_u = ECDH_ES.other_info(b(algid), b('Alice'), b('Bob'), klen) oi_jwa = [ 0, 0, 0, 7, 65, 49, 50, 56, 71, 67, 77, 0, 0, 0, 5, 65, 108, 105, 99, 101, 0, 0, 0, 3, 66, 111, 98, 0, 0, 0, 128] self.assertEqual(_ilist(oi_u), oi_jwa) # Derive Key for ECDH Agreement _derived_key_u, cek_ci_u = ECDH_ES.create_key(Zu, klen, oi_u, None) self.assertIsNone(cek_ci_u) # --- Party V # Agreement Zv = v_stc_jwk.key.agreement_to(u_epk_jwk.key) _derived_key_v, cek_ci_v = ECDH_ES.create_key(Zv, klen, oi_u, None) self.assertIsNone(cek_ci_v) self.assertEqual(_derived_key_u, _derived_key_v) kd_jwa = [ 86, 170, 141, 234, 248, 35, 109, 32, 92, 34, 40, 205, 113, 167, 16, 26] self.assertEqual(len(_derived_key_v), len(kd_jwa)) self.assertEqual(_ilist(_derived_key_u), kd_jwa) self.assertEqual(b("VqqN6vgjbSBcIijNcacQGg"), base64.base64url_encode(_derived_key_u))
ret = cls._cipher.new(jwk.key.private_key).decrypt(cek_ci, _sentinel) if ret == _sentinel: return None return ret class RSA_OAEP(RsaKeyEncryptor): _cipher = PKCS1_OAEP @classmethod def decrypt(cls, jwk, cek_ci, *args, **kwargs): return cls._cipher.new(jwk.key.private_key).decrypt(cek_ci) if __name__ == '__main__': from jose.jwe import Jwe from jose.jwa.keys import KeyTypeEnum jwk = Jwk.generate(kty=KeyTypeEnum.RSA) jwe = Jwe.from_json('{"alg": "RSA1_5", "enc": "A128CBC-HS256"}') cek, iv, cek_ci, kek = jwe.provide_key(jwk) print("CEK", base64.base64url_encode(cek)) print("IV", base64.base64url_encode(iv)) print("CEK_CI", base64.base64url_encode(cek_ci)) cek2 = jwe.agree_key(jwk, cek_ci) print("CEK2", base64.base64url_encode(cek_ci)) print("IV", base64.base64url_encode(iv)) assert(cek == cek2)
for e in encs: enc = EncEnum.create(e).encryptor cek, iv = enc.create_key_iv() assert len(cek) == enc._KEY_LEN assert len(iv) == enc._IV_LEN print(enc.__name__) print("CEK =", base64.urlsafe_b64encode(cek)) print("IV=", base64.urlsafe_b64encode(iv)) import itertools from jose.jwk import Jwk from jose.jwe import Jwe jwk = Jwk.generate(kty="oct") for a, e in list(itertools.product(algs, encs)): jwe = Jwe( alg=KeyEncEnum.create(a), enc=EncEnum.create(e), ) cek, iv, cek_ci, kek = jwe.provide_key(jwk) print("alg=", a, "enc=", e) print("CEK=", base64.base64url_encode(cek)) print("IV=", base64.base64url_encode(iv)) print("CEK_CI=", base64.base64url_encode(cek_ci)) print("Jwe.iv=", jwe.iv) print("Jwe.tag=", jwe.tag) cek2 = jwe.agree_key(jwk, cek_ci) print("CEK AGREED=", base64.base64url_encode(cek2))
assert len(cek) == enc._KEY_LEN assert len(iv) == enc._IV_LEN print enc.__name__ print "CEK =", base64.urlsafe_b64encode(cek) print "IV=", base64.urlsafe_b64encode(iv) import itertools from jose.jwk import Jwk from jose.jwe import Jwe jwk = Jwk.generate(kty="oct") for a, e in list(itertools.product(algs, encs)): jwe = Jwe( alg=KeyEncEnum.create(a), enc=EncEnum.create(e), ) cek, iv, cek_ci, kek = jwe.provide_key(jwk) print "TESTING ---- :alg=", a, "enc=", e print "CEK=", base64.base64url_encode(cek) print "IV=", base64.base64url_encode(iv) print "CEK_CI=", base64.base64url_encode(cek_ci) print "Jwe.p2s=", jwe.p2s print "Jwe.p2c=", jwe.p2c print "KEY=", jwk.k print "KEK=", base64.base64url_encode(kek) cek2 = jwe.agree_key(jwk, cek_ci) print "CEK AGREED=", base64.base64url_encode(cek2) assert cek == cek2
def test_jwe_appendix_a1(self): # A.1 plaint_oct = [ 84, 104, 101, 32, 116, 114, 117, 101, 32, 115, 105, 103, 110, 32, 111, 102, 32, 105, 110, 116, 101, 108, 108, 105, 103, 101, 110, 99, 101, 32, 105, 115, 32, 110, 111, 116, 32, 107, 110, 111, 119, 108, 101, 100, 103, 101, 32, 98, 117, 116, 32, 105, 109, 97, 103, 105, 110, 97, 116, 105, 111, 110, 46] plaint = ''.join(chr(i) for i in plaint_oct) self.assertEqual( plaint, 'The true sign of intelligence is not knowledge but imagination.') # A.1.1 jwe_json = '{"alg":"RSA-OAEP","enc":"A256GCM"}' jwe_b64 = 'eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ' self.assertEqual(jwe_b64, base64.base64url_encode(jwe_json)) jwe = Jwe.from_json(jwe_json) self.assertEqual(jwe.alg, KeyEncEnum.RSA_OAEP) self.assertEqual(jwe.enc, EncEnum.GCMA256) # A.1.2. cek_oct = [ 177, 161, 244, 128, 84, 143, 225, 115, 63, 180, 3, 255, 107, 154, 212, 246, 138, 7, 110, 91, 112, 46, 34, 105, 47, 130, 203, 46, 122, 234, 64, 252] cek = ''.join(chr(i) for i in cek_oct) jwk_dict = { 'kty': "RSA", "n": ''.join([ 'oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW', 'cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S', 'psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a', 'sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS', 'tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj', 'YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw', ]), "e": "AQAB", "d": ''.join([ 'kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N', 'WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9', '3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk', 'qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl', 't3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd', 'VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ', ]) } jwk = Jwk(**jwk_dict) self.assertEqual(jwk.kty, KeyTypeEnum.RSA) self.assertTrue(jwk.key.is_private) cek_enc_oct = [ 56, 163, 154, 192, 58, 53, 222, 4, 105, 218, 136, 218, 29, 94, 203, 22, 150, 92, 129, 94, 211, 232, 53, 89, 41, 60, 138, 56, 196, 216, 82, 98, 168, 76, 37, 73, 70, 7, 36, 8, 191, 100, 136, 196, 244, 220, 145, 158, 138, 155, 4, 117, 141, 230, 199, 247, 173, 45, 182, 214, 74, 177, 107, 211, 153, 11, 205, 196, 171, 226, 162, 128, 171, 182, 13, 237, 239, 99, 193, 4, 91, 219, 121, 223, 107, 167, 61, 119, 228, 173, 156, 137, 134, 200, 80, 219, 74, 253, 56, 185, 91, 177, 34, 158, 89, 154, 205, 96, 55, 18, 138, 43, 96, 218, 215, 128, 124, 75, 138, 243, 85, 25, 109, 117, 140, 26, 155, 249, 67, 167, 149, 231, 100, 6, 41, 65, 214, 251, 232, 87, 72, 40, 182, 149, 154, 168, 31, 193, 126, 215, 89, 28, 111, 219, 125, 182, 139, 235, 195, 197, 23, 234, 55, 58, 63, 180, 68, 202, 206, 149, 75, 205, 248, 176, 67, 39, 178, 60, 98, 193, 32, 238, 122, 96, 158, 222, 57, 183, 111, 210, 55, 188, 215, 206, 180, 166, 150, 166, 106, 250, 55, 229, 72, 40, 69, 214, 216, 104, 23, 40, 135, 212, 28, 127, 41, 80, 175, 174, 168, 115, 171, 197, 89, 116, 92, 103, 246, 83, 216, 182, 176, 84, 37, 147, 35, 45, 219, 172, 99, 226, 233, 73, 37, 124, 42, 72, 49, 242, 35, 127, 184, 134, 117, 114, 135, 206] cek_enc_b64 = ''.join([ 'OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe', 'ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb', 'Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV', 'mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8', '1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi', '6UklfCpIMfIjf7iGdXKHzg', ]) cek_enc_bytes = ''.join(chr(i) for i in cek_enc_oct) self.assertEqual(cek_enc_bytes, base64.base64url_decode(cek_enc_b64)) self.assertEqual(len(cek) * 8, 256) key_enc = jwe.alg.encryptor from jose.jwa.rsa import RSA_OAEP self.assertEqual(key_enc, RSA_OAEP) # decrypt and encrypt CEK dec_cek = key_enc.decrypt(jwk, cek_enc_bytes) self.assertEqual(dec_cek, cek) # Appendix OK # --- encryption outcome MAY changes, # but decrypted plaint is same as the original enc_cek = key_enc.encrypt(jwk, cek) dec_cek_2 = key_enc.decrypt(jwk, enc_cek) self.assertEqual(dec_cek, dec_cek_2) # Appendix A.1.4 iv_oct = [227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219] iv = ''.join(chr(i) for i in iv_oct) iv_b64url = '48V1_ALb6US04U3b' self.assertEqual(iv_b64url, base64.base64url_encode(iv)) # Appendix A.1.5 aad_oct = [ 101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 48, 69, 116, 84, 48, 70, 70, 85, 67, 73, 115, 73, 109, 86, 117, 89, 121, 73, 54, 73, 107, 69, 121, 78, 84, 90, 72, 81, 48, 48, 105, 102, 81] aad = ''.join(chr(i) for i in aad_oct) # Appendix A.1.6 cenc = jwe.enc.encryptor from jose.jwa.gcm import GCMA256 self.assertEqual(cenc, GCMA256) ciphert_oct = [ 229, 236, 166, 241, 53, 191, 115, 196, 174, 43, 73, 109, 39, 122, 233, 96, 140, 206, 120, 52, 51, 237, 48, 11, 190, 219, 186, 80, 111, 104, 50, 142, 47, 167, 59, 61, 181, 127, 196, 21, 40, 82, 242, 32, 123, 143, 168, 226, 73, 216, 176, 144, 138, 247, 106, 60, 16, 205, 160, 109, 64, 63, 192] ciphert = "".join(chr(i) for i in ciphert_oct) tag_oct = [ 92, 80, 104, 49, 133, 25, 161, 215, 173, 101, 219, 211, 136, 91, 210, 145] tag = "".join(chr(i) for i in tag_oct) # Content Decrytion pt, is_valid = cenc.decrypt(cek, ciphert, iv, aad, tag) self.assertEqual(pt, plaint) # consistent with the spec self.assertTrue(is_valid) #: encryt and decryt ct, tag2 = cenc.encrypt(cek, plaint, iv, aad) pt2, is_valid2 = cenc.decrypt(cek, ct, iv, aad, tag2) self.assertEqual(pt2, plaint) # consistent with the spec self.assertTrue(is_valid2)
def test_jws_appendix_a1(self): ''' nose2 jose.tests.test_jws.TestJws.test_jws_appendix_a1''' '''{"typ":"JWT", "alg":"HS256"} {"iss":"joe", "exp":1300819380, "http://example.com/is_root":true} ''' jws_oct = [ 123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125] jws_b64 = 'eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9' self.assertEqual( ''.join(chr(i) for i in jws_oct), base64.base64url_decode(jws_b64)) payload_oct = [ 123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125] payload_b64 = ''.join([ 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA', '4MTkzODAsDQogImh0dHA6Ly9leGFt', 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ']) self.assertEqual( ''.join(chr(i) for i in payload_oct), base64.base64url_decode(payload_b64)) sinput_oct = [ 101, 121, 74, 48, 101, 88, 65, 105, 79, 105, 74, 75, 86, 49, 81, 105, 76, 65, 48, 75, 73, 67, 74, 104, 98, 71, 99, 105, 79, 105, 74, 73, 85, 122, 73, 49, 78, 105, 74, 57, 46, 101, 121, 74, 112, 99, 51, 77, 105, 79, 105, 74, 113, 98, 50, 85, 105, 76, 65, 48, 75, 73, 67, 74, 108, 101, 72, 65, 105, 79, 106, 69, 122, 77, 68, 65, 52, 77, 84, 107, 122, 79, 68, 65, 115, 68, 81, 111, 103, 73, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, 108, 101, 71, 70, 116, 99, 71, 120, 108, 76, 109, 78, 118, 98, 83, 57, 112, 99, 49, 57, 121, 98, 50, 57, 48, 73, 106, 112, 48, 99, 110, 86, 108, 102, 81] sinput = '.'.join([jws_b64, payload_b64]) self.assertEqual( ''.join(chr(i) for i in sinput_oct), sinput) jwk_dict = { "kty": "oct", "k": "".join([ "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75", "aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"]) } jwk = Jwk(**jwk_dict) sig_b64 = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" jws = Jws.from_b64u(jws_b64) sig = jws.alg.signer.sign(jwk, sinput) self.assertEqual(sig_b64, base64.base64url_encode(sig)) self.assertTrue( jws.alg.signer.verify(jwk, sinput, sig))
def thumbprint(self): return base64.base64url_encode( hashlib.sha256(self.to_thumbprint_json()).digest())
import unittest from jose.jwk import Jwk, JwkSet from jose.jwe import Jwe, ZipEnum, Message, Recipient from jose.jwa.encs import KeyEncEnum, EncEnum from jose.jwa.keys import KeyTypeEnum from jose.utils import base64 import traceback from jose.tests import ( JWE_A2, JWE_A3, JWE_B, ) from jose.crypto import KeyOwner _S = lambda o: ''.join([chr(i) for i in o]) _BE = lambda s: base64.base64url_encode(s) _BD = lambda s: base64.base64url_decode(s) class TestEntity(KeyOwner): def __init__(self, identifier, jku, jwkset=None): self.identifier = identifier self.jku = jku self.jwkset = JwkSet( keys=[ Jwk.generate(KeyTypeEnum.RSA), Jwk.generate(KeyTypeEnum.EC), Jwk.generate(KeyTypeEnum.OCT), ] )