如何验证来自节点Web服务器上以javascript运行的“ navigator.credentials.get”的响应。
我已经使Fido2.0令牌正常工作并生成了响应,但是我不确定如何在Web服务器上对其进行验证。
我知道我必须使用公钥和签名来验证挑战,但是我不确定在节点中使用哪种加密模式或应该使用哪个库。
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
SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAIaQ
res.response.clientDataJSON
eyJjaGFsbGVuZ2UiOiJlSlZHVTM1dVFWSHhjT1ZUeXBLaDh4YlBNSGNLZ0MzSlZ2STlCSFdBTGRwWmthSWtJRmhuWHNBRHBSVW1Lenl5bmlRVkp5ajNUWG00X2l5Y3FLTnl5dyIsIm9yaWdpbiI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsInR5cGUiOiJ3ZWJhdXRobi5nZXQifQ
响应响应签名
MEQCIEeeSsO27uRwPXhYiZy9-Air6qiDw9V9gU7Dgv7poi8RAiBulG6PRqqbEiqFpQy7P_ujTQkfC532T5sCr0IsgwO3lA