Reputation: 979
In typescript I have the following code to sign a message with the ecdsa method and the SHA-512 algorithm.
const pem = "-----BEGIN PRIVATE KEY-----\nByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgUIcMiv/YpEgR1CKRsL6sS85BVo6lYft/S5nIjTlCHvihRANCAATykP7bc8\n-----END PRIVATE KEY-----"
// fetch the part of the PEM string between header and footer
const pemHeader = "-----BEGIN PRIVATE KEY-----";
const pemFooter = "-----END PRIVATE KEY-----";
const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);
// base64 decode the string to get the binary data
const binaryDerString = window.atob(pemContents);
// convert from a binary string to an ArrayBuffer
const binaryDer = this.str2ab(binaryDerString);
return window.crypto.subtle.importKey(
"pkcs8",
binaryDer,
{
name: "RSA-PSS",
hash: "SHA-512",
},
true,
["sign"]
);
}
I have this method to sign the message:
createSignature2(){
let privateKey = this.importPrivateKey();
console.log(privateKey)
let data = this.str2ab("Test buffer")
let sign = window.crypto.subtle.sign(
{
name: "ECDSA",
hash: {name: "SHA-512"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
},
privateKey, //from generateKey or importKey above
data //ArrayBuffer of data you want to sign
)
.then(function(signature){
//returns an ArrayBuffer containing the signature
console.log(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
}
I get an error:
Argument of type 'Promise<CryptoKey>' is not assignable to parameter of type 'CryptoKey'.
Type 'Promise<CryptoKey>' is missing the following properties from type 'CryptoKey': algorithm, extractable, type, usages
What am I missing here?
Thank you,
Upvotes: 0
Views: 1737
Reputation: 49341
The key import is incorrect. RSA-PSS
imports an RSA key (for a signing/verification with RSASSA-PSS as padding). However, for ECDSA it makes no sense to import an RSA key. RSA and ECDSA are completely different algorithms. Instead of the RSA key, an EC key must be imported and thereby the EC curve must be specified.
Regarding the posted key itself: As already mentioned in the comment, this does not correspond to any valid format and it represents neither an RSA nor an EC key.
Another point is about the syntax used. The code often applies then()
, but also constructions where the await
keyword is missing. Here, either only async/await
(in a correct way) or only then()
should be used consistently (s. here for the difference).
Furthermore, str2ab()
is missing.
The following code shows an example of importing an EC key including signing with ECDSA. P-521 is used as curve. As private key a PEM encoded sample EC key in PKCS#8 format is applied.
In the code the async/await
syntax is applied (because this is clearer in my opinion). str2ab()
is taken from the WebCrypto API documentation. ab2str()
is the inverse function to this. The signature is Base64 encoded for display:
(async () => {
createSignature2(); // Fix: apply consistently async/await syntax
async function createSignature2(){
const privateKey = await importPrivateKey();
console.log(privateKey)
const data = str2ab("Test buffer")
const sign = await window.crypto.subtle.sign({name: "ECDSA",hash: {name: "SHA-512"}}, privateKey, data);
console.log(window.btoa(ab2str(sign)));
}
async function importPrivateKey() {
const pem = `-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA3G3l+QFixI4fD4zW
lC9n7xnT/7MS4bm6Ge6KXPmesmy9AARSdysdhWLXq51hvd/4F4Rd+ZYWn8bdeN58
zOJdRAOhgYkDgYYABAGBW8V/nf4yXdePGpotIL8WNR1182yBdcztCpWQUkL9TOEy
vhhnf8SwtRDglbjCBiVONw4+WjC3pRfo3yTmee+mEQE3peJArA1zOFz9WJZhigA9
aK3t8BUbisZ38C4jcRuGgaBYUvg3ndMdqZnsNdbcg7sKOM9szCUvzGWkIWn2l4lW
zA==
-----END PRIVATE KEY-----`;
const pemHeader = "-----BEGIN PRIVATE KEY-----";
const pemFooter = "-----END PRIVATE KEY-----";
const pemContents = pem.substring(pemHeader.length, pem.length - pemFooter.length);
const binaryDerString = window.atob(pemContents);
const binaryDer = str2ab(binaryDerString);
return await window.crypto.subtle.importKey("pkcs8", binaryDer,{name: "ECDSA",namedCurve: "P-521"}, true, ["sign"]); // Fix: import ECDSA key
}
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 ab2str(buf) {
return String.fromCharCode.apply(null, new Uint8Array(buf));
}
})();
Upvotes: 0