I am trying to do client-side validation of the contents of a file but am not very familiar with web crypto and am struggling to make progress.
Currently I am facing the an error saying:
Cannot create a key using the specified key usages.
Here is a sandbox URL with the below example
Using the SubjectPublicKeyInfo instructions on the Subtle Crypto documentation.
I have the following javascript
void async function main() {
const [ contentBytes, signatureBase64, publicKeyString ] = await Promise.all([
(await fetch('./file.js')).arrayBuffer(),
(await fetch('./file.js.signature.b64')).text(),
(await fetch('./keys/rsa_public.pem')).text(),
])
const publicKeyBytes = await importRsaKey(publicKeyString)
await crypto.subtle.verify('RSA-SHA256', publicKeyBytes, signatureBase64, contentBytes)
}()
My implementation for the importRsaKey function is
function str2ab(str) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
function importRsaKey(pem) {
const pemContents = pem.trim().split('\n').
filter(v => !v.includes('--')).join('')
const binaryDerString = window.atob(pemContents);
const binaryDer = str2ab(binaryDerString);
return window.crypto.subtle.importKey(
"spki",
binaryDer,
{
name: "RSA-OAEP",
hash: "SHA-256"
},
true,
['verify']
);
}
I generated the public/private keys and signature using:
openssl genpkey -algorithm RSA -out rsa_private.pem -pkeyopt rsa_keygen_bits:2048
openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem
openssl dgst -sha256 -sign "./rsa_private.pem" -out file.js.signature file.js
base64 file.js.signature > file.js.signature.b64