def webauthnGet(self, resp, raw_id, authData, signature, user_handle, client_data_hash): logging.debug('===assertion===') if authData: logging.debug('authData') if authData[:32].hex() == hashlib.sha256(rpid_host.encode()).hexdigest(): logging.debug('\trpidHash ' + str(authData[:32].hex())) flags = int.from_bytes(authData[32:33], 'big') logging.debug(f'\tflags {bin(flags)}, {bin(flags & 0b0100_0000)}, {bin(flags & 0b1000_0000)}') logging.debug('\tsigCount ' + str(int.from_bytes(authData[33:37], 'big'))) with open(f"./keys/{base64.urlsafe_b64encode(raw_id).decode()}.cbor") as f: public_key = cbor.loads(base64.b64decode(f.readline().encode())) if public_key[3] == -7: # TODO: 他のアルゴリズムへの対応 verification_data = authData + client_data_hash x = int(codecs.encode(public_key[-2], 'hex'), 16) y = int(codecs.encode(public_key[-3], 'hex'), 16) credential_public_key = EllipticCurvePublicNumbers(x, y, SECP256R1()).public_key(backend=default_backend()) try: credential_public_key.verify(signature, verification_data, ECDSA(SHA256())) resp.media = {'status': 'ok'} logging.info('[success] navigator.credentials.get') except InvalidSignature as e: logging.info(f'InvalidSignature {e}') resp.media = {'status': 'ng'} else: logging.info('not support type') resp.media = {'status': 'ng'} else: logging.info('not match RPID') logging.debug(f'{authData[:32].hex()}, {hashlib.sha256(rpid_host.encode()).hexdigest()} [{authData[:32].hex() == hashlib.sha256(rpid_host.encode()).hexdigest()}]') resp.media = {'status': 'ng'} else: logging.info('not find authData') resp.media = {'status': 'ng'}
def verify_signature(signature, data, point): public_key = EllipticCurvePublicNumbers( *point, curve=SECP256K1).public_key(DEFAULT_BACKEND) return public_key.verify(signature, data, ECDSA_SHA256)
def webauthnCreate(self, resp, raw_id, attestation, client_data_hash): logging.debug('===attestation===') authData = attestation.get('authData') if authData: logging.debug('authData') if authData[:32].hex() == hashlib.sha256(rpid_host.encode()).hexdigest(): logging.debug('\trpidHash ' + str(authData[:32].hex())) flags = int.from_bytes(authData[32:33], 'big') logging.debug(f'\tflags {bin(flags)}, {bin(flags & 0b0100_0000)}, {bin(flags & 0b1000_0000)}') logging.debug('\tsigCount ' + str(int.from_bytes(authData[33:37], 'big'))) if flags & 0b0100_0000: logging.debug('attestedCredentialData') logging.debug('\taaguid ' + str(int.from_bytes(authData[37:53], 'big'))) credentialIdLength = int.from_bytes(authData[53:55], 'big') logging.debug('\tcredentialIdLength ' + str(credentialIdLength)) credentialId = authData[55:55+credentialIdLength] logging.debug('\tcredentialId ' + str(base64.b64encode(credentialId))) credentialPublicKey = cbor.loads(authData[55+credentialIdLength:]) logging.debug('\tcredentialPublicKey') logging.debug('\t\tkty ' + str(credentialPublicKey[1])) logging.debug('\t\talg ' + str(credentialPublicKey[3])) logging.debug('\t\tcrv ' + str(credentialPublicKey[-1])) logging.debug('\t\tx ' + str(credentialPublicKey[-2])) logging.debug('\t\ty ' + str(credentialPublicKey[-3])) if flags & 0b1000_0000: logging.debug('extensions ' + str(cbor.loads(bytes(authData[37:])))) logging.info('not support flags') resp.media = {'status': 'ng'} return logging.debug('fmt ' + str(attestation.get('fmt'))) attStmt = attestation.get('attStmt') logging.debug('attStmt') for k in attStmt.keys(): logging.debug(f'\t{k} {attStmt[k]}') if attestation.get('fmt') == 'packed' and 'x5c' not in attStmt: # TODO: 他のパターンへの対応 # TODO: 他のアルゴリズムへの対応 signature = attStmt['sig'] verification_data = authData + client_data_hash x = int(codecs.encode(credentialPublicKey[-2], 'hex'), 16) y = int(codecs.encode(credentialPublicKey[-3], 'hex'), 16) credential_public_key = EllipticCurvePublicNumbers(x, y, SECP256R1()).public_key(backend=default_backend()) try: credential_public_key.verify(signature, verification_data, ECDSA(SHA256())) resp.media = {'status': 'ok'} logging.info('[success] navigator.credentials.create') with open(f'keys/{base64.urlsafe_b64encode(raw_id).decode()}.cbor', 'w') as f: f.write(f'{base64.b64encode(authData[55+credentialIdLength:]).decode()}') except InvalidSignature as e: logging.info(f'InvalidSignature {e}') resp.media = {'status': 'ng'} else: logging.info('not support type') resp.media = {'status': 'ng'} else: logging.info('not match RPID') logging.debug(f'{authData[:32].hex()}, {hashlib.sha256(rpid_host.encode()).hexdigest()} [{authData[:32].hex() == hashlib.sha256(rpid_host.encode()).hexdigest()}]') resp.media = {'status': 'ng'} else: logging.info('not find authData') resp.media = {'status': 'ng'}