def test_u2f_register_request(self): challenge = "Jtb6wLXjMHN67fV1BVNivz-qnAnD8OOqFju49RDBJro" req = U2fRegisterRequest.create( 'https://example.com', [], websafe_decode(challenge) ) self.assertEqual(U2fRegisterRequest.wrap({ "registeredKeys": [], "appId": "https://example.com", "registerRequests": [{ "version": "U2F_V2", "challenge": "Jtb6wLXjMHN67fV1BVNivz-qnAnD8OOqFju49RDBJro" }] }), req) self.assertEqual(U2fRegisterRequest.wrap(req.json), req) self.assertEqual( websafe_decode('EAaArVRs5qV39C9S3zO0z9ynVoWeZkuNfeMpsVDQnOk'), req.applicationParameter ) self.assertEqual([], req.registeredKeys) self.assertEqual(1, len(req.registerRequests)) reg_req = req.get_request('U2F_V2') self.assertEqual(reg_req.challenge, websafe_decode(challenge)) self.assertEqual(reg_req.version, 'U2F_V2')
def test_register_fixed_values(self): req = U2fRegisterRequest.create( 'http://localhost:8081', [], websafe_decode('KEzvDDdHwnXtPHIMb0Uh43hgOJ-wQTsdLujGkeg6JxM')) reg, cert = req.complete({ "version": "U2F_V2", "registrationData": "BQS94xQL46G4vheJPkYSuEteM6Km4-MwgBAu1zZ6MAbjDD" "gqhYbpHuIhhGOKjedeDd58qqktqOJsby9wMdHGnUtVQD8ISPywVi3J6SaKebCVQdHP" "u3_zQigRS8LhoDwKT5Ed3tg8AWuNw9XBZEh4doEDxKGuInFazirUw8acOu2qDcEwgg" "IjMIIBDaADAgECAgRyuHt0MAsGCSqGSIb3DQEBCzAPMQ0wCwYDVQQDEwR0ZXN0MB4X" "DTE1MDkwNDA3MTAyNloXDTE2MDkwMzA3MTAyNlowKjEoMCYGA1UEAxMfWXViaWNvIF" "UyRiBFRSBTZXJpYWwgMTkyNDY5Mjg1MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA" "BC37i_h-xmEtGfWnuvj_BmuhtU18MKShNP_vZ7C2WJwj8OHaSLnzAfha14CMUPaKPt" "RFfP6w9CFGhvEizH33XZKjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0" "ODIuMS4yMBMGCysGAQQBguUcAgEBBAQDAgQwMAsGCSqGSIb3DQEBCwOCAQEAab7fWl" "J-lOR1sqIxawPU5DWZ1b9nQ0QmNNoetPHJ_fJC95r0esRq5axfmGufbNktNWanHww7" "i9n5WWxSaMTWuJSF0eAXUajo8odYA8nB4_0I6z615MWa9hTU64Pl9HlqkR5ez5jndm" "JNuAfhaIF4h062Jw051kMo_aENxuLixnybTfJG7Q5KRE00o2MFs5b9L9fzhDtBzv5Z" "-vGOefuiohowpwnxIA9l0tGqrum9plUdx06K9TqKMRDQ8naosy01rbouA6i5xVjl-t" "HT3z-r__FYcSZ_dQ5-SCPOh4F0w6T0UwzymQmeqYN3pP-UUgnJ-ihD-uhEWklKNYRy" "0K0G0jBGAiEA7rbbx2jwC1YGICkZMR07ggKWaHCwFBxNDW3OwhLNNzUCIQCSq0sjGS" "UnWMQgPEImrmd3tMKcbrjI995rti6UYozqsg", "clientData": "eyJvcmlnaW4iOiAiaHR0cDovL2xvY2FsaG9zdDo4MDgxIiwgImNo" "YWxsZW5nZSI6ICJLRXp2RERkSHduWHRQSElNYjBVaDQzaGdPSi13UVRzZEx1akdrZW" "c2SnhNIiwgInR5cCI6ICJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCJ9" }) assert reg
def bind(self, response): """ Complete registration, returning a U2FBinding. registrationResponse = { "registrationData": string, //b64 encoded raw registration response "clientData": string, //b64 encoded JSON of ClientData } """ if not isinstance(response, RegisterResponse): response = RegisterResponse(response) self._validate_client_data(response.clientData) raw_response = RawRegistrationResponse( self.app_param, response.clientParam, websafe_decode(response['registrationData']) ) raw_response.verify_csr_signature() # TODO: Validate the certificate as well return U2FBinding(self.app_id, self.facets, raw_response)
def test_authenticate_fixed_values(self): device = { 'version': 'U2F_V2', 'publicKey': 'BBCcnAOknoMgokEGuTdfpNLQ-uylwlKp_xbEW8urjJsXKv9XZSL-V' '8C2nwcPEckav1mKZFr5K96uAoLtuxOUf-E', 'keyHandle': 'BIarIKfyMqyf4bEI6tOqGInAfHrrQkMA2eyPJlNnInbAG1tXNpdRs' '48ef92_b1-mfN4VhaTWxo1SGoxT6CIanw', 'appId': 'http://www.example.com/appid' } response = { 'keyHandle': 'BIarIKfyMqyf4bEI6tOqGInAfHrrQkMA2eyPJlNnInbAG1tXNpdRs' '48ef92_b1-mfN4VhaTWxo1SGoxT6CIanw', 'signatureData': 'AAAAAAEwRQIhAJrcBSpaDprFzXmVw60r6x-_gOZ0t-8v7DGii' 'Kmar0SAAiAYKKEX41nWUCLLoKiBYuHYdPP1MPPNQ0cX_JIybPtThA', 'clientData': 'eyJvcmlnaW4iOiAiaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20iLCAi' 'Y2hhbGxlbmdlIjogIm9JZXUtblB4eDlEY0Y3TF9EQ0Uza3ZZb3gtYzRVdXZGYjhsTk' 'c2dGgxMG8iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24ifQ' } req = U2fSignRequest.create( 'http://www.example.com/appid', [device], websafe_decode('oIeu-nPxx9DcF7L_DCE3kvYox-c4UuvFb8lNG6th10o')) req.complete(response)
def test_register_fixed_values(self): req = U2fRegisterRequest.create( 'http://localhost:8081', [], websafe_decode('KEzvDDdHwnXtPHIMb0Uh43hgOJ-wQTsdLujGkeg6JxM') ) reg, cert = req.complete({ "version": "U2F_V2", "registrationData": "BQS94xQL46G4vheJPkYSuEteM6Km4-MwgBAu1zZ6MAbjDD" "gqhYbpHuIhhGOKjedeDd58qqktqOJsby9wMdHGnUtVQD8ISPywVi3J6SaKebCVQdHP" "u3_zQigRS8LhoDwKT5Ed3tg8AWuNw9XBZEh4doEDxKGuInFazirUw8acOu2qDcEwgg" "IjMIIBDaADAgECAgRyuHt0MAsGCSqGSIb3DQEBCzAPMQ0wCwYDVQQDEwR0ZXN0MB4X" "DTE1MDkwNDA3MTAyNloXDTE2MDkwMzA3MTAyNlowKjEoMCYGA1UEAxMfWXViaWNvIF" "UyRiBFRSBTZXJpYWwgMTkyNDY5Mjg1MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA" "BC37i_h-xmEtGfWnuvj_BmuhtU18MKShNP_vZ7C2WJwj8OHaSLnzAfha14CMUPaKPt" "RFfP6w9CFGhvEizH33XZKjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0" "ODIuMS4yMBMGCysGAQQBguUcAgEBBAQDAgQwMAsGCSqGSIb3DQEBCwOCAQEAab7fWl" "J-lOR1sqIxawPU5DWZ1b9nQ0QmNNoetPHJ_fJC95r0esRq5axfmGufbNktNWanHww7" "i9n5WWxSaMTWuJSF0eAXUajo8odYA8nB4_0I6z615MWa9hTU64Pl9HlqkR5ez5jndm" "JNuAfhaIF4h062Jw051kMo_aENxuLixnybTfJG7Q5KRE00o2MFs5b9L9fzhDtBzv5Z" "-vGOefuiohowpwnxIA9l0tGqrum9plUdx06K9TqKMRDQ8naosy01rbouA6i5xVjl-t" "HT3z-r__FYcSZ_dQ5-SCPOh4F0w6T0UwzymQmeqYN3pP-UUgnJ-ihD-uhEWklKNYRy" "0K0G0jBGAiEA7rbbx2jwC1YGICkZMR07ggKWaHCwFBxNDW3OwhLNNzUCIQCSq0sjGS" "UnWMQgPEImrmd3tMKcbrjI995rti6UYozqsg", "clientData": "eyJvcmlnaW4iOiAiaHR0cDovL2xvY2FsaG9zdDo4MDgxIiwgImNo" "YWxsZW5nZSI6ICJLRXp2RERkSHduWHRQSElNYjBVaDQzaGdPSi13UVRzZEx1akdrZW" "c2SnhNIiwgInR5cCI6ICJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCJ9" }) assert reg
def test_websafe_decode(self): self.assertEqual(websafe_decode(b''), b'') self.assertEqual(websafe_decode(b'Zg'), b'f') self.assertEqual(websafe_decode(b'Zm8'), b'fo') self.assertEqual(websafe_decode(b'Zm9v'), b'foo') self.assertEqual(websafe_decode(b'Zm9vYg'), b'foob') self.assertEqual(websafe_decode(b'Zm9vYmE'), b'fooba') self.assertEqual(websafe_decode(b'Zm9vYmFy'), b'foobar')
def __init__(self, *args, **kwargs): if len(args) == 1: data = args[0] if isinstance(data, six.binary_type): data = data.decode('utf-8') try: args = [websafe_decode(data)] except ValueError: pass # Not encoded, leave as is super(ClientData, self).__init__(*args, **kwargs)
def test_u2f_sign_request(self): challenge = "Jtb6wLXjMHN67fV1BVNivz-qnAnD8OOqFju49RDBJro" req = U2fSignRequest.wrap( { "appId": "https://example.com", "registeredKeys": [{ "publicKey": "BBCcnAOknoMgokEGuTdfpNLQ-uylwlKp_xbEW8urjJsXK" "v9XZSL-V8C2nwcPEckav1mKZFr5K96uAoLtuxOUf-E", "version": "U2F_V2", "keyHandle": "BIarIKfyMqyf4bEI6tOqGInAfHrrQkMA2eyPJlNnInbAG" "1tXNpdRs48ef92_b1-mfN4VhaTWxo1SGoxT6CIanw" }], "challenge": challenge } ) self.assertEqual(U2fSignRequest.wrap(req.json), req) self.assertEqual( req.applicationParameter, websafe_decode('EAaArVRs5qV39C9S3zO0z9ynVoWeZkuNfeMpsVDQnOk') ) self.assertEqual(req.challenge, websafe_decode(challenge))
def getAssertion(self, request, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData( typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet ) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # Unwrap: priv_key, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = int2byte(1 if touch else 0) counter = struct.pack('>I', self.counter) data = app_param + touch + counter + client_param signer = priv_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle )
def getAssertion(self, request, facet="https://www.example.com"): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData( typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet ) client_data = client_data.json.encode('utf-8') client_param = sha_256(client_data) # Unwrap: priv_key, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = int2byte(1) counter = struct.pack('>I', self.counter) data = app_param + touch + counter + client_param signer = priv_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) signature = signer.finalize() raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle )
def verify_token(self, token): client_data = json.loads(websafe_decode(token['clientData']).decode()) try: u2f_challenge = U2FChallenge.objects.get( challenge=client_data['challenge'], device=self) except U2FChallenge.DoesNotExist: return False try: complete_authentication(u2f_challenge.challenge_data, token, [settings.OTP_U2F_APP_ID]) except ValueError: return False u2f_challenge.delete() return True
def verify_authenticate(device, request, response, valid_facets=None): device = DeviceRegistration.wrap(device) request = SignRequest.wrap(request) response = SignResponse.wrap(response) _validate_client_data(response.clientData, request.challenge, "navigator.id.getAssertion", valid_facets) raw_response = RawAuthenticationResponse(device.appParam, response.clientParam, response.signatureData) raw_response.verify_signature(websafe_decode(device.publicKey)) return raw_response.counter_int, raw_response.user_presence
def getAssertion(self, request, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData( typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet ) client_data = client_data.json client_param = H(client_data) # Unwrap: privu, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = chr(1 if touch else 0) counter = struct.pack('>I', self.counter) digest = H(app_param + touch + counter + client_param) signature = privu.sign_dsa_asn1(digest) raw_response = touch + counter + signature return SignResponse( clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle )
def bind(self, username, data): user = self.users[username] enroll = user.pop('_u2f_enroll_') device, cert = complete_registration(enroll, data, [self.facet]) print print 'device, ' , device print 'key handle', binascii.hexlify(websafe_decode(device['keyHandle'])) print user.setdefault('_u2f_devices_', []).append(device.json) log.info("U2F device enrolled. Username: %s", username) cert = x509.load_der_x509_certificate(cert, default_backend()) log.debug("Attestation certificate:\n%s", cert.public_bytes(Encoding.PEM)) return json.dumps(True)
def verify_authenticate(device, request, response, valid_facets=None): device = DeviceRegistration.wrap(device) request = SignRequest.wrap(request) response = SignResponse.wrap(response) _validate_client_data(response.clientData, request.challenge, "navigator.id.getAssertion", valid_facets) raw_response = RawAuthenticationResponse( device.appParam, response.clientParam, response.signatureData ) raw_response.verify_signature(websafe_decode(device.publicKey)) return raw_response.counter_int, raw_response.user_presence
def getAssertion(self, data, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if isinstance(data, basestring): data = json.loads(data) if data['version'] != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % data['version']) key_handle = websafe_decode(data['keyHandle']) if not key_handle in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = { 'typ': "navigator.id.getAssertion", 'challenge': data['challenge'], 'origin': facet } client_data = json.dumps(client_data) client_param = H(client_data) # Unwrap: privu, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = chr(1 if touch else 0) counter = struct.pack('>I', self.counter) digest = H(app_param + touch + counter + client_param) signature = privu.sign_dsa_asn1(digest) raw_response = touch + counter + signature return json.dumps({ "clientData": websafe_encode(client_data), "signatureData": websafe_encode(raw_response), "challenge": data['challenge'], })
def getAssertion(self, request, facet="https://www.example.com", touch=False): """ signData = { 'version': "U2F_V2", 'challenge': websafe_encode(self.challenge), 'appId': self.binding.app_id, 'keyHandle': websafe_encode(self.binding.key_handle), } """ if not isinstance(request, SignRequest): request = SignRequest(request) if request.version != "U2F_V2": raise ValueError("Unsupported U2F version: %s" % request.version) key_handle = websafe_decode(request.keyHandle) if key_handle not in self.keys: raise ValueError("Unknown key handle!") # Client data client_data = ClientData(typ="navigator.id.getAssertion", challenge=request['challenge'], origin=facet) client_data = client_data.json client_param = H(client_data) # Unwrap: privu, app_param = self.keys[key_handle] # Increment counter self.counter += 1 # Create signature touch = chr(1 if touch else 0) counter = struct.pack('>I', self.counter) digest = H(app_param + touch + counter + client_param) signature = privu.sign_dsa_asn1(digest) raw_response = touch + counter + signature return SignResponse(clientData=websafe_encode(client_data), signatureData=websafe_encode(raw_response), keyHandle=request.keyHandle)
def webauthnuser(self): d = json.loads(self.json_data) # We manually need to convert the pubkey from DER format (used in our # former U2F implementation) to the format required by webauthn. This # is based on the following example: # https://www.w3.org/TR/webauthn/#sctn-encoded-credPubKey-examples pub_key = pub_key_from_der( websafe_decode(d['publicKey'].replace('+', '-').replace('/', '_'))) pub_key = binascii.unhexlify( 'A5010203262001215820{:064x}225820{:064x}'.format( pub_key.public_numbers().x, pub_key.public_numbers().y)) return webauthn.WebAuthnUser(d['keyHandle'], self.user.email, str(self.user), settings.SITE_URL, d['keyHandle'], websafe_encode(pub_key), 1, urlparse(settings.SITE_URL).netloc)
def validate(self, response): """ signResponse = { "clientData": string, //b64 encoded JSON of ClientData "signatureData": string, //b64 encoded raw sign response "challenge": string, //b64 encoded challenge } """ if not isinstance(response, SignResponse): response = SignResponse(response) self._validate_client_data(response.clientData) raw_response = RawAuthenticationResponse( self.app_param, response.clientParam, websafe_decode( response['signatureData'])) raw_response.verify_signature(self.binding.pub_key) return raw_response.counter_int, raw_response.user_presence
def validate(self, response): """ signResponse = { "clientData": string, //b64 encoded JSON of ClientData "signatureData": string, //b64 encoded raw sign response "keyHandle": string, //b64 encoded key handle } """ if not isinstance(response, SignResponse): response = SignResponse(response) self._validate_client_data(response.clientData) raw_response = RawAuthenticationResponse( self.app_param, response.clientParam, websafe_decode( response['signatureData'])) raw_response.verify_signature(self.binding.pub_key) return raw_response.counter_int, raw_response.user_presence
def test_authenticate_fixed_values(self): device = { 'version': 'U2F_V2', 'publicKey': 'BBCcnAOknoMgokEGuTdfpNLQ-uylwlKp_xbEW8urjJsXKv9XZSL-V' '8C2nwcPEckav1mKZFr5K96uAoLtuxOUf-E', 'keyHandle': 'BIarIKfyMqyf4bEI6tOqGInAfHrrQkMA2eyPJlNnInbAG1tXNpdRs' '48ef92_b1-mfN4VhaTWxo1SGoxT6CIanw', 'appId': 'http://www.example.com/appid' } response = { 'keyHandle': 'BIarIKfyMqyf4bEI6tOqGInAfHrrQkMA2eyPJlNnInbAG1tXNpdRs' '48ef92_b1-mfN4VhaTWxo1SGoxT6CIanw', 'signatureData': 'AAAAAAEwRQIhAJrcBSpaDprFzXmVw60r6x-_gOZ0t-8v7DGii' 'Kmar0SAAiAYKKEX41nWUCLLoKiBYuHYdPP1MPPNQ0cX_JIybPtThA', 'clientData': 'eyJvcmlnaW4iOiAiaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20iLCAi' 'Y2hhbGxlbmdlIjogIm9JZXUtblB4eDlEY0Y3TF9EQ0Uza3ZZb3gtYzRVdXZGYjhsTk' 'c2dGgxMG8iLCAidHlwIjogIm5hdmlnYXRvci5pZC5nZXRBc3NlcnRpb24ifQ' } req = U2fSignRequest.create( 'http://www.example.com/appid', [device], websafe_decode('oIeu-nPxx9DcF7L_DCE3kvYox-c4UuvFb8lNG6th10o') ) req.complete(response)
def clientData(self): return ClientData(websafe_decode(self['clientData']))
def challenge(self): return websafe_decode(self['challenge'])
def deserialize(cls, serialized): data = websafe_decode(serialized) return cls(data[:32], data[32:64], data[64:])
def deserialize(cls, binding, serialized): data = json.loads(serialized) return cls(binding, websafe_decode(data['challenge']))
def signatureData(self): return websafe_decode(self['signatureData'])
def publicKey(self): return websafe_decode(self['publicKey'])
def clientParam(self): return sha_256(websafe_decode(self['clientData']))
def test_websafe_decode_unicode(self): self.assertEqual(websafe_decode(u''), b'') self.assertEqual(websafe_decode(u'Zm9vYmFy'), b'foobar')
def registrationData(self): return websafe_decode(self['registrationData'])
def challengeParameter(self): return sha_256(websafe_decode(self['clientData']))
def signatureData(self): return SignatureData(websafe_decode(self['signatureData']))
def deserialize(cls, serialized): data = json.loads(serialized) return cls(data['appId'], data['facets'], websafe_decode(data['challenge']))
def keyHandle(self): return websafe_decode(self['keyHandle'])
def registrationData(self): return RegistrationData(websafe_decode(self['registrationData']))
from u2flib_server.utils import websafe_decode from u2flib_server.model import (JSONDict, RegistrationData, SignatureData, U2fRegisterRequest, U2fSignRequest) from binascii import b2a_hex import unittest SAMPLE_REG_DATA = websafe_decode( 'BQRFJ5xApW6uBsuSJ_FgUcL-seKecha71q8evgqfQwc5QuqQhv4qJoL3KpSUKX1T6XVJEqyOkn' 'Ok397y2Rh5m_zkQD9wrlgMW9EGOGmBQ0lKIa79vcQl2tMF7hlhNjIGrJHw7Rqg8wbnKWSvQjs5' 'ytK3s3X9YRuNcY3ht5pJYZbGa-4wggGHMIIBLqADAgECAgkAmb7osQyi7BwwCQYHKoZIzj0EAT' 'AhMR8wHQYDVQQDDBZZdWJpY28gVTJGIFNvZnQgRGV2aWNlMB4XDTEzMDcxNzE0MjEwM1oXDTE2' 'MDcxNjE0MjEwM1owITEfMB0GA1UEAwwWWXViaWNvIFUyRiBTb2Z0IERldmljZTBZMBMGByqGSM' '49AgEGCCqGSM49AwEHA0IABDvhl91zfpg9n7DeCedcQ8gGXUnemiXoi-JEAxz-EIhkVsMPAyzh' 'tJZ4V3CqMZ-MOUgICt2aMxacMX9cIa8dgS2jUDBOMB0GA1UdDgQWBBQNqL-TV04iaO6mS5tjGE' '6ShfexnjAfBgNVHSMEGDAWgBQNqL-TV04iaO6mS5tjGE6ShfexnjAMBgNVHRMEBTADAQH_MAkG' 'ByqGSM49BAEDSAAwRQIgXJWZdbvOWdhVaG7IJtn44o21Kmi8EHsDk4cAfnZ0r38CIQD6ZPi3Pl' '4lXxbY7BXFyrpkiOvCpdyNdLLYbSTbvIBQOTBGAiEAsp3iNiXaF9mk6mHzJqva-hi7AlT-_or-' '2HdKUJycqaUCIQCP9P4aju4iq8U6hRyIIllppzwfK9_7QNv_7_OV7pQxug' ) SAMPLE_REG_DATA_NEEDS_FIX = websafe_decode( 'BQQR2Q82wJ9RLOcH5TvQvve7LrBnDp0YiCSDxKPiHsg_AY1b70GK-dcCt-HqCkqJZikAXL4zLY' 'CsKmucc1xna99BQAMOcuxXOpiG-MJIB3zUpvT1hO2v18nBYsRRFjRPIStBxFyh6PMMjA10aZFf' '68_EFpgc_CAfEiEqr5L41anLJ3EwggIcMIIBBqADAgECAgQ4Zt91MAsGCSqGSIb3DQEBCzAuMS' 'wwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEw' 'MDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowKzEpMCcGA1UEAwwgWXViaWNvIFUyRiBFRSBTZXJpYW' 'wgMTM4MzExNjc4NjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ3jfx0DHOblHJO09Ujubh2' 'gQZWwT3ob6-uzzjZD1XiyAob_gsw3FOzXefQRblty48r-U-o4LkDFjx_btwuSHtxoxIwEDAOBg' 'orBgEEAYLECgEBBAAwCwYJKoZIhvcNAQELA4IBAQIaR2TKAInPkq24f6hIU45yzD79uzR5KUME' 'e4IWqTm69METVio0W2FHWXlpeUe85nGqanwGeW7U67G4_WAnGbcd6zz2QumNsdlmb_AebbdPRa' '95Z8BG1ub_S04JoxQYNLaa8WRlzN7POgqAnAqkmnsZQ_W9Tj2uO9zP3mpxOkkmnqz7P5zt4Lp5'