简体   繁体   中英

window.crypto.subtle.importkey and sign issue

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,

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)); } })();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM