Ejemplo n.º 1
0
    def to_string(self, remote_key = None, remote_ip = None):
        """
        Sign and encrypt this response.

        :param remote_key: Encrypt response to this key
        :param remote_ip: If no remote_key, look up a key for this remote_ip

        :type remote_key: str or None
        :type remote_ip: str or None

        :rtype: str
        """
        sign_key = self._config.keys.private_key
        self._logger.debug("Signing response using key {!r}".format(sign_key))
        jws = jose.sign(self._data, sign_key.jwk, alg = self._config.jose_alg)
        signed_claims = {'v1': jose.serialize_compact(jws)}
        self._logger.debug("Signed response: {!r}".format(signed_claims))
        encrypt_key = remote_key
        if not encrypt_key:
            # default to the first key found using the remote_ip in case no key was supplied
            ip_keys = self._config.keys.lookup_by_ip(remote_ip)
            if not ip_keys:
                self._logger.warning("Found no key for IP {!r}, can't encrypt response:\n{!r}".format(
                    remote_ip, self._data
                ))
                raise EduIDAPIError("No API Key found - can't encrypt response")
            encrypt_key = ip_keys[0]
        self._logger.debug("Encrypting claims to key {!r}".format(encrypt_key))
        jwe = jose.encrypt(signed_claims, encrypt_key.jwk)
        return jose.serialize_compact(jwe)
Ejemplo n.º 2
0
    def to_string(self, remote_key=None, remote_ip=None):
        """
        Sign and encrypt this response.

        :param remote_key: Encrypt response to this key
        :param remote_ip: If no remote_key, look up a key for this remote_ip

        :type remote_key: str or None
        :type remote_ip: str or None

        :rtype: str
        """
        sign_key = self._config.keys.private_key
        self._logger.debug("Signing response using key {!r}".format(sign_key))
        jws = jose.sign(self._data, sign_key.jwk, alg=self._config.jose_alg)
        signed_claims = {'v1': jose.serialize_compact(jws)}
        self._logger.debug("Signed response: {!r}".format(signed_claims))
        encrypt_key = remote_key
        if not encrypt_key:
            # default to the first key found using the remote_ip in case no key was supplied
            ip_keys = self._config.keys.lookup_by_ip(remote_ip)
            if not ip_keys:
                self._logger.warning(
                    "Found no key for IP {!r}, can't encrypt response:\n{!r}".
                    format(remote_ip, self._data))
                raise EduIDAPIError(
                    "No API Key found - can't encrypt response")
            encrypt_key = ip_keys[0]
        self._logger.debug("Encrypting claims to key {!r}".format(encrypt_key))
        jwe = jose.encrypt(signed_claims, encrypt_key.jwk)
        return jose.serialize_compact(jwe)
Ejemplo n.º 3
0
    def test_jwe(self):
        bad_key = {'k': RSA.generate(2048).exportKey('PEM')}

        for (alg, jwk), enc in product(self.algs, self.encs):
            jwe = jose.encrypt(claims, rsa_pub_key, enc=enc, alg=alg)

            # make sure the body can't be loaded as json (should be encrypted)
            try:
                json.loads(jose.b64decode_url(jwe.ciphertext))
                self.fail()
            except ValueError:
                pass

            token = jose.serialize_compact(jwe)

            jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key)
            self.assertNotIn(jose._TEMP_VER_KEY, claims)

            self.assertEqual(jwt.claims, claims)

            # invalid key
            try:
                jose.decrypt(jose.deserialize_compact(token), bad_key)
                self.fail()
            except jose.Error as e:
                self.assertEqual(e.message, 'Incorrect decryption.')
Ejemplo n.º 4
0
    def test_jwe_no_error_with_iat_claim(self):
        claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        jose.decrypt(jose.deserialize_compact(et),
                     rsa_priv_key,
                     expiry_seconds=20)
Ejemplo n.º 5
0
    def test_jwe(self):
        bad_key = {'k': RSA.generate(2048).exportKey('PEM')}

        for (alg, jwk), enc in product(self.algs, self.encs):
            jwe = jose.encrypt(claims, rsa_pub_key, enc=enc, alg=alg)

            # make sure the body can't be loaded as json (should be encrypted)
            try:
                json.loads(jose.b64decode_url(jwe.ciphertext))
                self.fail()
            except ValueError:
                pass

            token = jose.serialize_compact(jwe)

            jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key)
            self.assertNotIn(jose._TEMP_VER_KEY, claims)

            self.assertEqual(jwt.claims, claims)

            # invalid key
            try:
                jose.decrypt(jose.deserialize_compact(token), bad_key)
                self.fail()
            except jose.Error as e:
                self.assertEqual(e.message, 'Incorrect decryption.')
Ejemplo n.º 6
0
    def test_jws_asym(self):
        algs = ('RS256', 'RS384', 'RS512')

        for alg in algs:
            st = jose.serialize_compact(jose.sign(claims, rsa_priv_key, alg=alg))
            jwt = jose.verify(jose.deserialize_compact(st), rsa_pub_key)
            self.assertEqual(jwt.claims, claims)
Ejemplo n.º 7
0
    def test_jwe_decrypt_legacy_v1_without_temp_ver_incorrect_jwk(self):
        jwk_for_encrypt = {'k': PRIVATE_KEY}

        legacy_legacy_temp_ver = jose.serialize_compact(
            legacy_encrypt(claims, jwk_for_encrypt)
        )

        jwk_for_decrypt = {'k': RSA.generate(2048).exportKey('PEM')}

        legacy_patch = mock.patch.object(
            jose, 'legacy_decrypt', wraps=jose.legacy_decrypt
        )
        spec_patch = mock.patch.object(
            jose, 'spec_compliant_decrypt', wraps=jose.spec_compliant_decrypt
        )
        with legacy_patch as legacy_mock, spec_patch as spec_mock:
            with self.assertRaises(jose.Error) as decryption_error:
                jose.decrypt(
                    jose.deserialize_compact(legacy_legacy_temp_ver),
                    jwk_for_decrypt)

        self.assertEqual(legacy_mock.call_count, 1)
        self.assertEqual(spec_mock.call_count, 1)

        self.assertEqual(decryption_error.exception.message,
                          "Incorrect decryption.")
Ejemplo n.º 8
0
Archivo: tests.py Proyecto: wendtr/jose
    def test_jwe_direct_encryption(self):
        symmetric_key = "tisasymmetrickey"

        jwe = jose.encrypt(claims, "", alg = "dir",enc="A128CBC-HS256",
                        dir_key = symmetric_key)

        # make sure the body can't be loaded as json (should be encrypted)
        try:
            json.loads(jose.b64decode_url(jwe.ciphertext))
            self.fail()
        except ValueError:
            pass
        token = jose.serialize_compact(jwe)
		
        jwt = jose.decrypt(jose.deserialize_compact(token),"",
                           dir_key = symmetric_key)
        self.assertNotIn(jose._TEMP_VER_KEY, claims)
		
        self.assertEqual(jwt.claims, claims)
		
		# invalid key
        badkey = "1234123412341234"
        try:
            jose.decrypt(jose.deserialize_compact(token), '', dir_key=badkey)
            self.fail()
        except jose.Error as e:
            self.assertEqual(e.message, 'Mismatched authentication tags')
Ejemplo n.º 9
0
def internal_auth_temporary(event, context):
    """AWS_LAMBDA:auth_temporary_jwt
    Generate a valid token for temporary access.

    :param tt: Registration token.
    :type tt: str.
    :returns: str -- Authentication token used for API calls.

    """

    #generate token
    now_time = time.time()
    end_time = time.time() + 31104000
    claims = {
        'exp': end_time,
        'nbf': now_time,
        'iss': 'medpass-aws',
        'aud': 'webclient',
        'iat': now_time,
        'type': 'TEMPORARY',
        'id': event['user_id']
    }

    jwe_token = jose.encrypt(claims, {'k': PUBLIC_KEY}, enc='A256CBC-HS512')
    auth_token = jose.serialize_compact(jwe_token)
    output = {'Authorization': auth_token}
    return output
Ejemplo n.º 10
0
    def test_mfa_add_request(self):
        """
        Test basic ability to parse an mfa_add request.

        :return:
        """
        nonce = os.urandom(10)
        claims = {'version': 1,
                  'token_type': 'OATH',
                  'nonce': nonce.encode('hex'),
                  'OATH': {'digits': 6,
                           'issuer': 'TestIssuer',
                           'account': '*****@*****.**',
                           }
                  }
        priv_jwk = self.config.keys.private_key.jwk
        server_jwk = self.config.keys.lookup_by_name("self").jwk
        jwe = self._sign_and_encrypt(claims, priv_jwk, server_jwk)
        serialized = jose.serialize_compact(jwe)

        response = self.request('/mfa_add', request=serialized, return_error=True)

        jwt = self._decrypt_and_verify(response.body[0], priv_jwk, server_jwk)

        response_claims = jwt.claims

        self.logger.debug("Response claims:\n{!s}".format(pprint.pformat(response_claims)))

        self.assertEqual(response_claims,
                         {u'nonce': nonce.encode('hex'),
                          u'reason': u'No API Key found for OATH AEAD service',
                          u'status': u'FAIL',
                          u'version': 1,
                          })
Ejemplo n.º 11
0
    def test_jwe_decrypt_legacy_v1_without_temp_ver_incorrect_jwk(self):
        jwk_for_encrypt = {'k': PRIVATE_KEY}

        legacy_legacy_temp_ver = jose.serialize_compact(
            legacy_encrypt(claims, jwk_for_encrypt)
        )

        jwk_for_decrypt = {'k': RSA.generate(2048).exportKey('PEM')}

        legacy_patch = mock.patch.object(
            jose, 'legacy_decrypt', wraps=jose.legacy_decrypt
        )
        spec_patch = mock.patch.object(
            jose, 'spec_compliant_decrypt', wraps=jose.spec_compliant_decrypt
        )
        with legacy_patch as legacy_mock, spec_patch as spec_mock:
            with self.assertRaises(jose.Error) as decryption_error:
                jose.decrypt(
                    jose.deserialize_compact(legacy_legacy_temp_ver),
                    jwk_for_decrypt)

        self.assertEqual(legacy_mock.call_count, 1)
        self.assertEqual(spec_mock.call_count, 1)

        self.assertEqual(decryption_error.exception.message,
                          "Incorrect decryption.")
Ejemplo n.º 12
0
    def test_jwe_decrypt_legacy_v1_without_temp_ver(self):
        jwk = {'k': PRIVATE_KEY}

        legacy_patch = mock.patch.object(
            jose, 'legacy_decrypt', wraps=jose.legacy_decrypt
        )
        spec_patch = mock.patch.object(
            jose, 'spec_compliant_decrypt', wraps=jose.spec_compliant_decrypt
        )

        legacy_legacy_temp_ver = jose.serialize_compact(
            legacy_encrypt(claims, jwk)
        )

        with legacy_patch as legacy_mock, spec_patch as spec_mock:
            jwt = jose.decrypt(
                jose.deserialize_compact(legacy_legacy_temp_ver), jwk)

        self.assertEqual(legacy_mock.call_count, 1)
        self.assertEqual(spec_mock.call_count, 0)
        self.assertEqual(jwt.claims, claims)
        expected_header = {
            'alg': 'RSA-OAEP',
            'enc': 'A128CBC-HS256',
        }
        self.assertEqual(jwt.header, expected_header)
        self.assertNotIn('__v', jwt.header)
Ejemplo n.º 13
0
    def test_jwe_decrypt_legacy_v1_without_temp_ver(self):
        jwk = {'k': PRIVATE_KEY}

        legacy_patch = mock.patch.object(
            jose, 'legacy_decrypt', wraps=jose.legacy_decrypt
        )
        spec_patch = mock.patch.object(
            jose, 'spec_compliant_decrypt', wraps=jose.spec_compliant_decrypt
        )

        legacy_legacy_temp_ver = jose.serialize_compact(
            legacy_encrypt(claims, jwk)
        )

        with legacy_patch as legacy_mock, spec_patch as spec_mock:
            jwt = jose.decrypt(
                jose.deserialize_compact(legacy_legacy_temp_ver), jwk)

        self.assertEqual(legacy_mock.call_count, 1)
        self.assertEqual(spec_mock.call_count, 0)
        self.assertEqual(jwt.claims, claims)
        expected_header = {
            'alg': 'RSA-OAEP',
            'enc': 'A128CBC-HS256',
        }
        self.assertEqual(jwt.header, expected_header)
        self.assertNotIn('__v', jwt.header)
Ejemplo n.º 14
0
 def test_jwe_ignores_expired_token_if_validate_claims_is_false(self):
     claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5}
     et = jose.serialize_compact(
         jose.spec_compliant_encrypt(claims, rsa_pub_key))
     jose.spec_compliant_decrypt(jose.deserialize_compact(et),
                                 rsa_priv_key,
                                 validate_claims=False)
Ejemplo n.º 15
0
 def __init__(self, claims, logger, config, alg = 'RS256'):
     self._logger = logger
     self._config = config
     self._request_result = None
     self._api_key = None
     self._claims = claims
     jws = jose.sign(claims, self._config.keys.private_key.jwk, alg=alg)
     self.signed_claims = {'v1': jose.serialize_compact(jws)}
Ejemplo n.º 16
0
    def test_jws_sym(self):
        algs = ('HS256', 'HS384', 'HS512',)
        jwk = {'k': 'password'}

        for alg in algs:
            st = jose.serialize_compact(jose.sign(claims, jwk, alg=alg))
            jwt = jose.verify(jose.deserialize_compact(st), jwk, alg)

            self.assertEqual(jwt.claims, claims)
Ejemplo n.º 17
0
    def test_jwe_compression(self):
        local_claims = copy(claims)

        for v in xrange(1000):
            local_claims['dummy_' + str(v)] = '0' * 100

        jwe = jose.serialize_compact(jose.encrypt(local_claims, rsa_pub_key))
        _, _, _, uncompressed_ciphertext, _ = jwe.split('.')

        jwe = jose.serialize_compact(jose.encrypt(local_claims, rsa_pub_key,
            compression='DEF'))
        _, _, _, compressed_ciphertext, _ = jwe.split('.')

        self.assertTrue(len(compressed_ciphertext) <
                len(uncompressed_ciphertext))

        jwt = jose.decrypt(jose.deserialize_compact(jwe), rsa_priv_key)
        self.assertEqual(jwt.claims, local_claims)
Ejemplo n.º 18
0
    def test_jws_sym(self):
        algs = ('HS256', 'HS384', 'HS512',)
        jwk = {'k': 'password'}

        for alg in algs:
            st = jose.serialize_compact(jose.sign(claims, jwk, alg=alg))
            jwt = jose.verify(jose.deserialize_compact(st), jwk, alg)

            self.assertEqual(jwt.claims, claims)
Ejemplo n.º 19
0
    def test_jwe_add_header(self):
        add_header = {'foo': 'bar'}

        for (alg, jwk), enc in product(self.algs, self.encs):
            et = jose.serialize_compact(
                jose.encrypt(claims, rsa_pub_key, add_header=add_header))
            jwt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)

            self.assertEqual(jwt.header['foo'], add_header['foo'])
Ejemplo n.º 20
0
    def test_jwe_compression(self):
        local_claims = copy(claims)

        for v in xrange(1000):
            local_claims['dummy_' + str(v)] = '0' * 100

        jwe = jose.serialize_compact(jose.encrypt(local_claims, rsa_pub_key))
        _, _, _, uncompressed_ciphertext, _ = jwe.split('.')

        jwe = jose.serialize_compact(
            jose.encrypt(local_claims, rsa_pub_key, compression='DEF'))
        _, _, _, compressed_ciphertext, _ = jwe.split('.')

        self.assertTrue(
            len(compressed_ciphertext) < len(uncompressed_ciphertext))

        jwt = jose.decrypt(jose.deserialize_compact(jwe), rsa_priv_key)
        self.assertEqual(jwt.claims, local_claims)
Ejemplo n.º 21
0
    def test_jwe_add_header(self):
        add_header = {'foo': 'bar'}

        for (alg, jwk), enc in product(self.algs, self.encs):
            et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key,
                add_header=add_header))
            jwt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)

            self.assertEqual(jwt.header['foo'], add_header['foo'])
Ejemplo n.º 22
0
    def test_jwe_invalid_dates_error(self):
        claims = {'exp': time() - 5}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
            self.fail() # expecting expired token
        except ValueError:
            pass


        claims = {'nbf': time() + 5}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
            self.fail() # expecting not valid yet
        except ValueError:
            pass
Ejemplo n.º 23
0
    def test_version1(self):
        bad_key = {'k': RSA.generate(2048).exportKey('PEM')}

        jwe = legacy_encrypt(claims, rsa_pub_key, version=1)
        token = jose.serialize_compact(jwe)

        jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key)

        self.assertEqual(jwt.claims, claims)
        self.assertEqual(jwt.header.get(jose._TEMP_VER_KEY), 1)
Ejemplo n.º 24
0
    def test_version1(self):
        bad_key = {'k': RSA.generate(2048).exportKey('PEM')}

        jwe = legacy_encrypt(claims, rsa_pub_key, version=1)
        token = jose.serialize_compact(jwe)

        jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key)

        self.assertEqual(jwt.claims, claims)
        self.assertEqual(jwt.header.get(jose._TEMP_VER_KEY), 1)
Ejemplo n.º 25
0
def encrypt_fluffy(msgtype, key, groupkey="", keyid=""):
    #print "MsgType: ", msgtype
    #print "GroupKey: ", groupkey
    #print "KeyId: ", keyid	
    print '*****************************'
    print 'Performing Encryption on a ' + msgtype
    print '*****************************'

    msg = gsk.Gsk(msgtype, groupkey, keyid)
    s = gsk.printGsk(msg)
    j_obj = json.loads(s)
    
    #add and map fluffy claims into jwt claims
    pyld = map_payload(j_obj)
   
    print "Pretty output: " 
    print json.dumps(pyld, indent=4)
    print "--------------"

    j_obj['header']['msgtyp'] = msgtype
    
    header = {
            'kid': str(j_obj['payload']['keydata']['kid']),
            'typ': str(j_obj['header']['msgtyp']) + ' ' + str(j_obj['header']['pvno']),
	    'cty': j_obj['payload']['type'],
            }
    aad = {
            'aut': j_obj['security']['authtime'],
            'non': j_obj['security']['nonce'],
            'snu': j_obj['security']['seqnum']
            }
    
    header['aad'] = aad

    jwe = jose.encrypt(pyld, '', add_header = header, alg='dir', dir_key=str(key))

    print(jose.serialize_compact(jwe))
    f = open ("ENC_" + header['typ'] +".txt", "w")
    f.write(jose.serialize_compact(jwe));
    f.close();
Ejemplo n.º 26
0
    def test_jwe_expired_error_with_exp_claim(self):
        claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
            self.fail()  # expecting expired token
        except jose.Expired as e:
            pass

        self.assertEquals(
            e.args[0], 'Token expired at {}'.format(
                jose._format_timestamp(claims[jose.CLAIM_EXPIRATION_TIME])))
Ejemplo n.º 27
0
    def test_jwe_not_yet_valid_error_with_nbf_claim(self):
        claims = {jose.CLAIM_NOT_BEFORE: int(time()) + 5}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
            self.fail()  # expecting not valid yet
        except jose.NotYetValid as e:
            pass

        self.assertEquals(
            e.args[0], 'Token not valid until {}'.format(
                jose._format_timestamp(claims[jose.CLAIM_NOT_BEFORE])))
Ejemplo n.º 28
0
def auth_master_login_jwt(event, context):
    """AWS_LAMBDA:auth_master_login_jwt
    Authenticate a valid code/password combination.

    :param code: User identification code.
    :type code: str.
    :param password: User password.
    :type password: str.
    :returns: str -- Authentication token used for API calls.

    """
    try:
        #generate password hash for comparison, a slow hash with multiple iterations is used to difficult attacks
        binary_hash = hashlib.pbkdf2_hmac('sha256',
                                          event['body-json']['password'],
                                          DYN_CONF['MASTER_SALT'], 10000)
        hashed_password = binascii.hexlify(binary_hash)

        #compare results
        if hashed_password == DYN_CONF['MASTER_PASSWORD']:
            #generate token
            now_time = time.time()
            end_time = time.time() + 31104000
            claims = {
                'exp': end_time,
                'nbf': now_time,
                'iss': 'medpass-aws',
                'aud': 'webclient',
                'iat': now_time,
                'type': 'MASTER',
                'id': 'MASTER'
            }

            jwe_token = jose.encrypt(claims, {'k': PUBLIC_KEY},
                                     enc='A256CBC-HS512')
            auth_token = jose.serialize_compact(jwe_token)

            output = {
                'status': 'success',
                'Authorization': auth_token,
                'type': 'MASTER'
            }
        else:
            output = {'status': 'error', 'message': 'failed login'}

    except:
        LOGGER.error(traceback.print_exc())
        output = {'status': 'error', 'message': 'failed login'}

    return output
Ejemplo n.º 29
0
    def test_jwe_expired_error_with_exp_claim(self):
        claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
            self.fail()  # expecting expired token
        except jose.Expired as e:
            pass

        self.assertEquals(
            e.args[0],
            'Token expired at {}'.format(
                jose._format_timestamp(claims[jose.CLAIM_EXPIRATION_TIME])
            )
        )
Ejemplo n.º 30
0
    def test_jwe_not_yet_valid_error_with_nbf_claim(self):
        claims = {jose.CLAIM_NOT_BEFORE: int(time()) + 5}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
            self.fail()  # expecting not valid yet
        except jose.NotYetValid as e:
            pass

        self.assertEquals(
            e.args[0],
            'Token not valid until {}'.format(
                jose._format_timestamp(claims[jose.CLAIM_NOT_BEFORE])
            )
        )
Ejemplo n.º 31
0
    def test_jwe_adata(self):
        adata = '42'
        for (alg, jwk), enc in product(self.algs, self.encs):
            et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key,
                adata=adata))
            jwt = jose.legacy_decrypt(jose.deserialize_compact(et), rsa_priv_key,
                    adata=adata)

            # make sure signatures don't match when adata isn't passed in
            try:
                hdr, dt = jose.legacy_decrypt(jose.deserialize_compact(et),
                    rsa_priv_key)
                self.fail()
            except jose.Error as e:
                self.assertEqual(e.message, 'Mismatched authentication tags')

            self.assertEqual(jwt.claims, claims)
Ejemplo n.º 32
0
    def test_jwe(self):
        bad_key = {'k': RSA.generate(2048).exportKey('PEM')}

        jwe = legacy_encrypt(claims, rsa_pub_key)
        token = jose.serialize_compact(jwe)

        jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key)

        self.assertEqual(jwt.claims, claims)
        self.assertNotIn(jose._TEMP_VER_KEY, claims)

        # invalid key
        try:
            jose.decrypt(jose.deserialize_compact(token), bad_key)
            self.fail()
        except jose.Error as e:
            self.assertEqual(e.message, 'Incorrect decryption.')
Ejemplo n.º 33
0
    def test_jwe(self):
        bad_key = {'k': RSA.generate(2048).exportKey('PEM')}

        jwe = legacy_encrypt(claims, rsa_pub_key)
        token = jose.serialize_compact(jwe)

        jwt = jose.decrypt(jose.deserialize_compact(token), rsa_priv_key)

        self.assertEqual(jwt.claims, claims)
        self.assertNotIn(jose._TEMP_VER_KEY, claims)

        # invalid key
        try:
            jose.decrypt(jose.deserialize_compact(token), bad_key)
            self.fail()
        except jose.Error as e:
            self.assertEqual(e.message, 'Incorrect decryption.')
Ejemplo n.º 34
0
    def test_jwe_adata(self):
        adata = '42'
        for (alg, jwk), enc in product(self.algs, self.encs):
            et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key,
                adata=adata))
            jwt = jose.decrypt(jose.deserialize_compact(et), rsa_priv_key,
                    adata=adata)

            # make sure signaures don't match when adata isn't passed in
            try:
                hdr, dt = jose.decrypt(jose.deserialize_compact(et),
                    rsa_priv_key)
                self.fail()
            except jose.Error as e:
                self.assertEqual(e.message, 'Mismatched authentication tags')

            self.assertEqual(jwt.claims, claims)
Ejemplo n.º 35
0
    def test_jwe_expired_error_with_iat_claim(self):
        expiry_seconds = 10
        claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et),
                         rsa_priv_key,
                         expiry_seconds=expiry_seconds)
            self.fail()  # expecting expired token
        except jose.Expired as e:
            pass

        expiration_time = claims[jose.CLAIM_ISSUED_AT] + expiry_seconds
        self.assertEquals(
            e.args[0], 'Token expired at {}'.format(
                jose._format_timestamp(expiration_time)))
Ejemplo n.º 36
0
    def test_jwe_expired_error_with_iat_claim(self):
        expiry_seconds = 10
        claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        try:
            jose.decrypt(jose.deserialize_compact(et), rsa_priv_key,
                expiry_seconds=expiry_seconds)
            self.fail()  # expecting expired token
        except jose.Expired as e:
            pass

        expiration_time = claims[jose.CLAIM_ISSUED_AT] + expiry_seconds
        self.assertEquals(
            e.args[0],
            'Token expired at {}'.format(
                jose._format_timestamp(expiration_time)
            )
        )
Ejemplo n.º 37
0
    def test_mfa_add_request(self):
        """
        Test basic ability to parse an mfa_add request.

        :return:
        """
        nonce = os.urandom(10)
        claims = {
            'version': 1,
            'token_type': 'OATH',
            'nonce': nonce.encode('hex'),
            'OATH': {
                'digits': 6,
                'issuer': 'TestIssuer',
                'account': '*****@*****.**',
            }
        }
        priv_jwk = self.config.keys.private_key.jwk
        server_jwk = self.config.keys.lookup_by_name("self").jwk
        jwe = self._sign_and_encrypt(claims, priv_jwk, server_jwk)
        serialized = jose.serialize_compact(jwe)

        response = self.request('/mfa_add',
                                request=serialized,
                                return_error=True)

        jwt = self._decrypt_and_verify(response.body[0], priv_jwk, server_jwk)

        response_claims = jwt.claims

        self.logger.debug("Response claims:\n{!s}".format(
            pprint.pformat(response_claims)))

        self.assertEqual(
            response_claims, {
                u'nonce': nonce.encode('hex'),
                u'reason': u'No API Key found for OATH AEAD service',
                u'status': u'FAIL',
                u'version': 1,
            })
Ejemplo n.º 38
0
    def send_request(self, url, name, apikey):
        """
        Encrypt the claims and POST it to url.

        :param url: The URL to POST the data to
        :param name: The HTTP parameter name to put the data in
        :param apikey: API Key to encrypt data with before posting
        :return:

        :type url: str | unicode
        :type apikey: eduid_api.keystore.APIKey
        """
        self._logger.debug("Encrypting signed request using {!r}".format(apikey))
        if not apikey.keytype == 'jose':
            raise EduIDAPIError("Non-jose API key unusuable with send_request")
        self._api_key = apikey
        jwe = jose.encrypt(self.signed_claims, apikey.jwk)
        data = {name: jose.serialize_compact(jwe)}
        self._logger.debug("Sending signed and encrypted request to {!r}".format(url))
        self._request_result = requests.post(url, data = data)
        self._logger.debug("Result of request: {!r}".format(self._request_result))
        return self._request_result
Ejemplo n.º 39
0
def get_freja_state(user):
    current_app.logger.debug('Getting state for user {!s}.'.format(user))
    try:
        proofing_state = current_app.proofing_statedb.get_state_by_eppn(
            user.eppn)
        expire_time = current_app.config['FREJA_EXPIRE_TIME_HOURS']
        if helpers.is_proofing_state_expired(proofing_state, expire_time):
            current_app.proofing_statedb.remove_state(proofing_state)
            current_app.stats.count(name='freja.proofing_state_expired')
            raise DocumentDoesNotExist(reason='freja proofing state expired')
    except DocumentDoesNotExist:
        return {}
    # Return request data
    current_app.logger.debug(
        'Returning request data for user {!s}'.format(user))
    current_app.stats.count(name='freja.proofing_state_returned')
    opaque_data = helpers.create_opaque_data(proofing_state.nonce,
                                             proofing_state.token)
    valid_until = helpers.get_proofing_state_valid_until(
        proofing_state, expire_time)
    request_data = {
        "iarp": current_app.config['FREJA_IARP'],
        "exp": int(valid_until.astimezone(UTC()).strftime('%s')) *
        1000,  # Milliseconds since 1970 in UTC
        "proto": current_app.config['FREJA_RESPONSE_PROTOCOL'],
        "opaque": opaque_data
    }
    jwk = {'k': current_app.config['FREJA_JWK_SECRET'].decode('hex')}
    jws_header = {
        'alg': current_app.config['FREJA_JWS_ALGORITHM'],
        'kid': current_app.config['FREJA_JWS_KEY_ID'],
    }
    jws = jose.sign(request_data,
                    jwk,
                    add_header=jws_header,
                    alg=current_app.config['FREJA_JWS_ALGORITHM'])
    return {'iaRequestData': jose.serialize_compact(jws)}
Ejemplo n.º 40
0
 def test_jwe_ignores_expired_token_if_validate_claims_is_false(self):
     claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) - 5}
     et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))
     jose.decrypt(jose.deserialize_compact(et), rsa_priv_key,
         validate_claims=False)
Ejemplo n.º 41
0
def login(event, context):
    """AWS_LAMBDA:auth_login_jwt
    Authenticate a valid email/password combination.

    :param email: User identification email.
    :type email: str.
    :param password: User password.
    :type password: str.
    :returns: str -- Authentication token used for API calls.

    """

    try:
        #request user data (password, active_status, salt and id) from user services
        login_data = 'email' in event['body-json'] and {
            'email': event['body-json']['email']
        } or {
            'cpf': event['body-json']['cpf']
        }

        response = LAMBDA_CLIENT.invoke(
            FunctionName=
            'arn:aws:lambda:us-west-2:566614558620:function:user_get_credentials:'
            + ENVIRONMENT,
            Qualifier=ENVIRONMENT,
            InvocationType='RequestResponse',
            Payload=json.dumps(login_data),
            LogType='None')

        payload = json.loads(response['Payload'].read())
        if response['StatusCode'] == 200 and payload['status'] == 'success':
            #if the user provided a captcha verify it works
            approved_captcha = False
            if 'g-captcha-response' in event[
                    'body-json'] and payload['failed_login_attempts'] >= 3:
                #validate recaptcha
                google_response = requests.post(
                    'https://www.google.com/recaptcha/api/siteverify',
                    data={
                        'secret': '6LdZNSgUAAAAAE8caj0ckJluAdJ3mGPHrE6kZW_n',
                        'response': event['body-json']['g-captcha-response'],
                        'remoteip': event['source-ip']
                    }).json()
                approved_captcha = google_response['success']

            #verify that the user is not locked or did provide a captcha
            if payload['failed_login_attempts'] < 3 or approved_captcha:
                #generate password hash for comparison, a slow hash with multiple iterations is used to difficult attacks
                binary_hash = hashlib.pbkdf2_hmac(
                    'sha256', event['body-json']['password'], payload['salt'],
                    10000)
                hashed_password = binascii.hexlify(binary_hash)

                if 'token_annonymous' in event['body-json']:
                    annonymous_login = event['body-json']['token_annonymous'] == payload['token_annonymous'] and\
                                       True or False
                else:
                    annonymous_login = False

                #compare results and verify if user is active
                if (hashed_password == payload['password']
                        and payload['active']) or annonymous_login:

                    #clear old password reset tokens
                    USER_TABLE.update_item(
                        Key={'user_id': payload['user_id']},
                        UpdateExpression=
                        'SET password_token=:password_token, failed_login_attempts=:failed_login_attempts',
                        ExpressionAttributeValues={
                            ':password_token': {},
                            ':failed_login_attempts': 0
                        })

                    #generate token
                    now_time = time.time()
                    end_time = time.time() + 31104000
                    claims = {
                        'exp': end_time,
                        'nbf': now_time,
                        'iss': 'medpass-aws',
                        'aud': 'webclient',
                        'iat': now_time,
                        'type': payload['type'],
                        'id': payload['user_id']
                    }

                    jwe_token = jose.encrypt(claims, {'k': PUBLIC_KEY},
                                             enc='A256CBC-HS512')
                    auth_token = jose.serialize_compact(jwe_token)

                    output = {
                        'status': 'success',
                        'Authorization': auth_token,
                        'type': payload['type']
                    }

                    #profile dependent information
                    if 'profile_url' in payload:
                        output['profile_url'] = payload['profile_url']

                    #type dependent information
                    if payload['type'] == 'USER':
                        pendencies_response = REPORT_TABLE.get_item(
                            Key={'user_id': payload['user_id']},
                            ProjectionExpression='pendencies')
                        if 'Item' in pendencies_response:
                            output['pendencies'] = False
                        else:
                            output['pendencies'] = True
                    elif payload['type'] == 'PRE-MEDIC':
                        #warn user if data is being revisited
                        user_response = USER_TABLE.get_item(
                            Key={'user_id': payload['user_id']},
                            ProjectionExpression='profile')['Item']
                        if 'profile' in user_response:
                            output['sent'] = True
                        else:
                            output['sent'] = False
                        output['pendencies'] = True
                    elif payload['type'] == 'MEDIC':
                        output['pendencies'] = False

                else:
                    #include a failed login attempt to user
                    USER_TABLE.update_item(
                        Key={'user_id': payload['user_id']},
                        UpdateExpression='ADD failed_login_attempts :one',
                        ExpressionAttributeValues={':one': 1})
                    LOGGER.info('Incorrect login attempt at email: "' +
                                event['body-json']['email'] + '".')
                    output = {'status': 'error', 'message': 'failed login'}
            else:
                LOGGER.info('Locked out user login attempt at email: "' +
                            event['body-json']['email'] + '"')
                output = {
                    'status': 'captcha',
                    'message': 'locked out user need to validate captcha'
                }
        else:
            LOGGER.error("Failed to request user credential." +
                         payload['message'])
            output = {'status': 'error', 'message': 'failed login'}

    except:
        LOGGER.error(traceback.print_exc())
        output = {'status': 'error', 'message': 'failed login'}

    return output
Ejemplo n.º 42
0
mtb_key = RSA.generate(2048)

# JWE encode - encrypt info using the public key MtB
info = {'company': 'ACME', 'author': 'pepe', 'experiment': 'ID'}
print "\n\t START"
print "\t    |"
print "\t< Secret information:" + str(info) + " >"
print "\t    |"
print "\t< Encrypt information (information, MtB public key) >"
print "\t    |"
try:
    pub_jwk = {'k': mtb_key.publickey().exportKey('PEM')}
    jwe = jose.encrypt(info, pub_jwk)
    # issue the compact serialized version to the clients. this is what will be
    # transported along with requests to target systems.
    secret = jose.serialize_compact(jwe)
    print "\t   OK"
    print "\t    |"
except:
    print "\tError encrypting information! "
    e = sys.exc_info()[0]
    print "Error: %s" % e
    exit()

# JWT sign - Sign token using the private key External
claims = {
    'from': 'mindthebyte',
    'exp': int(time()) + 3600,
    'secret': secret,
}
print "\t< claims to be signed: " + str(claims)
Ejemplo n.º 43
0
 def _sign_and_encrypt(self, claims, priv_jwk, server_jwk, alg = 'RS256'):
     jws = jose.sign(claims, priv_jwk, alg=alg)
     signed_claims = {'v1': jose.serialize_compact(jws)}
     jwe = jose.encrypt(signed_claims, server_jwk)
     return jwe
Ejemplo n.º 44
0
 def test_jwe_no_error_with_nbf_claim(self):
     claims = {jose.CLAIM_NOT_BEFORE: int(time()) - 5}
     et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))
     jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
Ejemplo n.º 45
0
    def test_jwe_no_error_with_iat_claim(self):
        claims = {jose.CLAIM_ISSUED_AT: int(time()) - 15}
        et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))

        jose.decrypt(jose.deserialize_compact(et), rsa_priv_key,
            expiry_seconds=20)
Ejemplo n.º 46
0
 def _sign_and_encrypt(self, claims, priv_jwk, server_jwk, alg='RS256'):
     jws = jose.sign(claims, priv_jwk, alg=alg)
     signed_claims = {'v1': jose.serialize_compact(jws)}
     jwe = jose.encrypt(signed_claims, server_jwk)
     return jwe
Ejemplo n.º 47
0
 def test_jwe_no_error_with_nbf_claim(self):
     claims = {jose.CLAIM_NOT_BEFORE: int(time()) - 5}
     et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))
     jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
Ejemplo n.º 48
0
 def test_jwe_no_error_with_exp_claim(self):
     claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) + 5}
     et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))
     jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)
    # key = b"""-----BEGIN PRIVATE KEY-----
    # MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgsegINAr5xcE48BiD
    # yfXjsfQmEk1ReGtD7bSuKsKx04CgCgYIKoZIzj0DAQehRANCAASauMCp36D8FOF1
    # 5OGI1+fe5oeRoCbY5yGQ2Jk0Gi9P92ksyvC8LK7JDqtzKfEf18UsScYc+NWffEtt
    # v413G73q
    # -----END PRIVATE KEY-----"""
    # k = {'k': 'password'}
    #
    # signed = jws.sign(data, k, algorithm='ES256')
    # print(signed)
    # data = jws.verify(signed, k, algorithms='ES256')
    # print(data)



    jwk = {'k': 'password'}

    jws = jose.sign(data, jwk, alg='HS256')
    # JWS(header='eyJhbGciOiAiSFMyNTYifQ',
    # payload='eyJpc3MiOiAiaHR0cDovL3d3dy5leGFtcGxlLmNvbSIsICJzdWIiOiA0MiwgImV4cCI6IDEzOTU2NzQ0Mjd9',
    # signature='WYApAiwiKd-eDClA1fg7XFrnfHzUTgrmdRQY4M19Vr8')

    # issue the compact serialized version to the clients. this is what will be
    # transported along with requests to target systems.

    jwt = jose.serialize_compact(jws)
    # 'eyJhbGciOiAiSFMyNTYifQ.eyJpc3MiOiAiaHR0cDovL3d3dy5leGFtcGxlLmNvbSIsICJzdWIiOiA0MiwgImV4cCI6IDEzOTU2NzQ0Mjd9.WYApAiwiKd-eDClA1fg7XFrnfHzUTgrmdRQY4M19Vr8'

    jose.verify(jose.deserialize_compact(jwt), jwk, 'HS256')
    # JWT(header={u'alg': u'HS256'}, claims={u'iss': u'http://www.example.com', u'sub': 42, u'exp': 1395674427})
Ejemplo n.º 50
0
 def test_jwe_no_error_with_exp_claim(self):
     claims = {jose.CLAIM_EXPIRATION_TIME: int(time()) + 5}
     et = jose.serialize_compact(jose.encrypt(claims, rsa_pub_key))
     jose.decrypt(jose.deserialize_compact(et), rsa_priv_key)