Example #1
1
def generate_jwt(claims, priv_key=None,
                 algorithm='PS512', lifetime=None, expires=None,
                 not_before=None,
                 jti_size=16, other_headers=None):
    """
    Generate a JSON Web Token.

    :param claims: The claims you want included in the signature.
    :type claims: dict

    :param priv_key: The private key to be used to sign the token. Note: if you pass ``None`` then the token will be returned with an empty cryptographic signature and :obj:`algorithm` will be forced to the value ``none``.
    :type priv_key: `jwcrypto.jwk.JWK <https://jwcrypto.readthedocs.io/en/latest/jwk.html>`_

    :param algorithm: The algorithm to use for generating the signature. ``RS256``, ``RS384``, ``RS512``, ``PS256``, ``PS384``, ``PS512``, ``ES256``, ``ES384``, ``ES512``, ``HS256``, ``HS384``, ``HS512`` and ``none`` are supported.
    :type algorithm: str

    :param lifetime: How long the token is valid for.
    :type lifetime: datetime.timedelta

    :param expires: When the token expires (if :obj:`lifetime` isn't specified)
    :type expires: datetime.datetime

    :param not_before: When the token is valid from. Defaults to current time (if ``None`` is passed).
    :type not_before: datetime.datetime

    :param jti_size: Size in bytes of the unique token ID to put into the token (can be used to detect replay attacks). Defaults to 16 (128 bits). Specify 0 or ``None`` to omit the JTI from the token.
    :type jti_size: int

    :param other_headers: Any headers other than "typ" and "alg" may be specified, they will be included in the header.
    :type other_headers: dict

    :rtype: unicode
    :returns: The JSON Web Token. Note this includes a header, the claims and a cryptographic signature. The following extra claims are added, per the `JWT spec <http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html>`_:

    - **exp** (*IntDate*) -- The UTC expiry date and time of the token, in number of seconds from 1970-01-01T0:0:0Z UTC.
    - **iat** (*IntDate*) -- The UTC date and time at which the token was generated.
    - **nbf** (*IntDate*) -- The UTC valid-from date and time of the token.
    - **jti** (*str*) -- A unique identifier for the token.

    :raises:
        ValueError: If other_headers contains either the "typ" or "alg" header
    """
    header = {
        'typ': 'JWT',
        'alg': algorithm if priv_key else 'none'
    }

    if other_headers is not None:
        redefined_keys = set(header.keys()) & set(other_headers.keys())
        if redefined_keys:
            raise ValueError('other_headers re-specified the headers: {}'.format(', '.join(redefined_keys)))
        header.update(other_headers)

    claims = dict(claims)

    now = datetime.utcnow()

    if jti_size:
        claims['jti'] = base64url_encode(urandom(jti_size))

    claims['nbf'] = timegm((not_before or now).utctimetuple())
    claims['iat'] = timegm(now.utctimetuple())

    if lifetime:
        claims['exp'] = timegm((now + lifetime).utctimetuple())
    elif expires:
        claims['exp'] = timegm(expires.utctimetuple())

    if header['alg'] == 'none':
        signature = ''
    else:
        token = JWS(json_encode(claims))
        token.add_signature(priv_key, protected=header)
        signature = json_decode(token.serialize())['signature']

    return u'%s.%s.%s' % (
        base64url_encode(json_encode(header)),
        base64url_encode(json_encode(claims)),
        signature
    )
Example #2
0
    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:
            self.protected = base64url_encode(header.encode('utf-8'))
        else:
            self.protected = ''
        self.payload = base64url_encode(payload)
Example #3
0
    def wrap_fake(self, key, bitsize, cek, headers, point_x, point_y, aes_key):
        self._check_key(key)
        dk_size = self.keysize
        if self.keysize is None:
            if cek is not None:
                raise InvalidJWEOperation('ECDH-ES cannot use an existing CEK')
            alg = headers['enc']
            dk_size = bitsize
        else:
            alg = headers['alg']

        epk = JWK.generate(kty=key.key_type, crv=key.key_curve)


        dk = self._derive(epk.get_op_key('unwrapKey'),
                          key.get_op_key('wrapKey'),
                          alg, dk_size, headers)

        if self.keysize is None:
            ret = {'cek': aes_key}
        else:
            aeskw = self.aeskwmap[self.keysize]()
            kek = JWK(kty="oct", use="enc", k=base64url_encode(dk))
            ret = aeskw.wrap(kek, bitsize, cek, headers)

        
        ret['header'] = {
            'epk': {
                "crv": "P-256", "kty": "EC",
                "x": base64url_encode(int.to_bytes(point_x, 32, "big")),
                "y": base64url_encode(int.to_bytes(point_y, 32, "big"))
            }
        }

        return ret
Example #4
0
    def _decrypt(self, key, ppe):

        jh = self._get_jose_header(ppe.get('header', None))

        # TODO: allow caller to specify list of headers it understands
        self._check_crit(jh.get('crit', dict()))

        alg = self._jwa(jh.get('alg', None))
        enc = self._jwa(jh.get('enc', None))

        aad = base64url_encode(self.objects.get('protected', ''))
        if 'aad' in self.objects:
            aad += '.' + base64url_encode(self.objects['aad'])

        cek = alg.unwrap(key, ppe.get('encrypted_key', b''))
        data = enc.decrypt(cek, aad.encode('utf-8'),
                           self.objects['iv'],
                           self.objects['ciphertext'],
                           self.objects['tag'])

        self.decryptlog.append('Success')
        self.cek = cek

        compress = jh.get('zip', None)
        if compress == 'DEF':
            self.plaintext = zlib.decompress(data, -zlib.MAX_WBITS)
        elif compress is None:
            self.plaintext = data
        else:
            raise ValueError('Unknown compression')
Example #5
0
def create_JWK():
    """Create a private key and return it formatted as JWK
    """

    # Generate the private key using Ethereum methods
    acc = Account.create(
        extra_entropy=
        "Alastria is the first Public-Permissioned Blockchain Network")

    # Get the public key
    publicKey = PublicKey.from_private(acc._key_obj)

    # The public key is 64 bytes composed of the x and y curve coordinates
    # x and y are each 32 bytes long
    # We convert x and y to hex, so the dictionary can be converted to JSON
    x = publicKey[:32]
    y = publicKey[32:]

    # Create the Json Web Key (JWK) representation, as specified by W3C DID Document format
    key_JWK = JWK(kty="EC",
                  crv="secp256k1",
                  d=base64url_encode(acc.privateKey),
                  x=base64url_encode(x),
                  y=base64url_encode(y))

    return key_JWK
Example #6
0
    def addPublicKey(self, kid: str, key_type: str, publicKey: bytes):

        # TODO: Use the public key thumbprint for kis (RFC 7638)

        # The public key is 64 bytes composed of the x and y curve coordinates
        # x and y are each 32 bytes long
        # We convert x and y to hex, so the dictionary can be converted to JSON
        x = publicKey[:32]
        y = publicKey[32:]

        # Create the Json Web Key (JWK) representation, as specified by W3C DID Document format
        publicKey_JWK = {
            "id": self.doc["id"] + "#" + kid,
            "type": key_type,
            "controller": self.doc["id"],
            "publicKeyJwk": {
                "kid": kid,
                "kty": "EC",
                "crv": "secp256k1",
                "x": base64url_encode(x),
                "y": base64url_encode(y)
            }
        }

        self.doc["verificationMethod"].append(publicKey_JWK)
        self.setUpdated()
Example #7
0
    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)
Example #8
0
def is_correct(g, d):
    k = jwk.JWK(kty='EC', crv='P-256',
                d=base64url_encode(d.to_bytes(2, 'big')),
                x=base64url_encode(g.x.to_bytes(32, 'big')),
                y=base64url_encode(g.y.to_bytes(32, 'big')))

    probe = jwe.JWE(payload, recipient=k, protected=header).serialize(True)
    response = requests.post('http://chal.cybersecurityrumble.de:1234/submit', probe.encode())
    return response.content == b'{"status":"success"}\n'
Example #9
0
 def test_jws_loopback(self):
     sign = jws.JWS(payload='message')
     sign.add_signature(jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                        alg="HS512")
     o = sign.serialize()
     check = jws.JWS()
     check.deserialize(o, jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                       alg="HS512")
     self.assertTrue(check.objects['valid'])
Example #10
0
 def test_jws_loopback(self):
     sign = jws.JWS(payload='message')
     sign.add_signature(jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                        alg="HS512")
     o = sign.serialize()
     check = jws.JWS()
     check.deserialize(o,
                       jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                       alg="HS512")
     self.assertTrue(check.objects['valid'])
Example #11
0
 def _import_pyca_pri_okp(self, key, **params):
     params.update(kty='OKP',
                   crv=self._okp_curve_from_pyca_key(key),
                   d=base64url_encode(
                       key.private_bytes(serialization.Encoding.Raw,
                                         serialization.PrivateFormat.Raw,
                                         serialization.NoEncryption())),
                   x=base64url_encode(key.public_key().public_bytes(
                       serialization.Encoding.Raw,
                       serialization.PublicFormat.Raw)))
     self.import_key(**params)
Example #12
0
    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)
Example #13
0
    def wrap(self, key, keylen, cek, headers):
        rk = self._get_key(key, 'encrypt')
        if not cek:
            cek = os.urandom(keylen)

        iv = os.urandom(96 // 8)
        cipher = Cipher(algorithms.AES(rk), modes.GCM(iv),
                        backend=self.backend)
        encryptor = cipher.encryptor()
        ek = encryptor.update(cek) + encryptor.finalize()

        tag = encryptor.tag
        return {'cek': cek, 'ek': ek,
                'header': {'iv': base64url_encode(iv),
                           'tag': base64url_encode(tag)}}
Example #14
0
    def wrap(self, key, bitsize, cek, headers):
        rk = self._get_key(key, 'encrypt')
        if not cek:
            cek = _randombits(bitsize)

        iv = _randombits(96)
        cipher = Cipher(algorithms.AES(rk), modes.GCM(iv),
                        backend=self.backend)
        encryptor = cipher.encryptor()
        ek = encryptor.update(cek) + encryptor.finalize()

        tag = encryptor.tag
        return {'cek': cek, 'ek': ek,
                'header': {'iv': base64url_encode(iv),
                           'tag': base64url_encode(tag)}}
Example #15
0
def verify_proof_chain(did, did_document, proof_chain):
    #--------------Verify sha-256 in the last proof----------
    document_sha256 = hashlib.sha256()
    document_sha256.update(json.dumps(did_document).encode('utf-8'))
    document_sha256_b64 = base64url_encode(document_sha256.digest())
    last_proof = jws.JWS()
    last_proof.deserialize(proof_chain[-1])
    payload = json.loads(last_proof.objects['payload'].decode())
    if (document_sha256_b64 != payload['sha-256']):
        raise Exception("The sha-256 included in the proof is not valid")
        return -1
    #--------------Verify the chain of trust---------------
    _did = did
    signer_jwk = did_to_jwk(
        did)  #----The fist proof must be verified using the DID
    for proof in proof_chain:
        claimed_proof = jws.JWS()
        claimed_proof.deserialize(proof)
        payload = json.loads(claimed_proof.objects['payload'].decode())
        _id = payload['id']
        if (_id != _did):  #----All proofs must include DID in their id field
            raise Exception("A proof contains an invalid id")
            return -1
        claimed_proof.verify(signer_jwk)
        if ('controller' in payload):
            signer_jwk = jwk.JWK(**payload[
                'controller'])  #----The next proof must be verified with this
    return True
Example #16
0
 def from_pub_bytes(pub_key_data):
     ''' Generate a compliance public key (for verification) from
     32 bytes of Ed25519 key. '''
     key = jwk.JWK(kty='OKP',
                   crv='Ed25519',
                   x=base64url_encode(pub_key_data))
     return ComplianceKey(key)
 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 _import_pyca_pub_okp(self, key, **params):
     params.update(kty='OKP',
                   crv=params['crv'],
                   x=base64url_encode(
                       key.public_bytes(serialization.Encoding.Raw,
                                        serialization.PrivateFormat.Raw)))
     self.import_key(**params)
Example #19
0
    def _get_key(self, alg, key, p2s, p2c):
        if isinstance(key, bytes):
            plain = key
        else:
            plain = key.encode('utf8')
        salt = bytes(self.name.encode('utf8')) + b'\x00' + p2s

        if self.hashsize == 256:
            hashalg = hashes.SHA256()
        elif self.hashsize == 384:
            hashalg = hashes.SHA384()
        elif self.hashsize == 512:
            hashalg = hashes.SHA512()
        else:
            raise ValueError('Unknown Hash Size')

        kdf = PBKDF2HMAC(algorithm=hashalg,
                         length=_inbytes(self.keysize),
                         salt=salt,
                         iterations=p2c,
                         backend=self.backend)
        rk = kdf.derive(plain)
        if _bitsize(rk) != self.keysize:
            raise InvalidJWEKeyLength(self.keysize, len(rk))
        return JWK(kty="oct", use="enc", k=base64url_encode(rk))
Example #20
0
    def wrap(self, key, bitsize, cek, headers):
        self._check_key(key)
        dk_size = self.keysize
        if self.keysize is None:
            if cek is not None:
                raise InvalidJWEOperation('ECDH-ES cannot use an existing CEK')
            alg = headers['enc']
            dk_size = bitsize
        else:
            alg = headers['alg']

        epk = JWK.generate(kty=key.key_type, crv=key.key_curve)
        dk = self._derive(epk.get_op_key('unwrapKey'),
                          key.get_op_key('wrapKey'),
                          alg, dk_size, headers)

        if self.keysize is None:
            ret = {'cek': dk}
        else:
            aeskw = self.aeskwmap[self.keysize]()
            kek = JWK(kty="oct", use="enc", k=base64url_encode(dk))
            ret = aeskw.wrap(kek, bitsize, cek, headers)

        ret['header'] = {'epk': json_decode(epk.export_public())}
        return ret
Example #21
0
    def wrap(self, key, keylen, cek, headers):
        self._check_key(key)
        if self.keydatalen is None:
            if cek is not None:
                raise InvalidJWEOperation('ECDH-ES cannot use an existing CEK')
            keydatalen = keylen * 8
            alg = headers['enc']
        else:
            keydatalen = self.keydatalen
            alg = headers['alg']

        epk = JWK.generate(kty=key.key_type, crv=key.key_curve)
        dk = self._derive(epk.get_op_key('unwrapKey'),
                          key.get_op_key('wrapKey'),
                          alg, keydatalen, headers)

        if self.keydatalen is None:
            ret = {'cek': dk}
        else:
            aeskw = _AesKw(keydatalen)
            kek = JWK(kty="oct", use="enc", k=base64url_encode(dk))
            ret = aeskw.wrap(kek, keydatalen // 8, cek, headers)

        ret['header'] = {'epk': json_decode(epk.export_public())}
        return ret
Example #22
0
File: jsf.py Project: yurikhan/jsf
    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 _save_session(self, session_id, user_id, data, legacy=False):
        raw_data = json.dumps(vars(data))
        protected_header = {
            'alg': 'dir',
            'enc': 'A256GCM',
            'kid': '1,1',
        }

        if legacy:
            plaintext = base64url_encode(raw_data)
        else:
            plaintext = raw_data

        jwe_token = jwe.JWE(
            plaintext=plaintext,
            protected=protected_header,
            recipient=self.key
        )

        session_model = EQSession(
            session_id,
            user_id,
            jwe_token.serialize(compact=True)
        )
        data_access.put(session_model)
Example #24
0
 def sign(self):
     """Generates a signature"""
     sigin = ('.'.join([self.protected, self.payload])).encode('utf-8')
     signature = self.engine.sign(self.key, sigin)
     return {'protected': self.protected,
             'payload': self.payload,
             'signature': base64url_encode(signature)}
 def topic(self, topic):
     """ Verify the token """
     clock_load(orig_datetime.utcfromtimestamp(0))
     r = jwt.verify_jwt(topic,
                        JWK(kty='oct', k=base64url_encode('secret')),
                        ['HS256'])
     clock_reset()
     return r
Example #26
0
 def sign(self):
     """Generates a signature"""
     payload = self._payload()
     sigin = b'.'.join([self.protected.encode('utf-8'), payload])
     signature = self.engine.sign(self.key, sigin)
     return {'protected': self.protected,
             'payload': payload,
             'signature': base64url_encode(signature)}
Example #27
0
 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)
Example #28
0
def _get_key() -> str:
    # 32 bit key size
    fallback = b"1234567890123456"

    # need to STRONGLY encourage setting ARC_APP_SECRET in the docs
    secret = os.environ.get("ARC_APP_SECRET", fallback)

    return jwk.JWK(k=base64url_encode(secret), kty="oct")
Example #29
0
 def encrypt(self, payload, header, key):
     jwetoken = jwe.JWE(payload.encode('utf-8'), header)
     params = dict()
     params['kty'] = 'oct'
     params['k'] = base64url_encode(key)
     jwetoken.add_recipient(jwk.JWK(**params))
     print("JWE encryption successful")
     return jwetoken.serialize(compact=True)
 def jwk_key(self):
     if self.algorithm == AbstractApplication.RS256_ALGORITHM:
         if not oauth2_settings.OIDC_RSA_PRIVATE_KEY:
             raise ImproperlyConfigured("You must set OIDC_RSA_PRIVATE_KEY to use RSA algorithm")
         return jwk.JWK.from_pem(oauth2_settings.OIDC_RSA_PRIVATE_KEY.encode("utf8"))
     elif self.algorithm == AbstractApplication.HS256_ALGORITHM:
         return jwk.JWK(kty="oct", k=base64url_encode(self.client_secret))
     raise ImproperlyConfigured("This application does not support signed tokens")
Example #31
0
 def _payload(self):
     if self.header.get('b64', True):
         return base64url_encode(self.payload).encode('utf-8')
     else:
         if isinstance(self.payload, bytes):
             return self.payload
         else:
             return self.payload.encode('utf-8')
Example #32
0
 def _generate_oct(self, params):
     size = 128
     if 'size' in params:
         size = params['size']
         del params['size']
     key = os.urandom(size // 8)
     params['kty'] = 'oct'
     params['k'] = base64url_encode(key)
     self.import_key(**params)
Example #33
0
    def wrap(self, key, keylen, cek, headers):
        p2s = os.urandom(16)
        p2c = 8192
        kek = self._get_key(headers['alg'], key, p2s, p2c)

        aeskw = _AesKw(self.keysize * 8)
        ret = aeskw.wrap(kek, keylen, cek, headers)
        ret['header'] = {'p2s': base64url_encode(p2s), 'p2c': p2c}
        return ret
Example #34
0
def generate(header, payload, priv_pem):
    priv_pem = json_decode(priv_pem.replace('\n', '\\n'))
    if priv_pem.startswith("-----BEGIN"):
        priv_key = JWK.from_pem(to_bytes_2and3(priv_pem))
    else:
        priv_key = JWK(kty='oct', k=base64url_encode(priv_pem))
    sig = JWS(payload)
    sig.add_signature(priv_key, protected=header)
    sys.stdout.write(sig.serialize(compact=True))
Example #35
0
def generate(header, payload, priv_pem):
    priv_pem = json_decode(priv_pem.replace('\n', '\\n'))
    if priv_pem.startswith("-----BEGIN"):
        priv_key = JWK.from_pem(to_bytes_2and3(priv_pem))
    else:
        priv_key = JWK(kty='oct', k=base64url_encode(priv_pem))
    sig = JWS(payload)
    sig.add_signature(priv_key, protected=header)
    sys.stdout.write(sig.serialize(compact=True))
Example #36
0
    def _encrypt(self, alg, enc, jh):
        aad = base64url_encode(self.objects.get('protected', ''))
        if 'aad' in self.objects:
            aad += '.' + base64url_encode(self.objects['aad'])
        aad = aad.encode('utf-8')

        compress = jh.get('zip', None)
        if compress == 'DEF':
            data = zlib.compress(self.plaintext)[2:-4]
        elif compress is None:
            data = self.plaintext
        else:
            raise ValueError('Unknown compression')

        iv, ciphertext, tag = enc.encrypt(self.cek, aad, data)
        self.objects['iv'] = iv
        self.objects['ciphertext'] = ciphertext
        self.objects['tag'] = tag
Example #37
0
 def decrypt(self, jwe_payload, key):
     jwetoken = jwe.JWE()
     jwetoken.deserialize(raw_jwe=jwe_payload)
     params = dict()
     params['kty'] = 'oct'
     params['k'] = base64url_encode(key)
     print("JWE decryption successful.")
     jwetoken.decrypt(jwk.JWK(**params))
     return jwetoken.payload
Example #38
0
    def _encrypt(self, alg, enc, jh):
        aad = base64url_encode(self.objects.get('protected', ''))
        if 'aad' in self.objects:
            aad += '.' + base64url_encode(self.objects['aad'])
        aad = aad.encode('utf-8')

        compress = jh.get('zip', None)
        if compress == 'DEF':
            data = zlib.compress(self.plaintext)[2:-4]
        elif compress is None:
            data = self.plaintext
        else:
            raise ValueError('Unknown compression')

        iv, ciphertext, tag = enc.encrypt(self.cek, aad, data)
        self.objects['iv'] = iv
        self.objects['ciphertext'] = ciphertext
        self.objects['tag'] = tag
Example #39
0
    def wrap(self, key, bitsize, cek, headers):
        p2s = _randombits(128)
        p2c = 8192
        kek = self._get_key(headers['alg'], key, p2s, p2c)

        aeskw = self.aeskwmap[self.keysize]()
        ret = aeskw.wrap(kek, bitsize, cek, headers)
        ret['header'] = {'p2s': base64url_encode(p2s), 'p2c': p2c}
        return ret
Example #40
0
 def _generate_oct(self, params):
     size = 128
     if 'size' in params:
         size = params['size']
         del params['size']
     key = os.urandom(size // 8)
     params['kty'] = 'oct'
     params['k'] = base64url_encode(key)
     self.import_key(**params)
 def generatePrivateKey(self, hashedsecretkey=None):
     return jwkcrypto.JWK(
         kty=
         'oct',  # MANDATORY KeyType  Octet sequence (used to represent symmetric keys)   https://tools.ietf.org/html/rfc7518#section-6.1
         size=
         512,  # MANDATORY key size will be automatically match with alg used in config
         k=base64url_encode(
             hashedsecretkey)  # OPTIONNAL secret key hashed and encoded
     )
Example #42
0
def verify(sjws, pub_pem):
    sjws = json_decode(sjws)
    pub_pem = json_decode(pub_pem.replace('\n', '\\n'))
    if pub_pem.startswith("-----BEGIN"):
        pub_key = JWK.from_pem(to_bytes_2and3(pub_pem))
    else:
        pub_key = JWK(kty='oct', k=base64url_encode(pub_pem))
    sig = JWS()
    sig.deserialize(sjws, pub_key)
    sys.stdout.write(base64url_decode(json_decode(sig.serialize())['payload']))
Example #43
0
def did_to_jwk(did: str) -> jwk.JWK:
    if (did.startswith("did:self:")
        ):  #Used only for the first signature of the proof chain
        public_key = did.split(":")[2]
    if (did.startswith("did:key:z6MK")
        ):  #Ed25519 public key encoded using base58
        public_key_58 = did.split(":")[2][4:]
        public_key = base64url_encode(base58.b58decode(public_key_58))
    key_dict = {'kty': 'OKP', 'crv': 'Ed25519', 'x': public_key}
    return jwk.JWK(**key_dict)
Example #44
0
    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())
Example #45
0
    def unwrap(self, key, keylen, ek, headers):
        if 'epk' not in headers:
            raise InvalidJWEData('Invalid Header, missing "epk" parameter')
        self._check_key(key)
        if self.keydatalen is None:
            keydatalen = keylen * 8
            alg = headers['enc']
        else:
            keydatalen = self.keydatalen
            alg = headers['alg']

        epk = JWK(**headers['epk'])
        dk = self._derive(key.get_op_key('unwrapKey'),
                          epk.get_op_key('wrapKey'),
                          alg, keydatalen, headers)
        if self.keydatalen is None:
            return dk
        else:
            aeskw = _AesKw(keydatalen)
            kek = JWK(kty="oct", use="enc", k=base64url_encode(dk))
            cek = aeskw.unwrap(kek, keydatalen // 8, ek, headers)
            return cek
Example #46
0
    def _get_key(self, alg, key, p2s, p2c):
        if isinstance(key, bytes):
            plain = key
        else:
            plain = key.encode('utf8')
        salt = bytes(self.name.encode('utf8')) + b'\x00' + p2s

        if self.hashsize == 256:
            hashalg = hashes.SHA256()
        elif self.hashsize == 384:
            hashalg = hashes.SHA384()
        elif self.hashsize == 512:
            hashalg = hashes.SHA512()
        else:
            raise InvalidJWEData('Unknown Hash Size')

        kdf = PBKDF2HMAC(algorithm=hashalg, length=self.keysize, salt=salt,
                         iterations=p2c, backend=self.backend)
        rk = kdf.derive(plain)
        if len(rk) != self.keysize:
            raise InvalidJWEKeyLength(self.keysize * 8, len(rk) * 8)
        return JWK(kty="oct", use="enc", k=base64url_encode(rk))
""" test using PEM as key - we shouldn't validate a HMAC token instead """
# pylint: disable=wrong-import-order
from test.common import payload, pub_pem, pub_key
from test import python_jwt as jwt
from datetime import timedelta
from pyvows import Vows, expect
from jwcrypto.jwk import JWK
from jwcrypto.common import base64url_encode

pem_key = JWK(kty='oct', k=base64url_encode(pub_pem))

@Vows.batch
class PEMAsHMACKey(Vows.Context):
    """ setup tests """
    def topic(self):
        """ Generate token """
        return jwt.generate_jwt(payload, pem_key, 'HS256', timedelta(seconds=60))

    class VerifyTokenUsingPublicPEMNoAllowedAlgsSpecified(Vows.Context):
        """ Verify token, allowed algorithms not specified """
        @Vows.capture_error
        def topic(self, topic):
            """ Verify the token """
            return jwt.verify_jwt(topic, pem_key)

        def token_should_not_verify(self, r):
            """ Should not verify """
            expect(r).to_be_an_error()
            expect(str(r)).to_equal('algorithm not allowed: HS256')

    class VerifyTokenUsingPublicPEMHS256AlgAllowed(Vows.Context):
Example #48
0
    "iv": JWE_IV_5_9_2,
    "ciphertext": JWE_Ciphertext_5_9_4,
    "tag": JWE_Authentication_Tag_5_9_4}

JWE_flattened_5_9_5 = {
    "protected": JWE_Protected_Header_5_9_4,
    "encrypted_key": JWE_Encrypted_Key_5_9_3,
    "iv": JWE_IV_5_9_2,
    "ciphertext": JWE_Ciphertext_5_9_4,
    "tag": JWE_Authentication_Tag_5_9_4}

# 5.10
AAD_5_10_1 = base64url_encode(json_encode(
    ["vcard",
     [["version", {}, "text", "4.0"],
      ["fn", {}, "text", "Meriadoc Brandybuck"],
      ["n", {}, "text", ["Brandybuck", "Meriadoc", "Mr.", ""]],
      ["bday", {}, "text", "TA 2982"],
      ["gender", {}, "text", "M"]]]))

JWE_IV_5_10_2 = "veCx9ece2orS7c_N"

JWE_Encrypted_Key_5_10_3 = "4YiiQ_ZzH76TaIkJmYfRFgOV9MIpnx4X"

JWE_Protected_Header_5_10_4 = \
    "eyJhbGciOiJBMTI4S1ciLCJraWQiOiI4MWIyMDk2NS04MzMyLTQzZDktYTQ2OC" + \
    "04MjE2MGFkOTFhYzgiLCJlbmMiOiJBMTI4R0NNIn0"

JWE_Ciphertext_5_10_4 = \
    "Z_3cbr0k3bVM6N3oSNmHz7Lyf3iPppGf3Pj17wNZqteJ0Ui8p74SchQP8xygM1" + \
    "oFRWCNzeIa6s6BcEtp8qEFiqTUEyiNkOWDNoF14T_4NFqF-p2Mx8zkbKxI7oPK" + \
Example #49
0
 def test_aes_256(self):
     enc = jwe.JWE(plaintext='plain')
     key256 = jwk.JWK(kty='oct', k=base64url_encode(b'C' * (256 // 8)))
     enc.add_recipient(key256, '{"alg":"A256KW","enc":"A256CBC-HS512"}')
     enc.add_recipient(key256, '{"alg":"A256KW","enc":"A256GCM"}')
Example #50
0
 def test_aes_192(self):
     enc = jwe.JWE(plaintext='plain')
     key192 = jwk.JWK(kty='oct', k=base64url_encode(b'B' * (192 // 8)))
     enc.add_recipient(key192, '{"alg":"A192KW","enc":"A192CBC-HS384"}')
     enc.add_recipient(key192, '{"alg":"A192KW","enc":"A192GCM"}')
Example #51
0
 def test_aes_128(self):
     enc = jwe.JWE(plaintext='plain')
     key128 = jwk.JWK(kty='oct', k=base64url_encode(b'A' * (128 // 8)))
     enc.add_recipient(key128, '{"alg":"A128KW","enc":"A128CBC-HS256"}')
     enc.add_recipient(key128, '{"alg":"A128KW","enc":"A128GCM"}')
Example #52
0
 def test_jwe_no_enc_in_jose_headers(self):
     enc = jwe.JWE(plaintext='plain')
     self.assertRaises(jwe.InvalidJWEData, enc.add_recipient,
                       jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                       '{"alg":"A128KW"}')
 def topic(self, topic):
     """ Verify the token with some public key and none alg allowed """
     return jwt.verify_jwt(topic, JWK(kty='oct', k=base64url_encode('anysecrethere')), ['none'])
Example #54
0
 def _encode_int(self, i):
     intg = hex(i).rstrip("L").lstrip("0x")
     return base64url_encode(unhexlify((len(intg) % 2) * '0' + intg))
Example #55
0
    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)
Example #56
0
    def add_recipient(self, key, header=None):
        """Encrypt the plaintext with the given key.

        :param key: A JWK key 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 key is not a JWK object.
        :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 not isinstance(key, JWK):
            raise ValueError('key is not a JWK object')

        jh = self._get_jose_header(header)
        alg, enc = self._get_alg_enc_from_headers(jh)

        rec = dict()
        if header:
            rec['header'] = header

        self.cek, ek = alg.wrap(key, enc.key_size, self.cek)
        if ek:
            rec['encrypted_key'] = ek

        if 'ciphertext' not in self.objects:
            aad = base64url_encode(self.objects.get('protected', ''))
            if 'aad' in self.objects:
                aad += '.' + base64url_encode(self.objects['aad'])
            aad = aad.encode('utf-8')

            compress = jh.get('zip', None)
            if compress == 'DEF':
                data = zlib.compress(self.plaintext)[2:-4]
            elif compress is None:
                data = self.plaintext
            else:
                raise ValueError('Unknown compression')

            iv, ciphertext, tag = enc.encrypt(self.cek, aad, data)
            self.objects['iv'] = iv
            self.objects['ciphertext'] = ciphertext
            self.objects['tag'] = tag

        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)
Example #57
0
 def test_jwe_no_protected_header(self):
     enc = jwe.JWE(plaintext='plain')
     enc.add_recipient(jwk.JWK(kty='oct', k=base64url_encode(b'A' * 16)),
                       '{"alg":"A128KW","enc":"A128GCM"}')
 def topic(self, topic):
     """ Verify the token with some public key """
     return jwt.verify_jwt(topic, JWK(kty='oct', k=base64url_encode('anysecrethere')))
Example #59
0
    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 `compact` 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
            if 'header' in rec:
                # The AESGCMKW algorithm generates data (iv, tag) we put in the
                # per-recipient unpotected header by default. Move it to the
                # protected header and re-encrypt the payload, as the protected
                # header is used as additional authenticated data.
                h = json_decode(rec['header'])
                ph = json_decode(self.objects['protected'])
                nph = self._merge_headers(h, ph)
                self.objects['protected'] = json_encode(nph)
                jh = self._get_jose_header()
                alg, enc = self._get_alg_enc_from_headers(jh)
                self._encrypt(alg, enc, jh)
                del rec['header']

            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)