def update(self, param, reset_failcount=True): """ This method is called during the initialization process. :param param: parameters from the token init :type param: dict :return: None """ TokenClass.update(self, param) description = "U2F initialization" reg_data = getParam(param, "regdata") if reg_data: self.init_step = 2 attestation_cert, user_pub_key, key_handle, \ signature, description = parse_registration_data(reg_data) client_data = getParam(param, "clientdata", required) client_data_str = url_decode(client_data) app_id = self.get_tokeninfo("appId", "") # Verify the registration data # In case of any crypto error, check_data raises an exception check_registration_data(attestation_cert, app_id, client_data_str, user_pub_key, key_handle, signature) self.set_otpkey(key_handle) self.add_tokeninfo("pubKey", user_pub_key) self.set_description(description)
def test_02_parse_regdata(self): client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6IlNna3pUekdyYnNVREUyNEJSMV9kUTRYbXJtNTVqU2MzVml3Sm5DRjVmWm8iLCJvcmlnaW4iOiJodHRwczovL2RlbW8ueXViaWNvLmNvbSIsImNpZF9wdWJrZXkiOiJ1bnVzZWQifQ" reg_data = "BQT3NET2RTTcgzAiZRW5gkg3TT6mgQBepZl96iMtj-nXU25VdwBXCL1EjWOY-q1M76vT_iX9ebDhkZ1kvosbi3_AQGVopI2hcyIsc8q-KpzerJIZgWtN25bCy6g_hTk_M1khCjQGaiGJFwnk8GIn2OnkNOJRe7V00Q9PBZHn5mFwfFwwggJEMIIBLqADAgECAgRVYr6gMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTQzMjUzNDY4ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEszH3c9gUS5mVy-RYVRfhdYOqR2I2lcvoWsSCyAGfLJuUZ64EWw5m8TGy6jJDyR_aYC4xjz_F2NKnq65yvRQwmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEArBbZs262s6m3bXWUs09Z9Pc-28n96yk162tFHKv0HSXT5xYU10cmBMpypXjjI-23YARoXwXn0bm-BdtulED6xc_JMqbK-uhSmXcu2wJ4ICA81BQdPutvaizpnjlXgDJjq6uNbsSAp98IStLLp7fW13yUw-vAsWb5YFfK9f46Yx6iakM3YqNvvs9M9EUJYl_VrxBJqnyLx2iaZlnpr13o8NcsKIJRdMUOBqt_ageQg3ttsyq_3LyoNcu7CQ7x8NmeCGm_6eVnZMQjDmwFdymwEN4OxfnM5MkcKCYhjqgIGruWkVHsFnJa8qjZXneVvKoiepuUQyDEJ2GcqvhU2YKY1zBFAiEAqqVKbLnZuWYyzjcsb1YnHEyuk-dmM77Q66iExrj8h2cCIHAvpisjLj-D2KvnZZcIQ_fFjFj9OX5jkfmJ65QVQ9bE" cert, user_pub_key, key_handle, signature, description = \ parse_registration_data(reg_data) self.assertEqual( user_pub_key, '04f73444f64534dc8330226515b98248374d3ea681005ea5997dea232d8fe9d7536e5577005708bd448d6398faad4cefabd3fe25fd79b0e1919d64be8b1b8b7fc0' ) self.assertEqual( key_handle, '6568a48da173222c73cabe2a9cdeac9219816b4ddb96c2cba83f85393f3359210a34066a21891709e4f06227d8e9e434e2517bb574d10f4f0591e7e661707c5c' ) self.assertEqual(description, 'Yubico U2F EE Serial 1432534688') client_data_str = base64.b64decode(client_data + "==") r = check_registration_data(cert, "https://demo.yubico.com", client_data_str, user_pub_key, key_handle, signature) self.assertTrue(r) # modify signature broken_sig = 'ff' + signature[2:] with self.assertRaisesRegexp( Exception, 'Error checking the signature of the registration data.'): check_registration_data(cert, "https://demo.yubico.com", client_data_str, user_pub_key, key_handle, broken_sig)
def update(self, param, reset_failcount=True): """ This method is called during the initialization process. :param param: parameters from the token init :type param: dict :return: None """ TokenClass.update(self, param) reg_data = getParam(param, "regdata") verify_cert = is_true(getParam(param, "u2f.verify_cert", default=True)) if not reg_data: self.token.rollout_state = ROLLOUTSTATE.CLIENTWAIT # Set the description in the first enrollment step if "description" in param: self.set_description(getParam(param, "description", default="")) elif reg_data and self.token.rollout_state == ROLLOUTSTATE.CLIENTWAIT: attestation_cert, user_pub_key, key_handle, \ signature, automatic_description = parse_registration_data(reg_data, verify_cert=verify_cert) client_data = getParam(param, "clientdata", required) client_data_str = url_decode(client_data) app_id = self.get_tokeninfo("appId", "") # Verify the registration data # In case of any crypto error, check_data raises an exception check_registration_data(attestation_cert, app_id, client_data_str, user_pub_key, key_handle, signature) self.set_otpkey(key_handle) self.add_tokeninfo("pubKey", user_pub_key) # add attestation certificate info issuer = x509name_to_string(attestation_cert.get_issuer()) serial = "{!s}".format(attestation_cert.get_serial_number()) subject = x509name_to_string(attestation_cert.get_subject()) self.add_tokeninfo("attestation_issuer", issuer) self.add_tokeninfo("attestation_serial", serial) self.add_tokeninfo("attestation_subject", subject) # Reset rollout state self.token.rollout_state = "" # If no description has already been set, set the automatic description or the # description given in the 2nd request if not self.token.description: self.set_description( getParam(param, "description", default=automatic_description)) else: raise ParameterError( "regdata provided but token not in clientwait rollout_state.")
def update(self, param, reset_failcount=True): """ This method is called during the initialization process. :param param: parameters from the token init :type param: dict :return: None """ TokenClass.update(self, param) description = "U2F initialization" reg_data = getParam(param, "regdata") verify_cert = is_true(getParam(param, "u2f.verify_cert", default=True)) if reg_data: self.init_step = 2 attestation_cert, user_pub_key, key_handle, \ signature, description = parse_registration_data(reg_data, verify_cert=verify_cert) client_data = getParam(param, "clientdata", required) client_data_str = url_decode(client_data) app_id = self.get_tokeninfo("appId", "") # Verify the registration data # In case of any crypto error, check_data raises an exception check_registration_data(attestation_cert, app_id, client_data_str, user_pub_key, key_handle, signature) self.set_otpkey(key_handle) self.add_tokeninfo("pubKey", user_pub_key) # add attestation certificat info issuer = x509name_to_string(attestation_cert.get_issuer()) serial = "{!s}".format(attestation_cert.get_serial_number()) subject = x509name_to_string(attestation_cert.get_subject()) self.add_tokeninfo("attestation_issuer", issuer) self.add_tokeninfo("attestation_serial", serial) self.add_tokeninfo("attestation_subject", subject) # If a description is given we use the given description description = getParam(param, "description", default=description) self.set_description(description)
def test_01_check_reg_data(self): ATTESTATION_CERT = "3082013c3081e4a003020102020a4790128000115595735230" \ "0a06082a8648ce3d0403023017311530130603550403130c" \ "476e756262792050696c6f74301e170d313230383134313" \ "8323933325a170d3133303831343138323933325a303131" \ "2f302d0603550403132650696c6f74476e756262792d302" \ "e342e312d34373930313238303030313135353935373335" \ "323059301306072a8648ce3d020106082a8648ce3d030107" \ "034200048d617e65c9508e64bcc5673ac82a6799da3c1446" \ "682c258c463fffdf58dfd2fa3e6c378b53d795c4a4dffb4" \ "199edd7862f23abaf0203b4b8911ba0569994e101300a06" \ "082a8648ce3d0403020347003044022060cdb6061e9c2226" \ "2d1aac1d96d8c70829b2366531dda268832cb836bcd30dfa" \ "0220631b1459f09e6330055722c8d89b7f48883b9089b88d" \ "60d1d9795902b30410df" CLIENT_DATA = { "typ": "navigator.id.finishEnrollment", "challenge": "vqrS6WXDe1JUs5_c3i4-LkKIHRr-3XVb3azuA5TifHo", "cid_pubkey": { "kty": "EC", "crv": "P-256", "x": "HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8", "y": "XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4" }, "origin": "http://example.com" } APP_ID = 'http://example.com' app_id_hash = binascii.hexlify(sha256(APP_ID).digest()) self.assertEqual( app_id_hash, "f0e6a6a97042a4f1f1c87f5f7d44315b2d852c2df5c7991cc66241bf7072d1c4") attestation_cert = crypto.load_certificate( crypto.FILETYPE_ASN1, binascii.unhexlify(ATTESTATION_CERT)) client_data_str = '{"typ":"navigator.id.finishEnrollment","challenge":"vqrS6WXDe1JUs5_c3i4-LkKIHRr-3XVb3azuA5TifHo","cid_pubkey":{"kty":"EC","crv":"P-256","x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8","y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"},"origin":"http://example.com"}' client_data_hash = binascii.hexlify(sha256(client_data_str).digest()) self.assertEqual( client_data_hash, "4142d21c00d94ffb9d504ada8f99b721f4b191ae4e37ca0140f696b6983cfacb") user_pub_key = "04b174bc49c7ca254b70d2e5c207cee9cf174820ebd77ea3c65508c26da51b657c1cc6b952f8621697936482da0a6d3d3826a59095daf6cd7c03e2e60385d2f6d9" key_handle = "2a552dfdb7477ed65fd84133f86196010b2215b57da75d315b7b9e8fe2e3925a6019551bab61d16591659cbaf00b4950f7abfe6660e2e006f76868b772d70c25" signature = "304502201471899bcc3987e62e8202c9b39c33c19033f7340352dba80fcab017db9230e402210082677d673d891933ade6f617e5dbde2e247e70423fd5ad7804a6d3d3961ef871" r = check_registration_data(attestation_cert, APP_ID, client_data_str, user_pub_key, key_handle, signature) self.assertEqual(r, True)
def test_02_parse_regdata(self): client_data = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6IlNna3pUekdyYnNVREUyNEJSMV9kUTRYbXJtNTVqU2MzVml3Sm5DRjVmWm8iLCJvcmlnaW4iOiJodHRwczovL2RlbW8ueXViaWNvLmNvbSIsImNpZF9wdWJrZXkiOiJ1bnVzZWQifQ" reg_data = "BQT3NET2RTTcgzAiZRW5gkg3TT6mgQBepZl96iMtj-nXU25VdwBXCL1EjWOY-q1M76vT_iX9ebDhkZ1kvosbi3_AQGVopI2hcyIsc8q-KpzerJIZgWtN25bCy6g_hTk_M1khCjQGaiGJFwnk8GIn2OnkNOJRe7V00Q9PBZHn5mFwfFwwggJEMIIBLqADAgECAgRVYr6gMAsGCSqGSIb3DQEBCzAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKjEoMCYGA1UEAwwfWXViaWNvIFUyRiBFRSBTZXJpYWwgMTQzMjUzNDY4ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEszH3c9gUS5mVy-RYVRfhdYOqR2I2lcvoWsSCyAGfLJuUZ64EWw5m8TGy6jJDyR_aYC4xjz_F2NKnq65yvRQwmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS41MBMGCysGAQQBguUcAgEBBAQDAgUgMAsGCSqGSIb3DQEBCwOCAQEArBbZs262s6m3bXWUs09Z9Pc-28n96yk162tFHKv0HSXT5xYU10cmBMpypXjjI-23YARoXwXn0bm-BdtulED6xc_JMqbK-uhSmXcu2wJ4ICA81BQdPutvaizpnjlXgDJjq6uNbsSAp98IStLLp7fW13yUw-vAsWb5YFfK9f46Yx6iakM3YqNvvs9M9EUJYl_VrxBJqnyLx2iaZlnpr13o8NcsKIJRdMUOBqt_ageQg3ttsyq_3LyoNcu7CQ7x8NmeCGm_6eVnZMQjDmwFdymwEN4OxfnM5MkcKCYhjqgIGruWkVHsFnJa8qjZXneVvKoiepuUQyDEJ2GcqvhU2YKY1zBFAiEAqqVKbLnZuWYyzjcsb1YnHEyuk-dmM77Q66iExrj8h2cCIHAvpisjLj-D2KvnZZcIQ_fFjFj9OX5jkfmJ65QVQ9bE" cert, user_pub_key, key_handle, signature , description = \ parse_registration_data(reg_data) self.assertEqual(user_pub_key, '04f73444f64534dc8330226515b98248374d3ea681005ea5997dea232d8fe9d7536e5577005708bd448d6398faad4cefabd3fe25fd79b0e1919d64be8b1b8b7fc0') self.assertEqual(key_handle, '6568a48da173222c73cabe2a9cdeac9219816b4ddb96c2cba83f85393f3359210a34066a21891709e4f06227d8e9e434e2517bb574d10f4f0591e7e661707c5c') self.assertEqual(description, 'Yubico U2F EE Serial 1432534688') client_data_str = base64.b64decode(client_data+"==") r = check_registration_data(cert, "https://demo.yubico.com", client_data_str, user_pub_key, key_handle, signature) self.assertTrue(r)
def test_01_check_reg_data(self): ATTESTATION_CERT = "3082013c3081e4a003020102020a4790128000115595735230" \ "0a06082a8648ce3d0403023017311530130603550403130c" \ "476e756262792050696c6f74301e170d313230383134313" \ "8323933325a170d3133303831343138323933325a303131" \ "2f302d0603550403132650696c6f74476e756262792d302" \ "e342e312d34373930313238303030313135353935373335" \ "323059301306072a8648ce3d020106082a8648ce3d030107" \ "034200048d617e65c9508e64bcc5673ac82a6799da3c1446" \ "682c258c463fffdf58dfd2fa3e6c378b53d795c4a4dffb4" \ "199edd7862f23abaf0203b4b8911ba0569994e101300a06" \ "082a8648ce3d0403020347003044022060cdb6061e9c2226" \ "2d1aac1d96d8c70829b2366531dda268832cb836bcd30dfa" \ "0220631b1459f09e6330055722c8d89b7f48883b9089b88d" \ "60d1d9795902b30410df" CLIENT_DATA = {"typ":"navigator.id.finishEnrollment", "challenge":"vqrS6WXDe1JUs5_c3i4-LkKIHRr-3XVb3azuA5TifHo", "cid_pubkey":{"kty":"EC", "crv":"P-256", "x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8", "y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"}, "origin":"http://example.com"} APP_ID = 'http://example.com' app_id_hash = binascii.hexlify(sha256(APP_ID).digest()) self.assertEqual(app_id_hash, "f0e6a6a97042a4f1f1c87f5f7d44315b2d852c2df5c7991cc66241bf7072d1c4") attestation_cert = crypto.load_certificate(crypto.FILETYPE_ASN1, binascii.unhexlify(ATTESTATION_CERT)) client_data_str = '{"typ":"navigator.id.finishEnrollment","challenge":"vqrS6WXDe1JUs5_c3i4-LkKIHRr-3XVb3azuA5TifHo","cid_pubkey":{"kty":"EC","crv":"P-256","x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8","y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"},"origin":"http://example.com"}' client_data_hash = binascii.hexlify(sha256(client_data_str).digest()) self.assertEqual(client_data_hash, "4142d21c00d94ffb9d504ada8f99b721f4b191ae4e37ca0140f696b6983cfacb") user_pub_key = "04b174bc49c7ca254b70d2e5c207cee9cf174820ebd77ea3c65508c26da51b657c1cc6b952f8621697936482da0a6d3d3826a59095daf6cd7c03e2e60385d2f6d9" key_handle = "2a552dfdb7477ed65fd84133f86196010b2215b57da75d315b7b9e8fe2e3925a6019551bab61d16591659cbaf00b4950f7abfe6660e2e006f76868b772d70c25" signature = "304502201471899bcc3987e62e8202c9b39c33c19033f7340352dba80fcab017db9230e402210082677d673d891933ade6f617e5dbde2e247e70423fd5ad7804a6d3d3961ef871" r = check_registration_data(attestation_cert, APP_ID, client_data_str, user_pub_key, key_handle, signature) self.assertEqual(r, True)