def provide(cls, enc, jwk, jwe, *args, **kwargs): kek = jwk.key.shared_key[:cls._enc._KEY_LEN] dmy, kek_iv = cls._enc.create_key_iv() #: iv cek, iv = enc.encryptor.create_key_iv() cek_ci, tag = cls._enc.encrypt(kek, cek, kek_iv, "") jwe.iv = _BE(kek_iv) jwe.tag = _BE(tag) return (cek, iv, cek_ci, kek)
def serialize_json(self, **kwargs): assert self.iv assert self.cek #: Content encryption (self.ciphertext, self.tag) = self.encrypt() self.ciphertext = _BE(self.ciphertext) self.tag = _BE(self.tag) return self.to_json(**kwargs)
def serialize_compact(self, index=0): if len(self.recipients) < 1: return None header = self.header(index) # all header togher header_b64u = header.to_b64u() # auth_data = _BE(header) #: encrypt with same CEK+IV, but with new auth_data ciphertext, tag = self.encrypt(header, header_b64u) #: Tokenize return ".".join([ header_b64u, self.recipients[0].encrypted_key or '', self.iv, _BE(ciphertext), _BE(tag)])
def test_compact(self): ''' nose2 jose.tests.test_jws.TestJwsMessage.test_compact''' jku="https://me.com/jwkset" signer = TestEntity( identifier="https://me.com", jku=jku, ) for alg in SigDict.values(): alg = SigEnum.create(alg) plaintext = "This is a message to be signed by %s" % alg.value msg = Message( payload=_BE(plaintext), sender=signer) msg.add_signature( sender=signer, protected=Jws(alg=alg, kid=None, jku=jku), header=Jws(typ="text"), ) token = msg.serialize_compact() msg2 = Message.from_token(token, sender=signer) print "TOKEN=", token self.assertTrue(msg2.verify())
def provide(cls, enc, jwk, jwe, cek=None, iv=None, *args, **kwargs): if cek: #: TODO: Check iv is valid or not pass else: cek, iv = enc.encryptor.create_key_iv() jwe.p2s = jwe.p2s or _BE( Random.get_random_bytes(cls._wrapper._KEY_LEN)) jwe.p2c = jwe.p2c or 1024 kek = cls.derive(jwk, jwe.p2s, jwe.p2c, *args, **kwargs) cek_ci = cls.encrypt(kek, cek) return cek, iv, cek_ci, kek
def test_algs(self): ''' nose2 jose.tests.test_jws.TestJwsMessage.test_algs''' for alg in SigDict.values(): alg = SigEnum.create(alg) signer = "https://%s.com" % alg.name jku = signer + "/jwkset" jwk = Jwk.generate(alg.key_type) plaintext = "This is a message to be signed by %s" % alg.value signature = alg.signer.sign(jwk, plaintext) self.assertTrue(alg.signer.verify(jwk, plaintext, signature)) print alg.value, jwk.kty.value, len(signature), _BE(signature)
def provide_key(self, jwk, cek=None, iv=None, jwe=None): jwe = Jwe.merge(self.header, jwe) assert jwk and isinstance(jwk, Jwk), \ "Recipient's Jwk must be specified." assert jwe assert jwe.enc assert jwe.alg if jwk.kid and not self.header.kid: self.header.kid = jwk.kid (self.cek, self.iv, self.encrypted_key, kek ) = jwe.alg.encryptor.provide(jwe.enc, jwk, self.header, cek, iv) self.encrypted_key = _BE(self.encrypted_key) return self.cek, self.iv
def add_recipient(self, recipient): ''' before call, recipient has to be provided with messsage's CEK and IV ''' header = self.header(jwe=recipient.header) key = header.load_key(recipient.recipient) assert key is not None, "Recipient's key MUST be loaded." if len(self.recipients) < 1: #: Provide CEK & IV (self.cek, self.iv) = recipient.provide_key( key, jwe=header) self.iv = _BE(self.iv) else: # use existent cek and iv assert self.cek assert self.iv recipient.provide_key(key, self.cek, self.iv, jwe=header) self.recipients.append(recipient)
def run(self, args): super(MessageCommand, self).run(args) args.jku = args.jku or args.sender + "/jwkset" self.provide_keys(args.sender, args.jku) message = jws.Message( sender=args.sender, payload=_BE(args.payload)) for alg in sigs.SigDict.values(): protected = jws.Jws(alg=sigs.SigEnum.create(alg)) header = jws.Jws(jku=args.jku) message.add_signature(protected, header) jmsg = message.to_json(indent=2) print jmsg msg2 = jws.Message.from_json(jmsg) msg2 = jws.Message.from_token(jmsg, sender=args.sender) print msg2.verify()
def run(self, args): super(MultiCommand, self).run(args) message = jwe.Message( protected=jwe.Jwe(enc=args.enc, zip="DEF",), unprotected=jwe.Jwe(typ="text"), plaintext=_BE(args.payload) ) for alg in encs.KeyEncDict.values(): alg = encs.KeyEncEnum.create(alg) if alg.single: continue receiver = 'https://%s.com/' % alg.name.lower() jku = receiver + '/jwkset' jwk.Jwk.get_or_create_from( receiver, jku, alg.key_type, kid=None,) recipient = jwe.Recipient( header=jwe.Jwe(alg=alg, jku=jku,) ) message.add_recipient(recipient, receiver) print message.serialize_json(indent=2)
def run(self, args): super(SampleCommand, self).run(args) #Jws self.result.jws = jws.Jws(alg=sigs.SigEnum.create(args.alg)) print self.result.to_json(indent=2) # any parms for param in args.params: self.result.jws.set_value(*param.split('=')) # Initia Value if self.result.jws.alg.key_type == keys.KeyTypeEnum.RSA: self.result.inits = dict(length=args.bits) elif self.result.jws.alg.key_type == keys.KeyTypeEnum.EC: self.result.inits = dict( length=keys.CurveEnum.create(args.curve).bits) elif self.result.jws.alg.key_type == keys.KeyTypeEnum.OCT: self.result.inits = dict(length=args.length) #key if args.jwk: self.result.jwk = jwk.Jwk.from_file(args.jwk) else: self.result.jwk = jwk.Jwk.generate( kty=self.result.jws.alg.key_type, **self.result.inits) assert self.result.jwk.kty == self.result.jws.alg.key_type self.result.signature = _BE( self.result.jws.sign(self.result.plaintext, self.result.jwk)) self.result.verified = self.result.jws.verify( self.result.plaintext, _BD(self.result.signature), self.result.jwk) print self.result.to_json(indent=2)
def private_jwk(self): jwk = Jwk( kty="oct", k=_BE(self.material), ) return jwk
def to_jwk(self, jwk): jwk.k = _BE(self.material)
def state_from_nonce(cls, nonce): return _BE(hashlib.sha256(nonce + settings.SECRET_KEY).digest())
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))