crypto.subtle.sign() doesn't seem to be doing any signing?

81 views Asked by At

My code:

/*
Fetch the contents of the "message" textbox, and encode it
in a form we can use for the sign operation.
*/
function getMessageEncoding() {
  const messageBox = 'hello world!';
  let message = messageBox.value;
  let enc = new TextEncoder();
  return enc.encode(message);
}

async function main() {
    let encoded = getMessageEncoding();
    window.crypto.subtle.sign(
      {
        name: "ECDSA",
        hash: { name: "SHA-384" },
      },
     {"alg":"ES256","crv":"P-256","d":"KRiXxoIFHmBQJdoCsqB8Bc9_f2Z-QCdRgoydMKdoL04","ext":true,"key_ops":["sign"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"},
  encoded,
    ).then(signature => {
    console.log(signature);
    alert('test');
  });
  alert(signature);
}

main();

(the private key is a dummy private key and not a production one)

When I run it it doesn't do anything. I'd expect it to put the signature into the JS console?

Here it is on JS Fiddle:

https://jsfiddle.net/pwuersfL/1/

Any ideas?

1

There are 1 answers

0
Topaco On BEST ANSWER

In the posted code the key import with importKey() is missing. importKey() converts the JWK into a CryptoKey which can be processed by sign().

In the following code the missing import is added (plus verifying):

function getMessageEncoding() {
    //const messageBox = 'hello world!';
    //let message = messageBox.value;
    let message = 'hello world!'; // for testing
    let enc = new TextEncoder();
    return enc.encode(message);
}

async function main() {
    
    // sign
    let encoded = getMessageEncoding();
    let jwk = {"alg":"ES256","crv":"P-256","d":"KRiXxoIFHmBQJdoCsqB8Bc9_f2Z-QCdRgoydMKdoL04","ext":true,"key_ops":["sign"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"};
    let key =  await window.crypto.subtle.importKey("jwk", jwk, {name: "ECDSA", namedCurve: "P-256"},true,["sign"]); // Fix: import the key 
    let signature = await window.crypto.subtle.sign(
        {
            name: "ECDSA",
            hash: { name: "SHA-384" },
        },
        key,
        encoded,
    );
    console.log(ab2hex(signature));
    
    // verify
    jwk = {"alg":"ES256","crv":"P-256","ext":true,"key_ops":["verify"],"kty":"EC","x":"FKwqyGd4i2NAl8RUXCCBRCAIbcpeGyfyXwgA_AWHb8Y","y":"njxhw5O6zGVkBlcPDKYj0E-6VO1giHTUkJWBhgKNqd8"};
    key =  await window.crypto.subtle.importKey("jwk", jwk, {name: "ECDSA", namedCurve: "P-256"},true,["verify"]); 
    let verified = await window.crypto.subtle.verify(
        {
            name: "ECDSA",
            hash: { name: "SHA-384" },
        },
        key,
        signature,
        encoded,
    );
    console.log(verified);
}
 
// helper: hex encoding
function ab2hex(ab) { 
    return Array.prototype.map.call(new Uint8Array(ab), x => ('00' + x.toString(16)).slice(-2)).join('');
}

main();

The code produces for P-256 a 64 bytes signature in IEEE P1363 format (r|s), which can be successfully verified with the public key.