🐛 Key must be one of type CryptoKey, KeyObject, or Uint8Array error when using jose with react-native-quick-crypto
What's happening?
When using react-native-quick-crypto together with the jose library in a React Native app, calling exportJWK() throws the following error:
TypeError: Key must be one of type CryptoKey, KeyObject, or Uint8Array. Received an instance of CryptoKey
Reproducible Code
const { publicKey, privateKey } = await generateKeyPair('ES256', { extractable: true });
const publicKeyJwk = await exportJWK(publicKey);
Relevant log output
TypeError: Key must be one of type CryptoKey, KeyObject, or Uint8Array. Received an instance of CryptoKey
Device
iPhone 16
QuickCrypto Version
0.7.13
Can you reproduce this issue in the QuickCrypto Example app?
I didn't try (⚠️ your issue might get ignored & closed if you don't try this)
Additional information
- [ ] I am using Expo
- [x] I have read the Troubleshooting Guide
- [x] I agree to follow this project's Code of Conduct
- [x] I searched for similar issues in this repository and found none.
react-native-quick-crypto CryptoKey instances are missing its Symbol.toStringTag and so this fails. Filling in the the tag should help.
@panva hi 👋
I attempted to add the Symbol.toStringTag values for the RNQC classes, and add tests in this commit. Any idea why I'd be seeing the following?
fail: importJwk - error: Cannot read property 'slice' of undefined
fail: exportJWK - error: Invalid argument - options.modulusLength is not a number: undefined
Is the first one just a bad JWK, missing some key/value?
Is the second one missing some options?
Thought I'd take a quick stab at this.
@boorad do you have a full error trace and code you're executing for these?
It's a liitle wack, because RN:
TypeError: Cannot read property 'slice' of undefined
at getHashLength (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app=com.margelo.rnqc.example.RNQCExample:153197:36)
at checkEncCryptoKey (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app=com.margelo.rnqc.example.RNQCExample:153314:39)
at ?anon_0_ (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app=com.margelo.rnqc.example.RNQCExample:153770:79)
at next (native)
I made a change, and got past the `options.modulusLength issue. Back to the OG error message:
TypeError: Key must be one of type CryptoKey, KeyObject, or Uint8Array.
at ?anon_0_ (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app=com.margelo.rnqc.example.RNQCExample:154268:28)
at next (native)
...
at keyToJWK (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app=com.margelo.rnqc.example.RNQCExample:154248:27)
at ?anon_0_ (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app=com.margelo.rnqc.example.RNQCExample:154232:38)
at next (native)
...
at exportJWK
...
@panva code pushed, stacks above ^
TypeError: Cannot read property 'slice' of undefined at getHashLength
The algorithm member of the key is missing required property for its given type. In this case, RsaHashedKeyAlgorithm missing its hash property which itself is supposed to be a KeyAlgorithm dictionary.
Invalid argument - options.modulusLength is not a number: undefined
I am not sure where this is coming from.
Edit:
that's a bad call you're doing to node:crypto generateKeyPair here
crypto.generateKeyPair('rsa', {} /* <- missing modulusLength */, (err, publicKey) => {
if (err) {
throw err;
}
const publicKeyJwk = exportJWK(publicKey as CryptoKey);
console.log(publicKeyJwk);
});
Also the result of this is a KeyObject, not CryptoKey.
I made a change, and got past the `options.modulusLength issue. Back to the OG error message:
It's likely you're returning a symbol string tag values PublicKeyObject, PrivateKeyObject, AsymmetricKeyObject, or SecretKeyObject instead of just KeyObject which is what Node.js is doing for all these subclasses.
any update on this?