Проверьте подпись в Node.js из Fido 2.0 или navigator.credentials.get - PullRequest
0 голосов
/ 30 января 2019

Как проверить ответ от «navigator.credentials.get», запущенного в javascript на веб-сервере Node.

У меня работает токен Fido2.0 и генерируется ответ, но я не уверен, как проверить его на веб-сервере.

Я знаю, что мне нужно использовать открытый ключ и подпись, чтобы подтвердить вызов, но я не уверен, какой режим шифрования используется или какую библиотеку мне следует использовать в узле.

    function coerceToArrayBuffer(thing, name) {
        if (typeof thing === 'string') {
            // base64url to base64
            thing = thing.replace(/-/g, '+').replace(/_/g, '/');

            // base64 to Uint8Array
            var str = window.atob(thing);
            var bytes = new Uint8Array(str.length);
            for (var i = 0; i < str.length; i++) {
                bytes[i] = str.charCodeAt(i);
            }
            thing = bytes;
        }

        // Array to Uint8Array
        if (Array.isArray(thing)) {
            thing = new Uint8Array(thing);
        }

        // Uint8Array to ArrayBuffer
        if (thing instanceof Uint8Array) {
            thing = thing.buffer;
        }

        // error if none of the above worked
        if (!(thing instanceof ArrayBuffer)) {
            throw new TypeError('could not coerce \'' + name + '\' to ArrayBuffer');
        }

        return thing;
    }


    function coerceToBase64Url(thing, name) {
        // Array or ArrayBuffer to Uint8Array
        if (Array.isArray(thing)) {
            thing = Uint8Array.from(thing);
        }

        if (thing instanceof ArrayBuffer) {
            thing = new Uint8Array(thing);
        }

        // Uint8Array to base64
        if (thing instanceof Uint8Array) {
            var str = '';
            var len = thing.byteLength;

            for (var i = 0; i < len; i++) {
                str += String.fromCharCode(thing[i]);
            }
            thing = window.btoa(str);
        }

        if (typeof thing !== 'string') {
            throw new Error('could not coerce \'' + name + '\' to string');
        }

        // base64 to base64url
        // NOTE: "=" at the end of challenge is optional, strip it off here
        thing = thing.replace(/\+/g, '-').replace(/\//g, '_').replace(/=*$/g, '');

        return thing;
    }



let challenge = 'eJVGU35uQVHxcOVTypKh8xbPMHcKgC3JVvI9BHWALdpZkaIkIFhnXsADpRUmKzyyniQVJyj3TXm4_iycqKNyyw';
let userID = 'PTVW1ReUO1MoUwC71q2hHaZi4lbsYcaKcxPZikImYYN9gBJtnyy7phnkDOcoib_kSU3M98OZ_CmXINBc0FmYEBcecp-FS2ACcTIUnz2IdPcC5KRNoQrqxsExgbikmLXT';
challenge = coerceToArrayBuffer(challenge);
userID = coerceToArrayBuffer(userID);

let data = {publicKey:{
        'challenge':challenge,
        'timeout':60000,
        'allowCredentials':[
            {'id':userID,'type':'public-key'}
        ]
    }
    };

navigator.credentials.get(data).then((res)=>{
    console.log(coerceToBase64Url(res.response.authenticatorData));
    console.log(coerceToBase64Url(res.response.clientDataJSON));
    console.log(coerceToBase64Url(res.response.signature));
    console.log(coerceToBase64Url(res.response.userHandle));
    });

AuthenticatorData

1011 * SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAIaQ 1013 * res.response.clientDataJSON 1017 * eyJjaGFsbGVuZ2UiOiJlSlZHVTM1dVFWSHhjT1ZUeXBLaDh4YlBNSGNLZ0MzSlZ2STlCSFdBTGRwWmthSWtJRmhuWHNBRHBSVW1Lenl5bmlRVkp5ajNUWG00X2l5Y3FLTnl5dyIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsInR5cGUiOiJ3ZWJhdXRobi5nZXQifQ 1019 * res.response.signature

MEQCIEeeSsO27uRwPXhYiZy9-Air6qiDw9V9gU7Dgv7poi8RAiBulG6PRqqbEiqFpQy7P_ujTQkfC532T5s240A *

...