PeculiarVentures / PKI.js

PKI.js is a pure JavaScript library implementing the formats that are used in PKI applications (signing, encryption, certificate requests, OCSP and TSP requests/responses). It is built on WebCrypto (Web Cryptography API) and requires no plug-ins.
http://pkijs.org
Other
1.3k stars 204 forks source link

Cannot successfully encrypt privateKey due to InvalidAccessError #281

Open JaHajRF opened 4 years ago

JaHajRF commented 4 years ago

Hello,

I'm creating mobile app, using react native with WebviewCrypto.

Error: During privateKey encryption and parsing proccess i got:


"InvalidAccessError: key is not extractable"

even if key has extractable flag set to true.

After some debugging I've found that calling deriveKey from crypto subtle is throwing an error. To be specific 'false' parameter is passed to function call, which makes key export failing.


    sequence = sequence.then(result => this.deriveKey({
      name: "PBKDF2",
      hash: {
        name: parameters.hmacHashAlgorithm
      },
      salt: saltView,
      iterations: parameters.iterationCount
    }, result, parameters.contentEncryptionAlgorithm, false, ["encrypt"]), error => Promise.reject(error)); //endregion

It looks like a bug.

Workaround: My temporary solution is to monkey patch it.


const origDeriveKey = crypto.subtle.deriveKey;
  crypto.subtle.deriveKey = (algorithm,
    baseKey,
    derivedKeyAlgorithm,
    extractable,
    keyUsages) => origDeriveKey(
      algorithm,
      baseKey,
      derivedKeyAlgorithm,
      true,
      keyUsages)

Fix: Change deriveKey parameter from 'false' -> 'true'.

YuryStrozhevsky commented 4 years ago

@JaHajRF Derived keys are not for exporting. Moreover, I am pretty sure you got the error not while running any PKI.js code, but in your own code when you were trying to make something with secondary keys produced by PKI.js. I do not see any bugs in PKIjs here.

JaHajRF commented 4 years ago

@YuryStrozhevsky thanks for reply. I still think that this is caused by pki.js package.

Let me be more explicit, about the issue:

During my privateKey encryption and parsing proccess I'm calling parseInternalValues


    const pkcs8 = new pkijs.PKCS8ShroudedKeyBag(schema);
    await pkcs8.parseInternalValues({
        password: passwordBuffer,
    });

both schema and passwordBuffer looks fine.

On debbuging proccess I've found that parseInternalValues at some point is calling this line of code, which is within decryptEncryptedContentInfo function:


    sequence = sequence.then(result => {
      this.deriveKey({
      name: "PBKDF2",
      hash: {
        name: hmacHashAlgorithm
      },
      salt: saltView,
      iterations: iterationCount
    }, result, contentEncryptionAlgorithm, false, ["decrypt"])}, error => Promise.reject(error)); //endregion

passed false parameter is failing my password parsing proccess with "InvalidAccessError: key is not extractable".

And what is worth to mention is the fact that my tests on node environment are passing. So apparently this solution is not working for react-native with WebCrypto.