예제 #1
0
    def test_client_secret_jwt(self, client):
        _ci = client.client_info
        _ci.token_endpoint = "https://example.com/token"
        _ci.provider_info = {
            'issuer': 'https://example.com/',
            'token_endpoint': "https://example.com/token"
        }

        csj = ClientSecretJWT()
        request = AccessTokenRequest()

        csj.construct(request,
                      cli_info=client.client_info,
                      algorithm="HS256",
                      authn_endpoint='userinfo')
        assert request["client_assertion_type"] == JWT_BEARER
        assert "client_assertion" in request
        cas = request["client_assertion"]

        _skey = [SYMKey(k=b64e(as_bytes(_ci.client_secret)), use='sig')]
        jso = JWT(rec_keys={client.client_id: _skey}).unpack(cas)
        assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])

        _rj = JWS()
        info = _rj.verify_compact(
            cas, [SYMKey(k=b64e(as_bytes(_ci.client_secret)))])

        assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
        assert info['aud'] == [_ci.provider_info['issuer']]
예제 #2
0
def left_hash(msg, func="HS256"):
    """ 128 bits == 16 bytes """
    if func == 'HS256':
        return as_unicode(b64e(sha256_digest(msg)[:16]))
    elif func == 'HS384':
        return as_unicode(b64e(sha384_digest(msg)[:24]))
    elif func == 'HS512':
        return as_unicode(b64e(sha512_digest(msg)[:32]))
def test_a_1_1c():
    hmac = cryptojwt.intarr2bin(HMAC_KEY)
    signer = SIGNER_ALGS["HS256"]
    header = b'{"typ":"JWT",\r\n "alg":"HS256"}'
    payload = b'{"iss":"joe",\r\n "exp":1300819380,' \
              b'\r\n "http://example.com/is_root":true}'
    sign_input = b64e(header) + b'.' + b64e(payload)
    sig = signer.sign(sign_input, hmac)
    assert b64e(sig) == b'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'
예제 #4
0
def add_code_challenge(client_info, state):
    """
    PKCE RFC 7636 support

    :return:
    """
    try:
        cv_len = client_info.config['code_challenge']['length']
    except KeyError:
        cv_len = 64  # Use default

    # code_verifier: string of length cv_len
    code_verifier = unreserved(cv_len)
    _cv = code_verifier.encode()

    try:
        _method = client_info.config['code_challenge']['method']
    except KeyError:
        _method = 'S256'

    try:
        # Pick hash method
        _hash_method = CC_METHOD[_method]
        # Use it on the code_verifier
        _hv = _hash_method(_cv).hexdigest()
        # base64 encode the hash value
        code_challenge = b64e(_hv.encode()).decode()
    except KeyError:
        raise Unsupported('PKCE Transformation method:{}'.format(_method))

    client_info.state_db.add_info(state,
                                  code_verifier=code_verifier,
                                  code_challenge_method=_method)

    return {"code_challenge": code_challenge, "code_challenge_method": _method}
def test_a_1_1b():
    payload = b'{"iss":"joe",\r\n "exp":1300819380,' \
              b'\r\n "http://example.com/is_root":true}'
    val = b64e(payload)
    assert val == (
        b'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9'
        b'leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ')
예제 #6
0
    def thumbprint(self, hash_function, members=None):
        """
        Create a thumbprint of the key following the outline in
        https://tools.ietf.org/html/draft-jones-jose-jwk-thumbprint-01

        :param hash_function: A hash function to use for hashing the
            information
        :param members: Which attributes of the Key instance that should
            be included when computing the hash value.
        :return: A base64 encode hash over a set of Key attributes
        """
        if members is None:
            members = self.required

        members.sort()
        ser = self.serialize()
        _se = []
        for elem in members:
            try:
                _val = ser[elem]
            except KeyError:  # should never happen with the required set
                pass
            else:
                if isinstance(_val, bytes):
                    _val = as_unicode(_val)
                _se.append('"{}":{}'.format(elem, json.dumps(_val)))
        _json = '{{{}}}'.format(','.join(_se))

        return b64e(DIGEST_HASH[hash_function](_json))
예제 #7
0
    def encryption_key(self, alg, **kwargs):
        """
        Return an encryption key as per
        http://openid.net/specs/openid-connect-core-1_0.html#Encryption

        :param alg: encryption algorithm
        :param kwargs:
        :return: encryption key as byte string
        """
        if not self.key:
            self.deserialize()

        tsize = ALG2KEYLEN[alg]
        # _keylen = len(self.key)

        if tsize <= 32:
            # SHA256
            _enc_key = sha256_digest(self.key)[:tsize]
        elif tsize <= 48:
            # SHA384
            _enc_key = sha384_digest(self.key)[:tsize]
        elif tsize <= 64:
            # SHA512
            _enc_key = sha512_digest(self.key)[:tsize]
        else:
            raise JWKException("No support for symmetric keys > 512 bits")

        logger.debug('Symmetric encryption key: {}'.format(
            as_unicode(b64e(_enc_key))))

        return _enc_key
예제 #8
0
def party_value(pv):
    if pv:
        s = b64e(pv)
        r = int2big_endian(len(s))
        r.extend(s)
        return r
    else:
        return [0, 0, 0, 0]
예제 #9
0
def test_encryption_key():
    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A128KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWBw'

    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A192KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86'

    sk = SYMKey(key='df34db91c16613deba460752522d28f6ebc8a73d0d9185836270c26b')
    _enc = sk.encryption_key(alg='A256KW')
    _v = as_unicode(b64e(_enc))
    assert _v == 'xCo9VhtommCTGMWi-RyWB14GQqHAGC86vweU_Pi62X8'

    ek = sha256_digest(
        'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY'
    )[:16]
    assert as_unicode(b64e(ek)) == 'yf_UUkAFZ8Pn_prxPPgu9w'

    sk = SYMKey(
        key=
        'YzE0MjgzNmRlODI5Yzg2MGYyZTRjNGE0NTZlMzBkZDRiNzJkNDA5MzUzNjM0ODkzM2E2MDk3ZWY'
    )
    _enc = sk.encryption_key(alg='A128KW')
    _v = as_unicode(b64e(_enc))
    assert _v == as_unicode(b64e(ek))
예제 #10
0
def x5t_calculation(cert):
    """
    base64url-encoded SHA-1 thumbprint (a.k.a. digest) of the DER
    encoding of an X.509 certificate.

    :param cert: DER encoded X.509 certificate
    :return: x5t value
    """
    if isinstance(cert, str):
        der_cert = base64.b64decode(cert.encode('ascii'))
    else:
        der_cert = base64.b64decode(cert)

    return b64e(hashlib.sha1(der_cert).digest())
def test_jwe_09_a1():
    # RSAES OAEP and AES GCM
    msg = b"The true sign of intelligence is not knowledge but imagination."

    # A.1.1
    header = b'{"alg":"RSA-OAEP","enc":"A256GCM"}'
    b64_header = b64e(header)

    # A.1.2
    assert b64_header == b"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ"

    # A.1.3
    cek = intarr2bytes([
        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
    ])

    # A.1.4 Key Encryption
    enc_key = [
        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
    ]

    b64_ejek = b'ApfOLCaDbqs_JXPYy2I937v_xmrzj' \
               b'-Iss1mG6NAHmeJViM6j2l0MHvfseIdHVyU2BIoGVu9ohvkkWiRq5DL2jYZTPA9TAdwq3FUIVyoH-Pedf6elHIVFi2KGDEspYMtQARMMSBcS7pslx6flh1Cfh3GBKysztVMEhZ_maFkm4PYVCsJsvq6Ct3fg2CJPOs0X1DHuxZKoIGIqcbeK4XEO5a0h5TAuJObKdfO0dKwfNSSbpu5sFrpRFwV2FTTYoqF4zI46N9-_hMIznlEpftRXhScEJuZ9HG8C8CHB1WRZ_J48PleqdhF4o7fB5J1wFqUXBtbtuGJ_A2Xe6AEhrlzCOw'

    iv = intarr2bytes([227, 197, 117, 252, 2, 219, 233, 68, 180, 225, 77, 219])

    aadp = b64_header + b'.' + b64_ejek

    gcm = AES_GCMEncrypter(key=cek)
    ctxt, tag = split_ctx_and_tag(gcm.encrypt(msg, iv, aadp))

    _va = to_intarr(ctxt)
    assert _va == [
        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
    ]

    assert bytes2intarr(tag) == [
        130, 17, 32, 198, 120, 167, 144, 113, 0, 50, 158, 49, 102, 208, 118,
        152
    ]

    #tag = long2hexseq(tag)
    #iv = long2hexseq(iv)
    res = b".".join([b64_header, b64_ejek, b64e(iv), b64e(ctxt), b64e(tag)])

    # print(res.split(b'.'))
    expected = b'.'.join([
        b'eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ',
        b'ApfOLCaDbqs_JXPYy2I937v_xmrzj'
        b'-Iss1mG6NAHmeJViM6j2l0MHvfseIdHVyU2BIoGVu9ohvkkWiRq5DL2jYZTPA9TAdwq3FUIVyoH-Pedf6elHIVFi2KGDEspYMtQARMMSBcS7pslx6flh1Cfh3GBKysztVMEhZ_maFkm4PYVCsJsvq6Ct3fg2CJPOs0X1DHuxZKoIGIqcbeK4XEO5a0h5TAuJObKdfO0dKwfNSSbpu5sFrpRFwV2FTTYoqF4zI46N9-_hMIznlEpftRXhScEJuZ9HG8C8CHB1WRZ_J48PleqdhF4o7fB5J1wFqUXBtbtuGJ_A2Xe6AEhrlzCOw',
        b'48V1_ALb6US04U3b',
        b'5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6jiSdiwkIr3ajwQzaBtQD_A',
        b'ghEgxninkHEAMp4xZtB2mA'
    ])

    assert res == expected
def test_a_1_1a():
    header = b'{"typ":"JWT",\r\n "alg":"HS256"}'
    val = b64e(header)
    assert val == b"eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9"
예제 #13
0
 def add_kid(self):
     """
     Construct a Key ID using the thumbprint method and add it to
     the key attributes.
     """
     self.kid = b64e(self.thumbprint('SHA-256')).decode('utf8')
예제 #14
0
 def serialize(self, private=True):
     res = self.common()
     res["k"] = as_unicode(b64e(bytes(self.key)))
     return res
예제 #15
0
    def enc_setup(self, msg, key=None, auth_data=b'', **kwargs):
        """

        :param msg: Message to be encrypted
        :param auth_data:
        :param key: An EC key
        :param kwargs:
        :return:
        """
        encrypted_key = ""
        self.msg = msg
        self.auth_data = auth_data

        # Generate the input parameters
        try:
            apu = b64d(kwargs["apu"])
        except KeyError:
            apu = get_random_bytes(16)
        try:
            apv = b64d(kwargs["apv"])
        except KeyError:
            apv = get_random_bytes(16)

        # Handle Local Key and Ephemeral Public Key
        if not key:
            raise Exception("EC Key Required for ECDH-ES JWE Encryption Setup")

        # epk is either an Elliptic curve key instance or a JWK description of
        # one. This key belongs to the entity on the other side.
        try:
            _epk = kwargs['epk']
        except KeyError:
            _epk = ec.generate_private_key(NIST2SEC[as_unicode(key.crv)],
                                           default_backend())
            epk = ECKey().load_key(_epk.public_key())
        else:
            if isinstance(_epk, ec.EllipticCurvePublicKey):
                epk = ECKey().load_key(_epk)
            elif isinstance(_epk, ECKey):
                epk = _epk
            else:
                raise ValueError("epk of a type I can't handle")

        params = {
            "apu": b64e(apu),
            "apv": b64e(apv),
            "epk": epk.serialize(False)
        }

        cek = iv = None
        if 'cek' in kwargs and kwargs['cek']:
            cek = kwargs['cek']
        if 'iv' in kwargs and kwargs['iv']:
            iv = kwargs['iv']

        iv = self._generate_iv(self.enc, iv=iv)

        if self.alg == "ECDH-ES":
            try:
                dk_len = KEY_LEN[self.enc]
            except KeyError:
                raise Exception(
                    "Unknown key length for algorithm %s" % self.enc)

            cek = ecdh_derive_key(_epk, key.key, apu, apv,
                                  str(self.enc).encode(), dk_len)
        elif self.alg in ["ECDH-ES+A128KW", "ECDH-ES+A192KW", "ECDH-ES+A256KW"]:
            _pre, _post = self.alg.split("+")
            klen = int(_post[1:4])
            kek = ecdh_derive_key(_epk, key.key, apu, apv,
                                  str(_post).encode(), klen)
            cek = self._generate_key(self.enc, cek=cek)
            encrypted_key = aes_key_wrap(kek, cek, default_backend())
        else:
            raise Exception("Unsupported algorithm %s" % self.alg)

        return cek, encrypted_key, iv, params, epk