Last active
April 12, 2023 12:26
-
-
Save colek42/b47e5dde5d180da60a264b94b6af4a94 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function signTextWithYubiKey() { | |
try { | |
// Create a new credential | |
const challenge = new Uint8Array(32); | |
crypto.getRandomValues(challenge); | |
const publicKeyCredentialCreationOptions = { | |
challenge, | |
rp: { name: 'example.com' }, | |
user: { | |
id: new Uint8Array(16), | |
name: 'user@example.com', | |
displayName: 'User' | |
}, | |
pubKeyCredParams: [ | |
{ type: 'public-key', alg: -7 }, // ES256 | |
{ type: 'public-key', alg: -257 } // RS256 | |
], | |
authenticatorSelection: { | |
authenticatorAttachment: 'cross-platform' | |
}, | |
timeout: 60000, | |
attestation: 'none' | |
}; | |
const credential = await navigator.credentials.create({ | |
publicKey: publicKeyCredentialCreationOptions | |
}); | |
console.log('New credential:', credential); | |
// Sign the text "Hello, World!" with the YubiKey | |
const textToSign = "Hello, World!"; | |
const textChallenge = new TextEncoder().encode(textToSign); | |
const publicKeyCredentialRequestOptions = { | |
challenge: textChallenge, | |
allowCredentials: [ | |
{ | |
type: 'public-key', | |
id: credential.rawId, | |
transports: ['usb'] | |
} | |
], | |
timeout: 60000 | |
}; | |
const assertion = await navigator.credentials.get({ | |
publicKey: publicKeyCredentialRequestOptions | |
}); | |
const signature = assertion.response.signature; | |
console.log('Signed text:', signature); | |
// Retrieve the public key object from the attestation response | |
const attestationBuffer = new Uint8Array(credential.response.attestationObject).buffer; | |
const attestation = CBOR.decode(attestationBuffer); | |
const publicKeyObject = attestation.authData.slice(37); | |
return { publicKeyObject, signature }; | |
} catch (error) { | |
console.error('Error:', error); | |
} | |
} | |
async function verifySignature(publicKeyObject, signature, text) { | |
try { | |
// Import the public key object | |
const publicKey = await crypto.subtle.importKey( | |
'raw', | |
publicKeyObject, | |
{ name: 'ECDSA', namedCurve: 'P-256' }, | |
true, | |
['verify'] | |
); | |
// Verify the signature | |
const textBytes = new TextEncoder().encode(text); | |
const isValid = await crypto.subtle.verify( | |
{ name: 'ECDSA', hash: { name: 'SHA-256' } }, | |
publicKey, | |
signature, | |
textBytes | |
); | |
if (isValid) { | |
console.log('The signature is valid.'); | |
} else { | |
console.log('The signature is invalid.'); | |
} | |
} catch (error) { | |
console.error('Error:', error); | |
} | |
} | |
(async () => { | |
const { publicKeyObject, signature } = await signTextWithYubiKey(); | |
await verifySignature(publicKeyObject, signature, "Hello, World!"); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment