def test_rs256_signature2(self): rsa256_token_header = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vd2ViaG9vay5zaXRlLzQ4MjAzNjZlLTRhY2YtNDQ5Mi04YjhiLTJmZDRlMGIyNmJlMiJ9" rsa256_token_payload = "eyJ1c2VyIjoiYWRtaW4ifQ" rsa256_token_signature = "lJSuLrAA6goQ5f2AXYXV25xZ66yuE_aRQlRpTpirSbVN7SxMOFooPkPIywejg1F5F89vFmibY_ATqu5bvyFjX1dIbb-PPFBSyB3AwgeLGq_UXSyRjf2WEw-UWYxq00l6b3f8qOI2nuS8Ea3iy5xfGqc6geUXXtJZN02o-QWoZ0qZ6vECrL3__dwbFQDLdgIw_TPYzrVjjLk69islxE8Vv9G5ZOAtwFZrzcZuTQTMTRJrpMNstuX4gYeJOu7VUWzKoQjT4D_PUX4mB_Sn80JyVMHPjcse_ZtHSkWgse86Gx0-Tmv7B7tqTXNtNfugctrkUxwZM2b0k4XYErnycXK-Bg" rsa_token_ser = ".".join([ rsa256_token_header, rsa256_token_payload, rsa256_token_signature ]) rsa_token = TestJWT.TestJWT.deserialize(rsa_token_ser) self.assertEqual("RS256", rsa_token.header['alg']) self.assertEqual("JWT", rsa_token.header['typ']) self.assertEqual( "https://webhook.site/4820366e-4acf-4492-8b8b-2fd4e0b26be2", rsa_token.header['jku']) self.assertEqual("admin", rsa_token.payload['user']) pk = load_pem_private_key(utils.read_pem_file("./keys/pk1.pem"), None, default_backend()) pubkey = load_pem_public_key(utils.read_pem_file("./keys/pubkey1.pem"), default_backend()) signature = rsa_token.compute_signature(pk) self.assertEqual(rsa256_token_signature, utils.force_unicode(signature)) self.assertTrue( rsa_token.verify_signature(pubkey, utils.base64url_decode(signature))) self.assertTrue( rsa_token.verify_signature( pubkey, utils.base64url_decode(rsa256_token_signature)))
def test_rsa256_jwks_to_pubkey_multiple_keys_duplicate(self): n = b'oGV0P-rgmJd8qEu_0c1YYjNLt8RjBmGcy4X0RXK3lEfHjGWJggkaHFY_zP-m0uWijPl7ASq1gf7cL7w801pLXB_vUqxPyl7rP8ul_4j_ghWjGrl58yNyRBcIVh18HICCqAduvbasehRstSv0JSAP6VArEcpLGOnHI0IILclWjFQf35A4fbsVYbqs2ZUhP7C5Jq36SA5GRqq4QTKuG0YP4t1j9CEEIQUldwHcuoMzBH4GOP0eZd1EkhTw8uQvQeHtao-J0Mfh-ljFC2Rcvoysx6HwGVZIg2DlGiWttYCWzUvc5q2doFIJ640gO9KLFeOC5ebGTwnzJ_Z5jCaim2Eomw' e = b'AQAB' n1 = "yeNlzlub94YgerT030codqEztjfU_S6X4DbDA_iVKkjAWtYfPHDzz_sPCT1Axz6isZdf3lHpq_gYX4Sz-cbe4rjmigxUxr-FgKHQy3HeCdK6hNq9ASQvMK9LBOpXDNn7mei6RZWom4wo3CMvvsY1w8tjtfLb-yQwJPltHxShZq5-ihC9irpLI9xEBTgG12q5lGIFPhTl_7inA1PFK97LuSLnTJzW0bj096v_TMDg7pOWm_zHtF53qbVsI0e3v5nmdKXdFf9BjIARRfVrbxVxiZHjU6zL6jY5QJdh1QCmENoejj_ytspMmGW7yMRxzUqgxcAqOBpVm0b-_mW3HoBdjQ" jwks = { 'keys': [{ 'alg': "RS256", 'kty': "RSA", 'kid': "test_key", 'e': e, 'n': n1 }, { 'alg': "RS256", 'kty': "RSA", 'kid': "test_key", 'e': e, 'n': n }, { 'alg': "RS256", 'kty': "RSA", 'kid': "kez123", 'e': e, 'n': n1 }] } expected_pubkey: RSAPublicKey = load_pem_public_key( utils.read_pem_file("./keys/pubkey1.pem"), default_backend()) pubkey: RSAPublicKey = rsa_jwks_to_pubkey(jwks, 'test_key') self.assertEqual(expected_pubkey.public_numbers().e, pubkey.public_numbers().e) self.assertEqual(expected_pubkey.public_numbers().n, pubkey.public_numbers().n)
def test_attack_pubkey_deception_jwk(self): rsa256_token_header = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9" rsa256_token_payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" rsa256_token_signature = "ZR8EJ-ssd7b3Z9ZrCODkK_tJvOVXNZbcUn_FQAbLlKjPdEkNNCP_i5h84QfRXA8cWu1Z83UOb25Oogw0GIE9k-Q4AJO-BwEC2muHKRdzgHGrO6_2abeFJxAZapSf4ww39UlGzYX22b2kRYECLmsVaa0NV1KyQIf147h460wDGDr1wd2OCvUZXYULA_vzzRo3HHX440XOx_CnBvrR7shqnIjOLycEG61Ganq6oJsujVXHTQUtKdNB1Amu9NEQRRQzYWSTLuUMwV9mJnCuyr9bWp5srd3VPOC1bMXU2UgJiauw8eYu_w2_bbgZOn0jwajiygkfuJXNJGi8k_09sJmJ0w" rsa_token_ser = ".".join([ rsa256_token_header, rsa256_token_payload, rsa256_token_signature ]) rsa_token = TestJWT.deserialize(rsa_token_ser) self.assertEqual("RS256", rsa_token.get_algorithm()) self.assertEqual("JWT", rsa_token.header['typ']) self.assertEqual(2, len(rsa_token.header)) self.assertEqual("1234567890", rsa_token.payload['sub']) self.assertEqual("John Doe", rsa_token.payload['name']) self.assertEqual(1516239022, rsa_token.payload['iat']) self.assertEqual(3, len(rsa_token.payload)) pk: RSAPrivateKey = load_pem_private_key( utils.read_pem_file("./keys/pk1.pem"), None, default_backend()) pubkey: RSAPublicKey = pk.public_key() self.assertTrue( rsa_token.verify_signature( pubkey, utils.base64url_decode(rsa256_token_signature))) rsa_token_jwk = TestJWT.deserialize(rsa_token_ser) kid = "my_own_key" attack = Attack(rsa_token_ser) attack.attack_pubkey_deception_jwk(pk, kid) payloads = attack.payloads rsa_token_jwk = TestJWT.deserialize( payloads['attack_pubkey_deception_jwk']) self.assertEqual("RS256", rsa_token_jwk.get_algorithm()) self.assertEqual("JWT", rsa_token_jwk.header['typ']) self.assertEqual("RSA", rsa_token_jwk.header['jwk']['kty']) self.assertEqual(kid, rsa_token_jwk.header['jwk']['kid']) self.assertEqual("sig", rsa_token_jwk.header['jwk']['use']) e = pk.public_key().public_numbers().e n = pk.public_key().public_numbers().n expected_n = utils.force_unicode( utils.base64url_encode( n.to_bytes((n.bit_length() + 7) // 8, byteorder='big'))) expected_e = utils.force_unicode( utils.base64url_encode( e.to_bytes((e.bit_length() + 7) // 8, byteorder='big'))) self.assertEqual(expected_n, rsa_token_jwk.header['jwk']['n']) self.assertEqual(expected_e, rsa_token_jwk.header['jwk']['e']) self.assertEqual(3, len(rsa_token_jwk.header)) self.assertEqual("1234567890", rsa_token_jwk.payload['sub']) self.assertEqual("John Doe", rsa_token_jwk.payload['name']) self.assertEqual(1516239022, rsa_token_jwk.payload['iat']) self.assertEqual(3, len(rsa_token_jwk.payload)) rsa_token_jwk_signature = rsa_token_jwk.compute_signature(pk) self.assertTrue( rsa_token_jwk.verify_signature( pubkey, utils.base64url_decode(rsa_token_jwk_signature))) expected_signature = "jheDPqm8kxisAUcuDX-gHdTEIQDan_qRphZddj2VkcW-wJbVARly1Wzaw4of96Dl0xJXqJBV_kKG5UmmEiiEjQWUZzY4_XuZmI_STEf7FvVe_OPbN6fmyzGJQZSJVaoXTMYw8_yhQ1fIip6ctGVKrt6752RolratwDsYVZawQ1J9V3WIioPvXjQoyEGbothy7yOxemZXB71SMcQ-mmLKc8v0mirA8kyR8Wg0lw_JkRVRbViItn6SMFg2_Fuf12P1rkxx2qo3BVPzvgz1Nln4U8kFe2HGdtpc2IMTrAvzO0hOhc8cBe2-9HZJAFdGd_6SPhkp1VVlx-qTIL2y0EqH4Q" self.assertEqual(expected_signature, utils.force_unicode(rsa_token_jwk_signature))
def test_attack_pubkey_deception_jku(self): rsa256_token_header = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9" rsa256_token_payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" rsa256_token_signature = "ZR8EJ-ssd7b3Z9ZrCODkK_tJvOVXNZbcUn_FQAbLlKjPdEkNNCP_i5h84QfRXA8cWu1Z83UOb25Oogw0GIE9k-Q4AJO-BwEC2muHKRdzgHGrO6_2abeFJxAZapSf4ww39UlGzYX22b2kRYECLmsVaa0NV1KyQIf147h460wDGDr1wd2OCvUZXYULA_vzzRo3HHX440XOx_CnBvrR7shqnIjOLycEG61Ganq6oJsujVXHTQUtKdNB1Amu9NEQRRQzYWSTLuUMwV9mJnCuyr9bWp5srd3VPOC1bMXU2UgJiauw8eYu_w2_bbgZOn0jwajiygkfuJXNJGi8k_09sJmJ0w" rsa_token_ser = ".".join([ rsa256_token_header, rsa256_token_payload, rsa256_token_signature ]) rsa_token = TestJWT.deserialize(rsa_token_ser) self.assertEqual("RS256", rsa_token.get_algorithm()) self.assertEqual("JWT", rsa_token.header['typ']) self.assertEqual(2, len(rsa_token.header)) self.assertEqual("1234567890", rsa_token.payload['sub']) self.assertEqual("John Doe", rsa_token.payload['name']) self.assertEqual(1516239022, rsa_token.payload['iat']) self.assertEqual(3, len(rsa_token.payload)) pk: RSAPrivateKey = load_pem_private_key( utils.read_pem_file("./keys/pk1.pem"), None, default_backend()) pubkey: RSAPublicKey = pk.public_key() self.assertTrue( rsa_token.verify_signature( pubkey, utils.base64url_decode(rsa256_token_signature))) rsa_token_jwk = TestJWT.deserialize(rsa_token_ser) kid = "my_own_key" jku = "https://webhook.site/4820366e-4acf-4492-8b8b-2fd4e0b26be2" attack = Attack(rsa_token_ser) attack.attack_pubkey_deception_jku(pk, jku, jwt=None, kid=kid) ser_rsa_token_jwk = attack.payloads['attack_pubkey_deception_jku'] rsa_token_jwk = TestJWT.deserialize(ser_rsa_token_jwk) jku_signature = TestJWT.split_jwt(ser_rsa_token_jwk)[2] expected_signature = "e5xKg2xAMXeDD2BLCYAaSueV3wuKMeqSl0YPXaL1y84Z2uDZiwLGLUV92Pmcl7qfhWjJtJQ-LXn2g95-lU5kOXkj9Si1onsVk3ZUHcXQcAKRrY1B2KFe4IbCBhQFpiI34Sm6Xr8MrqjrPrILYvhXE8ZLEBxDG_JebWOqL3H6Hef09J-rvb1XJqqLtHj7vpvuKmll7vG8LHM8BKws1GyVfzkqk3jvmUGJCF3lWQ4npXI2eSc5aGxGWJEkd3XpFkMUriWk0bkKwYyF3VTr1VfSlEq5xkiX-WA92psXRQZsjEX90sL5-qYKLzrvdBqhssL1T5LQAAGAkXAwLFqXGZ5NUw" self.assertEqual(expected_signature, jku_signature) self.assertEqual("RS256", rsa_token_jwk.get_algorithm()) self.assertEqual("JWT", rsa_token_jwk.header['typ']) self.assertEqual(kid, rsa_token_jwk.header['kid']) self.assertEqual(jku, rsa_token_jwk.header['jku']) self.assertEqual("1234567890", rsa_token_jwk.payload['sub']) self.assertEqual("John Doe", rsa_token_jwk.payload['name']) self.assertEqual(1516239022, rsa_token_jwk.payload['iat']) self.assertEqual(3, len(rsa_token_jwk.payload)) jwks = json.loads(attack.payloads['attack_pubkey_deception_jku_jwks']) jku_pubkey: RSAPublicKey = utils.rsa_jwks_to_pubkey(jwks, kid) rsa_token_jwk.verify_signature(jku_pubkey, utils.base64url_decode(jku_signature))
def test_rsa256_jwks_to_pubkey_single_key(self): n = b'oGV0P-rgmJd8qEu_0c1YYjNLt8RjBmGcy4X0RXK3lEfHjGWJggkaHFY_zP-m0uWijPl7ASq1gf7cL7w801pLXB_vUqxPyl7rP8ul_4j_ghWjGrl58yNyRBcIVh18HICCqAduvbasehRstSv0JSAP6VArEcpLGOnHI0IILclWjFQf35A4fbsVYbqs2ZUhP7C5Jq36SA5GRqq4QTKuG0YP4t1j9CEEIQUldwHcuoMzBH4GOP0eZd1EkhTw8uQvQeHtao-J0Mfh-ljFC2Rcvoysx6HwGVZIg2DlGiWttYCWzUvc5q2doFIJ640gO9KLFeOC5ebGTwnzJ_Z5jCaim2Eomw' e = b'AQAB' jwks = { 'keys': [{ 'alg': "RS256", 'kty': "RSA", 'kid': "test_key", 'e': e, 'n': n }] } print("{}".format(jwks)) expected_pubkey: RSAPublicKey = load_pem_public_key( utils.read_pem_file("./keys/pubkey1.pem"), default_backend()) pubkey: RSAPublicKey = rsa_jwks_to_pubkey(jwks) self.assertEqual(expected_pubkey.public_numbers().e, pubkey.public_numbers().e) self.assertEqual(expected_pubkey.public_numbers().n, pubkey.public_numbers().n)
def parse_and_validate(): if len(sys.argv) < 2: print_help() if len(sys.argv) >= 2: serial_jwt = sys.argv[1] _, _, signature = TestJWT.split_jwt(serial_jwt) jwt: TestJWT = TestJWT.deserialize(serial_jwt) jwt.show_token() if len(sys.argv) == 3: params: str = sys.argv[2] param_val = get_arg_value(params) if param_val is None: print_help() return verified_sig = False if params.startswith("-s") and param_val: secret = param_val verified_sig = jwt.verify_signature(secret, signature) elif params.startswith("-p") and param_val: key = load_pem_public_key(utils.read_pem_file(param_val), default_backend()) verified_sig = jwt.verify_signature( key, utils.base64url_decode(signature)) elif params.startswith("-jwks") and param_val: jwks = json.loads( utils.read_file(param_val, strip_newline=True, join_lines=True)) key = utils.rsa_jwks_to_pubkey(jwks) verified_sig = jwt.verify_signature( key, utils.base64url_decode(signature)) # TODO add support to verify signature if jwk is included in header else: print_help() return if verified_sig: print("Signature verified") else: print("Signature verification FAILED !!")