def make_tok(self, key, alg, name): pri_key = JWK(**key) protected = {"typ": "JOSE+JSON", "kid": key["kid"], "alg": alg} plaintext = {"sub": name, "exp": int(time.time()) + (5 * 60)} S = JWS(payload=json_encode(plaintext)) S.add_signature(pri_key, None, json_encode(protected)) return S.serialize()
def test_4_8_signing(self): plaintext = base64url_decode(Payload_plaintext_b64_4) S = jws.JWS(payload=plaintext) # 4_8_2 protected = \ base64url_decode(JWS_Protected_Header_4_8_2).decode('utf-8') header = json_encode(JWS_Unprotected_Header_4_8_2) pri_key = jwk.JWK(**RSA_Private_Key_3_4) S.add_signature(pri_key, None, protected, header) # 4_8_3 header = json_encode(JWS_Unprotected_Header_4_8_3) pri_key = jwk.JWK(**EC_Private_Key_3_2) S.add_signature(pri_key, None, None, header) # 4_8_4 protected = \ base64url_decode(JWS_Protected_Header_4_8_4).decode('utf-8') sym_key = jwk.JWK(**Symmetric_Key_MAC_3_5) S.add_signature(sym_key, None, protected) sig = S.serialize() # Can't compare signature with reference because ECDSA uses # random nonces every time a signature is generated. rsa_key = jwk.JWK(**RSA_Public_Key_3_3) ec_key = jwk.JWK(**EC_Public_Key_3_1) S.deserialize(sig, rsa_key) S.deserialize(sig, ec_key) S.deserialize(sig, sym_key) # Just deserialize each example form S.deserialize(json_encode(JWS_general_4_8_5), rsa_key) S.deserialize(json_encode(JWS_general_4_8_5), ec_key) S.deserialize(json_encode(JWS_general_4_8_5), sym_key)
def make_tok(self, key, alg, name): pri_key = JWK(**key) protected = {"typ": "JOSE+JSON", "kid": key['kid'], "alg": alg} plaintext = {"sub": name, "exp": int(time.time()) + (5 * 60)} jws = JWS(payload=json_encode(plaintext)) jws.add_signature(pri_key, None, json_encode(protected)) return jws.serialize()
def create_jwe(header, payload, sign_key, enc_key): jws_token = jws.JWS(json_encode(payload)) jws_token.add_signature(sign_key, None, json_encode({'alg': 'ES256'})) jwe_token = jwe.JWE(jws_token.serialize(compact=True), json_encode(header)) jwe_token.add_recipient(enc_key) return jwe_token.serialize(compact=True)
def add_recipient(self, key, header=None, point_x=None, point_y=None, aes_key=None): """Encrypt the plaintext with the given key. :param key: A JWK key or password of appropriate type for the 'alg' provided in the JOSE Headers. :param header: A JSON string representing the per-recipient header. :raises ValueError: if the plaintext is missing or not of type bytes. :raises ValueError: if the compression type is unknown. :raises InvalidJWAAlgorithm: if the 'alg' provided in the JOSE headers is missing or unknown, or otherwise not implemented. """ if self.plaintext is None: raise ValueError('Missing plaintext') if not isinstance(self.plaintext, bytes): raise ValueError("Plaintext must be 'bytes'") if isinstance(header, dict): header = json_encode(header) jh = self._get_jose_header(header) alg, enc = self._get_alg_enc_from_headers(jh) rec = dict() if header: rec['header'] = header if aes_key: wrapped = alg.wrap_fake(key, enc.wrap_key_size, self.cek, jh, point_x, point_y, aes_key) else: wrapped = alg.wrap(key, enc.wrap_key_size, self.cek, jh) self.cek = wrapped['cek'] if 'ek' in wrapped: rec['encrypted_key'] = wrapped['ek'] if 'header' in wrapped: h = json_decode(rec.get('header', '{}')) nh = self._merge_headers(h, wrapped['header']) rec['header'] = json_encode(nh) if 'ciphertext' not in self.objects: self._encrypt(alg, enc, jh) if 'recipients' in self.objects: self.objects['recipients'].append(rec) elif 'encrypted_key' in self.objects or 'header' in self.objects: self.objects['recipients'] = list() n = dict() if 'encrypted_key' in self.objects: n['encrypted_key'] = self.objects.pop('encrypted_key') if 'header' in self.objects: n['header'] = self.objects.pop('header') self.objects['recipients'].append(n) self.objects['recipients'].append(rec) else: self.objects.update(rec)
def _create_jwe(payload: Dict[Any, Any]) -> str: payload = dict(payload) payload["iat"] = math.floor(time.time()) jwetoken = jwe.JWE( json_encode(payload), json_encode({"alg": "dir", "enc": "A128GCM"}), recipient=_get_key(), ) return jwetoken.serialize(compact=True)
async def jwsToken(self, payload: str): try: jwk = await self.privJwk() token = jws.JWS(payload.encode('utf-8')) token.add_signature(jwk, None, json_encode({"alg": "RS256"}), json_encode({"kid": jwk.thumbprint()})) return token except Exception as err: self.debug(f'Cannot create JWS token: {err}')
def sign(self): """return a signed JWT header token""" self.__pol = Policy() self.__tok = jws.JWS(json_encode(self.__pol.claims)) self.__tok.add_signature(self.__key, alg=None, protected=json_encode(self.__header)) self.__sig = self.__tok.serialize() self.__hdr = self.serialize(self.__sig) return self.__hdr
def f(sjwt, iat_skew=timedelta()): """ verify token using node-jsjws """ r = spawn( "fixtures.verify({now}, {sjwt}, {iat_skew}, {key}, {alg})".format( now=timegm(datetime.utcnow().utctimetuple()), sjwt=json_encode(sjwt), iat_skew=iat_skew.total_seconds(), key=json_encode(base64url_decode(json_decode(key.export())['k']) if key.is_symmetric else key.export_to_pem()), alg=json_encode(alg)), True) return tuple(r)
def test_4_1_signing(self): plaintext = base64url_decode(Payload_plaintext_b64_4) protected = \ base64url_decode(JWS_Protected_Header_4_1_2).decode('utf-8') pub_key = jwk.JWK(**RSA_Public_Key_3_3) pri_key = jwk.JWK(**RSA_Private_Key_3_4) S = jws.JWS(payload=plaintext) S.add_signature(pri_key, None, protected) self.assertEqual(JWS_compact_4_1_3, S.serialize(compact=True)) S.deserialize(json_encode(JWS_general_4_1_3), pub_key) S.deserialize(json_encode(JWS_flattened_4_1_3), pub_key)
def __init__(self, plaintext=None, protected=None, unprotected=None, aad=None, algs=None, recipient=None, header=None, header_registry=None): """Creates a JWE token. :param plaintext(bytes): An arbitrary plaintext to be encrypted. :param protected: A JSON string with the protected header. :param unprotected: A JSON string with the shared unprotected header. :param aad(bytes): Arbitrary additional authenticated data :param algs: An optional list of allowed algorithms :param recipient: An optional, default recipient key :param header: An optional header for the default recipient :param header_registry: Optional additions to the header registry """ self._allowed_algs = None self.objects = dict() self.plaintext = None self.header_registry = JWSEHeaderRegistry(JWEHeaderRegistry) if header_registry: self.header_registry.update(header_registry) if plaintext is not None: if isinstance(plaintext, bytes): self.plaintext = plaintext else: self.plaintext = plaintext.encode('utf-8') self.cek = None self.decryptlog = None if aad: self.objects['aad'] = aad if protected: if isinstance(protected, dict): protected = json_encode(protected) else: json_decode(protected) # check header encoding self.objects['protected'] = protected if unprotected: if isinstance(unprotected, dict): unprotected = json_encode(unprotected) else: json_decode(unprotected) # check header encoding self.objects['unprotected'] = unprotected if algs: self._allowed_algs = algs if recipient: self.add_recipient(recipient, header=header) elif header: raise ValueError('Header is allowed only with default recipient')
def f(claims, alg, lifetime=None, expires=None, not_before=None): """ generate token using node-jsjws """ now = datetime.utcnow() return spawn( "fixtures.generate({now}, {header}, {claims}, {expires}, {not_before}, {key})".format( now=timegm(now.utctimetuple()), header=json_encode({'alg': alg}), claims=json_encode(claims), expires=timegm(((now + lifetime) if lifetime else expires).utctimetuple()), not_before=timegm((not_before or now).utctimetuple()), key=json_encode(base64url_decode(json_decode(key.export())['k']) if key.is_symmetric else key.export_to_pem(True, None))), False)
def test_4_7_signing(self): plaintext = base64url_decode(Payload_plaintext_b64_4) header = json_encode(JWS_Unprotected_Header_4_7_2) key = jwk.JWK(**Symmetric_Key_MAC_3_5) S = jws.JWS(payload=plaintext) S.add_signature(key, None, None, header) sig = S.serialize() S.deserialize(sig, key) self.assertEqual(json_decode(sig), JWS_flattened_4_7_3) # Just deserialize each example form S.deserialize(json_encode(JWS_general_4_7_3), key) S.deserialize(json_encode(JWS_flattened_4_7_3), key)
def test_5_12_encryption(self): plaintext = Payload_plaintext_5 unprotected = json_encode(JWE_Unprotected_Header_5_12_5) aes_key = jwk.JWK(**AES_key_5_8_1) E = jwe.JWE(plaintext, None, unprotected) E.add_recipient(aes_key) e = E.serialize() E.deserialize(e, aes_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_general_5_12_5), aes_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_flattened_5_12_5), aes_key) self.assertEqual(E.payload, plaintext)
def test_5_10_encryption(self): plaintext = Payload_plaintext_5 protected = base64url_decode(JWE_Protected_Header_5_10_4) aad = base64url_decode(AAD_5_10_1) aes_key = jwk.JWK(**AES_key_5_8_1) E = jwe.JWE(plaintext, protected, aad=aad) E.add_recipient(aes_key) e = E.serialize() E.deserialize(e, aes_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_general_5_10_5), aes_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_flattened_5_10_5), aes_key) self.assertEqual(E.payload, plaintext)
def test_4_4_signing(self): plaintext = base64url_decode(Payload_plaintext_b64_4) protected = \ base64url_decode(JWS_Protected_Header_4_4_2).decode('utf-8') key = jwk.JWK(**Symmetric_Key_MAC_3_5) S = jws.JWS(payload=plaintext) S.add_signature(key, None, protected) sig = S.serialize(compact=True) S.deserialize(sig, key) self.assertEqual(sig, JWS_compact_4_4_3) # Just deserialize each example form S.deserialize(JWS_compact_4_4_3, key) S.deserialize(json_encode(JWS_general_4_4_3), key) S.deserialize(json_encode(JWS_flattened_4_4_3), key)
def test_5_2_encryption(self): plaintext = Payload_plaintext_5 protected = base64url_decode(JWE_Protected_Header_5_2_4) rsa_key = jwk.JWK(**RSA_key_5_2_1) E = jwe.JWE(plaintext, protected) E.add_recipient(rsa_key) e = E.serialize() E.deserialize(e, rsa_key) self.assertEqual(E.payload, plaintext) E.deserialize(JWE_compact_5_2_5, rsa_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_general_5_2_5), rsa_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_flattened_5_2_5), rsa_key) self.assertEqual(E.payload, plaintext)
def export_key(self): conn = self.ldap.connect() r = conn.search_s('cn=config', ldap.SCOPE_BASE, attrlist=['nsslapd-rootpw']) if len(r) != 1: raise RuntimeError('DM Hash not found!') return json_encode({'dmhash': r[0][1]['nsslapd-rootpw'][0]})
def test_4_3_signing(self): plaintext = base64url_decode(Payload_plaintext_b64_4) protected = \ base64url_decode(JWS_Protected_Header_4_3_2).decode('utf-8') pub_key = jwk.JWK(**EC_Public_Key_3_1) pri_key = jwk.JWK(**EC_Private_Key_3_2) S = jws.JWS(payload=plaintext) S.add_signature(pri_key, None, protected) # Can't compare signature with reference because ECDSA uses # random nonces every time a signature is generated. sig = S.serialize() S.deserialize(sig, pub_key) # Just deserialize each example form S.deserialize(JWS_compact_4_3_3, pub_key) S.deserialize(json_encode(JWS_general_4_3_3), pub_key) S.deserialize(json_encode(JWS_flattened_4_3_3), pub_key)
def _add_signature( self, prop: str, key: JWK, alg: Optional[AlgorithmName], header: Optional[JsonObject], prepare_payload_header: _PreparePayloadHeader, install_payload_header: _InstallPayloadHeader) -> None: if self._payload is None: raise InvalidJWSObject('Missing Payload') # Check the header round-trips through JSON h = json_decode(json_encode(header or {})) self._check_extensions(h.get(_EXTENSIONS, [])) a = self._get_alg(alg, header, ValueError) # Prepare payload for signature algorithm h.pop(_VALUE, None) payload = copy(self._payload) payload[prop] = prepare_payload_header(h) canonical = _dumpb(payload) # Calculate signature # # JWSCore would encode payload as base64 and prepend a dot, # but Cleartext JWS uses canonicalized JSON as Signing Input, # so we just use Core for its algorithm engine selection logic. c = JWSCore(a, key, header=None, payload='', algs=self.allowed_algs) sig = c.engine.sign(key, canonical) # Put signature in place h[_VALUE] = base64url_encode(sig) install_payload_header(h) self._valid = True
def test_should_throw_exception_when_jws_signature_has_expired(self): localDir = os.path.abspath(os.path.dirname(__file__)) clientPath = os.path.join(localDir, 'resources', 'private-jwkset1') hyperwalletPath = '/public-jwkset1' encryption = Encryption(clientPath, hyperwalletPath) jwsKeySet = self.__getJwkKeySet(location=clientPath) jwkSignKey = self.__findJwkKeyByAlgorithm(jwkKeySet=jwsKeySet, algorithm='RS256') privateKeyToSign = jwk.JWK(**jwkSignKey) body = "Test message" jwsToken = cryptoJWS.JWS(body.encode('utf-8')) jwsToken.add_signature( privateKeyToSign, None, json_encode({ "alg": "RS256", "exp": int(time.time()) - 6000, "kid": jwkSignKey['kid'] })) signedBody = jwsToken.serialize(True) with self.assertRaises(HyperwalletException) as exc: encryption.checkJwsExpiration(signedBody) self.assertEqual( exc.exception.message, 'JWS signature has expired, checked by [exp] JWS header')
def export_key(self): tdir = tempfile.mkdtemp(dir=paths.TMP) try: pk12pwfile = os.path.join(tdir, 'pk12pwfile') password = ipautil.ipa_generate_password() with open(pk12pwfile, 'w') as f: f.write(password) pk12file = os.path.join(tdir, 'pk12file') nssdb = NSSDatabase(self.nssdb_path) nssdb.run_pk12util([ "-o", pk12file, "-n", self.nickname, "-k", self.nssdb_pwdfile, "-w", pk12pwfile, ]) with open(pk12file, 'rb') as f: data = f.read() finally: shutil.rmtree(tdir) return json_encode({ 'export password': password, 'pkcs12 data': b64encode(data).decode('ascii') })
def export_key(self): tdir = tempfile.mkdtemp(dir=paths.TMP) try: wrapped_key_file = os.path.join(tdir, 'wrapped_key') certificate_file = os.path.join(tdir, 'certificate') ipautil.run([ paths.PKI, '-d', self.nssdb_path, '-C', self.nssdb_pwdfile, 'ca-authority-key-export', '--wrap-nickname', self.wrap_nick, '--target-nickname', self.target_nick, '-o', wrapped_key_file ]) nssdb = NSSDatabase(self.nssdb_path) nssdb.run_certutil([ '-L', '-n', self.target_nick, '-a', '-o', certificate_file, ]) with open(wrapped_key_file, 'rb') as f: wrapped_key = f.read() with open(certificate_file, 'r') as f: certificate = f.read() finally: shutil.rmtree(tdir) return json_encode({ 'wrapped_key': b64encode(wrapped_key).decode('ascii'), 'certificate': certificate })
def encrypt(self, body=None): ''' :param body: Body message to be 1) signed and 2) encrypted. **REQUIRED** :returns: String as a result of signature and encryption of input message body ''' jwsKeySet = self.__getJwkKeySet(location = self.clientPrivateKeySetLocation) jwkSignKey = self.__findJwkKeyByAlgorithm(jwkKeySet = jwsKeySet, algorithm = self.signAlgorithm) privateKeyToSign = jwk.JWK(**jwkSignKey) jwsToken = cryptoJWS.JWS(body.encode('utf-8')) jwsToken.add_signature(privateKeyToSign, None, json_encode({ "alg": self.signAlgorithm, "kid": jwkSignKey['kid'], "exp": self.__getJwsExpirationTime() })) signedBody = jwsToken.serialize(True) jweKeySet = self.__getJwkKeySet(location = self.hyperwalletKeySetLocation) jwkEncryptKey = self.__findJwkKeyByAlgorithm(jwkKeySet = jweKeySet, algorithm = self.encryptionAlgorithm) publicKeyToEncrypt = jwk.JWK(**jwkEncryptKey) protected_header = { "alg": self.encryptionAlgorithm, "enc": self.encryptionMethod, "typ": "JWE", "kid": jwkEncryptKey['kid'], } jweToken = jwe.JWE(signedBody.encode('utf-8'), recipient=publicKeyToEncrypt, protected=protected_header) return jweToken.serialize(True)
def handle(self, request): handler = self._find_handler(request) response = {'headers': dict()} # Handle request output = handler(request, response) if output is None: output = response.get('output') ct = response['headers'].get('Content-Type') if ct is None: ct = response['headers']['Content-Type'] = DEFAULT_CTYPE if 'application/json' in ct and isinstance(output, (dict, list)): output = json_encode(output).encode('utf-8') response['headers']['Content-Length'] = str(len(output)) response['output'] = output if output is not None and not hasattr(output, 'read') \ and not isinstance(output, six.binary_type): msg = "Handler {} returned unsupported type {} ({}):\n{!r}" raise TypeError(msg.format(handler, type(output), ct, output)) if output is not None and 'Content-Length' not in response['headers']: if hasattr(output, 'read'): # LOG: warning file-type objects should set Content-Length pass else: response['headers']['Content-Length'] = str(len(output)) return response
def export(self): """Exports the key in the standard JSON format""" d = dict() d.update(self._params) d.update(self._key) d.update(self._unknown) return json_encode(d)
def export_public(self): """Exports the public key in the standard JSON format. It fails if one is not available like when this function is called on a symmetric key. """ pub = self._public_params() return json_encode(pub)
def export_key(self): tdir = tempfile.mkdtemp(dir=paths.TMP) try: nsspwfile = os.path.join(tdir, 'nsspwfile') with open(nsspwfile, 'w+') as f: f.write(self.nssdb_password) wrapped_key_file = os.path.join(tdir, 'wrapped_key') certificate_file = os.path.join(tdir, 'certificate') ipautil.run([ paths.PKI, '-d', self.nssdb_path, '-C', nsspwfile, 'ca-authority-key-export', '--wrap-nickname', self.wrap_nick, '--target-nickname', self.target_nick, '-o', wrapped_key_file]) ipautil.run([ paths.CERTUTIL, '-d', self.nssdb_path, '-L', '-n', self.target_nick, '-a', '-o', certificate_file]) with open(wrapped_key_file, 'r') as f: wrapped_key = f.read() with open(certificate_file, 'r') as f: certificate = f.read() finally: shutil.rmtree(tdir) return json_encode({ 'wrapped_key': b64encode(wrapped_key), 'certificate': certificate})
def __init__(self, alg, key, header, payload, algs=None): """Core JWS token handling. :param alg: The algorithm used to produce the signature. See RFC 7518 :param key: A (:class:`jwcrypto.jwk.JWK`) key of appropriate type for the "alg" provided in the 'protected' json string. :param header: A JSON string representing the protected header. :param payload(bytes): An arbitrary value :param algs: An optional list of allowed algorithms :raises ValueError: if the key is not a :class:`JWK` object :raises InvalidJWAAlgorithm: if the algorithm is not valid, is unknown or otherwise not yet implemented. """ self.alg = alg self.engine = self._jwa(alg, algs) if not isinstance(key, JWK): raise ValueError('key is not a JWK object') self.key = key if header is not None: if isinstance(header, dict): header = json_encode(header) self.protected = base64url_encode(header.encode('utf-8')) else: self.protected = '' self.payload = base64url_encode(payload)
def encrypt_data(payload, passphrase): """ Crypta un payload in ingresso utilizzando la passphrase inserita :param payload: oggetto da cryptare :param passphrase: password da utilizzare per l'encrypt :return: payload cryptato """ try: if type(passphrase) == bytes: hash_passphrase = hashlib.sha512(passphrase).digest() else: hash_passphrase = hashlib.sha512(passphrase.encode()).digest() key_base64 = base64.urlsafe_b64encode(hash_passphrase) kjs = json.dumps({ 'k': key_base64.decode('utf-8', 'strict'), 'kty': 'oct' }) key = jwk.JWK.from_json(kjs) token = jwe.JWE(payload, json_encode({ "alg": "dir", "enc": "A256CBC-HS512" })) token.add_recipient(key) return token.serialize(compact=True) except Exception as e: LOG.warning("Exception: {}".format(str(e)), extra=set_client_ip()) return None
def topic(self): """ Generate token """ token = jwt.generate_jwt(payload, None, 'none', timedelta(seconds=60)) header, claims, _ = token.split('.') parsed_header = json_decode(base64url_decode(header)) del parsed_header['alg'] return u"%s.%s." % (base64url_encode(json_encode(parsed_header)), claims)
def sign_request(payload, nonce, jwk): # type: (dict, str, JWK) -> None header = generate_header(jwk) protected = dict(nonce=nonce) jws = JWS(json_encode(payload).encode()) jws.add_signature(jwk, header['alg'], protected, header) return json_decode(jws.serialize())
def export_key(self): tdir = tempfile.mkdtemp(dir=paths.TMP) try: wrapped_key_file = os.path.join(tdir, 'wrapped_key') certificate_file = os.path.join(tdir, 'certificate') ipautil.run([ paths.PKI, '-d', self.nssdb_path, '-C', self.nssdb_pwdfile, 'ca-authority-key-export', '--wrap-nickname', self.wrap_nick, '--target-nickname', self.target_nick, '-o', wrapped_key_file]) nssdb = NSSDatabase(self.nssdb_path) nssdb.run_certutil([ '-L', '-n', self.target_nick, '-a', '-o', certificate_file, ]) with open(wrapped_key_file, 'rb') as f: wrapped_key = f.read() with open(certificate_file, 'r') as f: certificate = f.read() finally: shutil.rmtree(tdir) return json_encode({ 'wrapped_key': b64encode(wrapped_key).decode('ascii'), 'certificate': certificate})
def export_public(self): """Exports the public key in the standard JSON format""" pub = {'kty': self._params['kty']} reg = JWKValuesRegistry[self._params['kty']] for param in reg: if reg[param][1] == 'Public': pub[param] = self._key[param] return json_encode(pub)
def serialize(self, compact=False): """Serializes the object into a JWE token. :param compact(boolean): if True generates the compact representation, otherwise generates a standard JSON format. :raises InvalidJWEOperation: if the object cannot serialized with the compact representation and `compat` is True. :raises InvalidJWEOperation: if no recipients have been added to the object. """ if 'ciphertext' not in self.objects: raise InvalidJWEOperation("No available ciphertext") if compact: for invalid in 'aad', 'unprotected': if invalid in self.objects: raise InvalidJWEOperation("Can't use compact encoding") if 'recipients' in self.objects: if len(self.objects['recipients']) != 1: raise InvalidJWEOperation("Invalid number of recipients") rec = self.objects['recipients'][0] else: rec = self.objects return '.'.join([base64url_encode(self.objects['protected']), base64url_encode(rec.get('encrypted_key', '')), base64url_encode(self.objects['iv']), base64url_encode(self.objects['ciphertext']), base64url_encode(self.objects['tag'])]) else: obj = self.objects enc = {'ciphertext': base64url_encode(obj['ciphertext']), 'iv': base64url_encode(obj['iv']), 'tag': base64url_encode(self.objects['tag'])} if 'protected' in obj: enc['protected'] = base64url_encode(obj['protected']) if 'unprotected' in obj: enc['unprotected'] = json_decode(obj['unprotected']) if 'aad' in obj: enc['aad'] = base64url_encode(obj['aad']) if 'recipients' in obj: enc['recipients'] = list() for rec in obj['recipients']: e = dict() if 'encrypted_key' in rec: e['encrypted_key'] = \ base64url_encode(rec['encrypted_key']) if 'header' in rec: e['header'] = json_decode(rec['header']) enc['recipients'].append(e) else: if 'encrypted_key' in obj: enc['encrypted_key'] = \ base64url_encode(obj['encrypted_key']) if 'header' in obj: enc['header'] = json_decode(obj['header']) return json_encode(enc)
def serialize(self, compact=False): """Serializes the object into a JWS token. :param compact(boolean): if True generates the compact representation, otherwise generates a standard JSON format. :raises InvalidJWSOperation: if the object cannot serialized with the compact representation and `compat` is True. :raises InvalidJWSSignature: if no signature has been added to the object, or no valid signature can be found. """ if compact: if 'signatures' in self.objects: raise InvalidJWSOperation("Can't use compact encoding with " "multiple signatures") if 'signature' not in self.objects: raise InvalidJWSSignature("No available signature") if not self.objects.get('valid', False): raise InvalidJWSSignature("No valid signature found") if 'protected' in self.objects: protected = base64url_encode(self.objects['protected']) else: protected = '' return '.'.join([protected, base64url_encode(self.objects['payload']), base64url_encode(self.objects['signature'])]) else: obj = self.objects if 'signature' in obj: if not obj.get('valid', False): raise InvalidJWSSignature("No valid signature found") sig = {'payload': base64url_encode(obj['payload']), 'signature': base64url_encode(obj['signature'])} if 'protected' in obj: sig['protected'] = base64url_encode(obj['protected']) if 'header' in obj: sig['header'] = obj['header'] elif 'signatures' in obj: sig = {'payload': base64url_encode(obj['payload']), 'signatures': list()} for o in obj['signatures']: if not o.get('valid', False): continue s = {'signature': base64url_encode(o['signature'])} if 'protected' in o: s['protected'] = base64url_encode(o['protected']) if 'header' in o: s['header'] = o['header'] sig['signatures'].append(s) if len(sig['signatures']) == 0: raise InvalidJWSSignature("No valid signature found") else: raise InvalidJWSSignature("No available signature") return json_encode(sig)
def add_recipient(self, key, header=None): """Encrypt the plaintext with the given key. :param key: A JWK key or password of appropriate type for the 'alg' provided in the JOSE Headers. :param header: A JSON string representing the per-recipient header. :raises ValueError: if the plaintext is missing or not of type bytes. :raises ValueError: if the compression type is unknown. :raises InvalidJWAAlgorithm: if the 'alg' provided in the JOSE headers is missing or unknown, or otherwise not implemented. """ if self.plaintext is None: raise ValueError('Missing plaintext') if not isinstance(self.plaintext, bytes): raise ValueError("Plaintext must be 'bytes'") jh = self._get_jose_header(header) alg, enc = self._get_alg_enc_from_headers(jh) rec = dict() if header: rec['header'] = header wrapped = alg.wrap(key, enc.key_size, self.cek, jh) self.cek = wrapped['cek'] if 'ek' in wrapped: rec['encrypted_key'] = wrapped['ek'] if 'header' in wrapped: h = json_decode(rec.get('header', '{}')) nh = self._merge_headers(h, wrapped['header']) rec['header'] = json_encode(nh) if 'ciphertext' not in self.objects: self._encrypt(alg, enc, jh) if 'recipients' in self.objects: self.objects['recipients'].append(rec) elif 'encrypted_key' in self.objects or 'header' in self.objects: self.objects['recipients'] = list() n = dict() if 'encrypted_key' in self.objects: n['encrypted_key'] = self.objects['encrypted_key'] del self.objects['encrypted_key'] if 'header' in self.objects: n['header'] = self.objects['header'] del self.objects['header'] self.objects['recipients'].append(n) self.objects['recipients'].append(rec) else: self.objects.update(rec)
def test_2_KEMClient(self): server_keys = [JWK(**test_keys[kem.KEY_USAGE_SIG]), None] client_keys = [JWK(**self.client_keys[kem.KEY_USAGE_SIG]), JWK(**self.client_keys[kem.KEY_USAGE_ENC])] cli = kem.KEMClient(server_keys, client_keys) kh = kem.KEMHandler({'KEMKeysStore': self.kk}) req = cli.make_request("key name") kh.parse(req, "key name") msg = kh.reply('key value') self.assertEqual(msg, json_decode(json_encode(msg))) rep = cli.parse_reply("key name", msg['value']) self.assertEqual(rep, 'key value')
def thumbprint(self, hashalg=hashes.SHA256()): """Returns the key thumbprint as specified by RFC 7638. :param hashalg: A hash function (defaults to SHA256) """ t = {'kty': self._params['kty']} for name, val in iteritems(JWKValuesRegistry[t['kty']]): if val[2] == 'Required': t[name] = self._key[name] digest = hashes.Hash(hashalg, backend=default_backend()) digest.update(bytes(json_encode(t).encode('utf8'))) return base64url_encode(digest.finalize())
def export(self, private_key=True): """Exports the key in the standard JSON format. :param private_key(bool): Whether to export the private key. Defaults to True. """ if private_key is not True: return self.export_public() d = dict() d.update(self._params) d.update(self._key) d.update(self._unknown) return json_encode(d)
def export_public(self): """Exports the public key in the standard JSON format""" pub = {} preg = JWKParamsRegistry for name in preg: if preg[name][1] == 'Public': if name in self._params: pub[name] = self._params[name] reg = JWKValuesRegistry[self._params['kty']] for param in reg: if reg[param][1] == 'Public': pub[param] = self._key[param] return json_encode(pub)
def test_5_6_encryption(self): plaintext = Payload_plaintext_5 protected = base64url_decode(JWE_Protected_Header_5_6_3) aes_key = jwk.JWK(**AES_key_5_6_1) E = jwe.JWE(plaintext, protected) E.add_recipient(aes_key) _ = E.serialize(compact=True) e = E.serialize() E.deserialize(e, aes_key) self.assertEqual(E.payload, plaintext) E.deserialize(JWE_compact_5_6_4, aes_key) self.assertEqual(E.payload, plaintext) E.deserialize(json_encode(JWE_general_5_6_4), aes_key) self.assertEqual(E.payload, plaintext)
def export(self, private_keys=True): """Exports a RFC 7517 keyset using the standard JSON format :param private_key(bool): Whether to export private keys. Defaults to True. """ exp_dict = dict() for k, v in iteritems(self): if k == 'keys': keys = list() for jwk in v: keys.append(json_decode(jwk.export(private_keys))) v = keys exp_dict[k] = v return json_encode(exp_dict)
def test_1_Parse_GET(self): cli_skey = JWK(**self.client_keys[0]) jtok = kem.make_sig_kem("mykey", None, cli_skey, "RS256") kh = kem.KEMHandler({'KEMKeysStore': self.kk}) kh.parse(jtok, "mykey") msg = kh.reply('output') self.assertEqual(msg, json_decode(json_encode(msg))) jtok = JWT(jwt=msg['value']) cli_ekey = JWK(**self.client_keys[1]) jtok.token.decrypt(cli_ekey) nested = jtok.token.payload jtok = JWT(jwt=nested.decode('utf-8')) jtok.token.verify(JWK(**test_keys[0])) payload = json_decode(jtok.token.payload)['value'] self.assertEqual(payload, 'output')
def get_key(self, usage, principal): conn = self.connect() scope = ldap.SCOPE_SUBTREE ldap_filter = self.build_filter(IPA_KEYS_QUERY, {'usage': RFC5280_USAGE_MAP[usage], 'princ': principal}) r = conn.search_s(self.keysbase, scope, ldap_filter) if len(r) != 1: raise ValueError("Incorrect number of results (%d) searching for" "public key for %s" % (len(r), principal)) ipa_public_key = r[0][1]['ipaPublicKey'][0] jwk = self._parse_public_key(ipa_public_key) jwk['use'] = KEY_USAGE_MAP[usage] return json_encode(jwk)