0

I've been developing an app with TIDAL's auth web sdk. In it, they call SubtleCrypto's wrapKey function using parameters nearly identical to those in the example in the MDN docs.

const wrapCryptoKey = async ({
  keyToWrap,
  password,
  salt
}) => {
  const keyMaterial = await getKeyMaterial(password);
  const wrappingKey = await getWrappingKey(keyMaterial, salt);
  return globalThis.crypto.subtle.wrapKey(
    "raw",
    keyToWrap,
    wrappingKey,
    "AES-KW"
  );
};

getWrappingKey:

const getWrappingKey = (keyMaterial, salt) => {
  return globalThis.crypto.subtle.deriveKey(
    {
      hash: "SHA-256",
      iterations: 1e5,
      name: "PBKDF2",
      salt
    },
    keyMaterial,
    { length: 256, name: "AES-KW" },
    true,
    ["wrapKey", "unwrapKey"]
  );
};

However, when this runs, it throws an error that the cipher is unknown. AES-KW is listed as supported for my node version (v20.14.0). Where am I going wrong?

    at SubtleCrypto.wrapKey (node:internal/crypto/webcrypto:715:10) {
  [cause]: Error: Unknown cipher
      at node:internal/crypto/aes:145:27
      at node:internal/crypto/util:430:19
      at new Promise (<anonymous>)
      at jobPromise (node:internal/crypto/util:428:10)
      at asyncAesKwCipher (node:internal/crypto/aes:145:10)
      at Object.aesCipher (node:internal/crypto/aes:212:27)
      at cipherOrWrap (node:internal/crypto/webcrypto:918:12)
      at SubtleCrypto.wrapKey (node:internal/crypto/webcrypto:715:10)
      at async handleNewCryptoKey (../node_modules/@tidal-music/auth/dist/index.js:273:22)
      at async Module.init (../node_modules/@tidal-music/auth/dist/index.js:479:32) {
    code: 'ERR_CRYPTO_UNKNOWN_CIPHER'
  }
}

I've tried updating to the latest node version and restarting & rebuilding my project to no avail.

3
  • What kind of key is wrappingKey? Commented Jun 2, 2024 at 23:57
  • @AndrewHenle It's the result of deriveKey using PBKDF2. I've updated my question with a snippet. Commented Jun 3, 2024 at 1:03
  • 1
    I can neither reproduce the problem in the browser nor on NodeJS. Please post a complete executable example instead of code fragments. Commented Jun 3, 2024 at 7:53

1 Answer 1

0

This problem was caused by calling wrapKey in the main electron process. Electron uses BoringSSL (as opposed to Node.js using OpenSSL), which does not support AES-KW as an algorithm. From Electron issue #41720:

Node.js proper uses OpenSSL to underpin crypto, whereas Electron uses BoringSSL: a fork of OpenSSL from Chromium pared down significantly compared to Node.js. The actual error here is that the cipher is unsupported, which is a choice made intentionally by BoringSSL. It's implemented in WebCrypto, however, so you're able to use it in the renderer process if you so choose.

As mentioned in that quote, Electron does use Node.js to back crypto in the renderer process. I solved my problem by creating a temporary browser window and moving my calls to TIDAL's api into it and communicating with the main process via ipcRenderer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.