Skip to content

Instantly share code, notes, and snippets.

@My1
Forked from babelouest/hmac-secret-demo.html
Created February 27, 2021 21:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save My1/6b6bb3d536d2b96cdfcabd60ca32c565 to your computer and use it in GitHub Desktop.
Save My1/6b6bb3d536d2b96cdfcabd60ca32c565 to your computer and use it in GitHub Desktop.
<!doctype html>
<html lang="en">
<head>
<!--
inspired by Mozilla Webauthn documentation: https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API
copyright: 2019 Nicolas Mora <nicolas@babelouest.org>
license: MIT
-->
<title>Hmac-Secret webauthn Extension</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/cbor-js-unofficial@0.1.0-a4/cbor.min.js"></script>
<!--<script type="text/javascript" src="cbor.js"></script>-->
</head>
<body>
<div>
Step 1: Create a new credential
</div>
<div>
<button type="button" id="create">New credential with Hmac-Secret extension</button>
</div>
<div id="createResult">
</div>
<hr/>
<div>
Step 2: validate assertion
</div>
<div>
salt1 (required): <input type="text" id="salt1" value="0123456789ABCDEF" maxLength="16" placeholder="16 chars" />
</div>
<div>
salt2 (optional): <input type="text" id="salt2" maxLength="16" placeholder="16 chars" />
</div>
<div>
<button type="button" id="assert">Validate assertion with Hmac-Secret extension</button>
</div>
<div id="assertResult">
</div>
</body>
</html>
<script type="text/javascript">
var credentials = [];
function str2ab(str) {
var buf = new ArrayBuffer(str.length * 2);
var bufView = new Uint16Array(buf);
for (var i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function newCredential() {
var createCredentialDefaultArgs = {
publicKey: {
rp: {
name: "Acme"
},
user: {
id: new Uint8Array(16),
name: "john.p.smith@example.com",
displayName: "John P. Smith"
},
pubKeyCredParams: [{ type: "public-key", alg: -7 }],
attestation: "direct",
timeout: 60000,
extensions: {
hmacCreateSecret: true
},
challenge: new Uint8Array([
0x8C, 0x0A, 0x26, 0xFF, 0x22, 0x91, 0xC1, 0xE9, 0xB9, 0x4E, 0x2E, 0x17, 0x1A, 0x98, 0x6A, 0x73,
0x71, 0x9D, 0x43, 0x48, 0xD5, 0xA7, 0x6A, 0x15, 0x7E, 0x38, 0x94, 0x52, 0x77, 0x97, 0x0F, 0xEF
]).buffer
}
};
console.log("credential options", createCredentialDefaultArgs);
navigator.credentials.create(createCredentialDefaultArgs)
.then((cred) => {
console.log("credential", cred);
credentials.push({
id: cred.rawId,
transports: ["usb", "nfc", "ble"],
type: "public-key"
});
var attStmt = CBOR.decode(cred.response.attestationObject);
console.log("attStmt", attStmt);
if (attStmt.authData[32] & 0x80) {
document.getElementById("createResult").innerHTML = "extension flag set";
} else {
document.getElementById("createResult").innerHTML = "extension flag not set";
}
})
.catch((err) => {
document.getElementById("createResult").innerHTML = "creation error";
console.log("creation error", err);
});
}
function newAssertion() {
var getCredentialDefaultArgs = {
publicKey: {
timeout: 60000,
allowCredentials: credentials,
challenge: new Uint8Array([
0x79, 0x50, 0x68, 0x71, 0xDA, 0xEE, 0xEE, 0xB9, 0x94, 0xC3, 0xC2, 0x15, 0x67, 0x65, 0x26, 0x22,
0xE3, 0xF3, 0xAB, 0x3B, 0x78, 0x2E, 0xD5, 0x6F, 0x81, 0x26, 0xE2, 0xA6, 0x01, 0x7D, 0x74, 0x50
]),
extensions: {
hmacGetSecret: {
salt1: str2ab(document.getElementById("salt1").value)
}
}
}
};
if (document.getElementById("salt2").value) {
getCredentialDefaultArgs.publicKey.extensions.hmacGetSecret.salt2 = str2ab(document.getElementById("salt2").value);
}
console.log("assertion option", getCredentialDefaultArgs);
navigator.credentials.get(getCredentialDefaultArgs)
.then((assertion) => {
console.log("assertion", assertion);
if (assertion.response.authenticatorData[32] & 0x80) {
document.getElementById("assertResult").innerHTML = "extension flag set";
} else {
document.getElementById("assertResult").innerHTML = "extension flag not set";
}
})
.catch((err) => {
document.getElementById("assertResult").innerHTML = "assertion error";
console.log("assertion error", err);
});
}
window.onload = function() {
document.getElementById("create").onclick = newCredential;
document.getElementById("assert").onclick = newAssertion;
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment