Issue
I am trying to use the SubtleCrypto Web API in Ionic to encrypt data using a public key. I am importing the key in PEM format and then passing it onto window.crypto.subtle.importKey
and then using that result into window.crypto.subtle.encrypt
It would appear that there is a problem with the window.crypto.subtle.importKey
- I am getting a Uncaught (in promise): DataError
when I am trying to import the key.
I am currently using the following methods to import the key:
//Get the public key in CryptoKey format
let importedPublicKey = await window.crypto.subtle.importKey(
"pkcs8",
this.pemPublicToArrayBuffer(serverPublicKey),
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
true,
[]
);
private pemPublicToArrayBuffer(pem) {
var b64Lines = this.removeLines(pem);
var b64Prefix = b64Lines.replace('-----BEGIN PUBLIC KEY-----', '');
var b64Final = b64Prefix.replace('-----END PUBLIC KEY-----', '');
return this.base64ToArrayBuffer(b64Final);
}
private base64ToArrayBuffer(b64) {
var byteString = window.atob(b64);
var byteArray = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
byteArray[i] = byteString.charCodeAt(i);
}
return byteArray;
}
Does anyone possibly know why the key import is failing with the PEM public key?
Solution
I've spent quite some time struggling with this error myself, and now I'm sure I can give you (and anyone else) some good advice on this.
You are passing "pkcs8" as a format to the importKey method, but if you are importing a PUBLIC key, the format is likely to be the "spki" (SubjectPublicKeyInfo) a special format for public keys, while "pkcs8" supposed to be used for PRIVATE keys. That brings us to the next point:
Where did you get this key from? If you are exporting public key with the OpenSSL cli (openssl rsa -pubout -in priv.pem -out pub.pem) then you are getting the key in "spki" format (default one).
You should pass ["encrypt"] as a "usages" parameter to the importKey (instead of an empty array) if you are importing a PUBLIC key, otherwise you will end up with one of the following errors: "SyntaxError: Cannot create a key using the specified key usages" (wrong usage specified for the key) or "InvalidAccessError: key.usages does not permit this operation" (empty array of usages). Things to keep in mind here is that Public keys can be used only to ["encrypt"] and Private keys to ["decrypt"]. I haven't tried to import key pairs though, but as I understand it, you should pass "pkcs8" as a format, and ["encrypt", "decrypt"] for usages.
Even if you set up all the above properly, you may still get the nasty "Uncaught (in promise): DataError", for me it was due to the format mismatch, I've been passing a key in PKCS#1 RSAPublicKey format with the "spki" parameter. So you should probably start from inspecting your key to get exact format and algorithm details from it.
Hope this helps someone. Ivan
Answered By - Ivan A.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.