Open chenkins opened 1 year ago
Interesting. I noticed that the private keys exported by JavaScript are longer than the ones exported by Java.
When decoding the ASN.1, there is additional information, maybe this is required...
I will have a closer look at this tomorrow, so we can be sure keys can be used cross-boundaries.
I just tried this in jshell (Temurin 20):
import java.security.*;
import import java.security.spec.*;
var keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(new ECGenParameterSpec("secps384r1"));
var keyPair = keyGen.generateKeyPair();
Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded())
and this in my browser's console (Brave 1.52.130 Chromium: 114.0.5735.198):
let pemEncoded = atob('ME4CAQAwEAYHKoZIzj0CAQYFK4EEACIENzA1AgEBBDCC6lPePPdsnq2gMH6A+kHb2P9OBgoIrNm2wRLXHmTHJWBeg/EPoeBIWCpOgwFU9Hc=')
let keyData = new Uint8Array(pemEncoded.length)
for (let i=0; i<keyData.length; i++) keyData[i] = pemEncoded.charCodeAt(i)
let privateKey = await crypto.subtle.importKey('pkcs8', keyData, {name: 'ECDH', namedCurve: 'P-384'}, true, ['deriveBits'])
await crypto.subtle.exportKey('jwk', privateKey)
And it does work. Nevertheless I'll add a regression test to the .ts project where we import both a pkcs8-encoded private key as well as an spki-encoded public key. But for now I must assume something else is broken.
Can you share the base64-encoded keys that you used for testing?
@overheadhunter
Update 1: I cannot reproduce currently: when I now generate new user keys P384KeyPair.generate();
in Java, it works (i.e. I can go the hub and add the browser as device with the setup code), and this used to fail consistently (around mid-June).
Update 2: The strange thing is that this always worked in crypto.spec.ts
but not in the browser (I tried both with Firefox and Safari), so I expected the following test to fail, but it did not:
describe('UserKeys recover', () => {
it('x = decrypt(encrypt(x, pass), pass)', async () => {
const encodedPublicKey = "MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEmAkfc+lCMuKBkq3pq/eDuhZZb1z2aS/98EM2DLfMBis0QLoXCG0EE9mgnIRYh0yn+oII0vK7FnJGjDdhhfVlfCXgLkg7P52zRt+X6eVWa8UayFkT3qMLlRYNWDAkyaxJ"
const encryptedPrivateKey= "eyJwMnMiOiJicVhoMGJNeS1QS3FmTFBoYW5DNmZ3IiwicDJjIjoxMDAwMDAwLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUEJFUzItSFM1MTIrQTI1NktXIn0.voAnfslMyy4Kydt8yozQLNSNbHCvuzsOLOwx-RFnLaZB1Ft6RFI3Rw.T0HWPxw9ZOyS8UzE.8YdWEf5buapJle9Ji1wYxGDVSxlVl-i6LKEYaRY2HmZPwj9JfaVrFAXrZd_apD_MUTtcfbjjrKcqJmn7ua01ptWCLko3Vy90QUu2xMgzyhS9_aJKAXn23A9VxKPVqTRP3lqzFJn1AYRqc2XiwzJ2pqNg61QSnQ.mfwMD4dsSdQ81BOkHMs9xw"
const setupCode= "blabla"
const userKeys = await UserKeys.recover(encodedPublicKey,encryptedPrivateKey,setupCode)
console.log(await userKeys.encodedPublicKey())
});
Update-3: I can reproduce the error in the hub/browser with the above key pair:
import static ch.iterate.hub.model.UserKeyJWE.*;
...
userKeys = userKeysRecover(
"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEmAkfc+lCMuKBkq3pq/eDuhZZb1z2aS/98EM2DLfMBis0QLoXCG0EE9mgnIRYh0yn+oII0vK7FnJGjDdhhfVlfCXgLkg7P52zRt+X6eVWa8UayFkT3qMLlRYNWDAkyaxJ",
"eyJwMnMiOiJicVhoMGJNeS1QS3FmTFBoYW5DNmZ3IiwicDJjIjoxMDAwMDAwLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUEJFUzItSFM1MTIrQTI1NktXIn0.voAnfslMyy4Kydt8yozQLNSNbHCvuzsOLOwx-RFnLaZB1Ft6RFI3Rw.T0HWPxw9ZOyS8UzE.8YdWEf5buapJle9Ji1wYxGDVSxlVl-i6LKEYaRY2HmZPwj9JfaVrFAXrZd_apD_MUTtcfbjjrKcqJmn7ua01ptWCLko3Vy90QUu2xMgzyhS9_aJKAXn23A9VxKPVqTRP3lqzFJn1AYRqc2XiwzJ2pqNg61QSnQ.mfwMD4dsSdQ81BOkHMs9xw",
"blabla");
or base-64 only:
2023-07-21 15:51:20,154 [main] INFO ch.iterate.hub.workflows.FirstLoginDeviceSetup - pub=MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEmAkfc+lCMuKBkq3pq/eDuhZZb1z2aS/98EM2DLfMBis0QLoXCG0EE9mgnIRYh0yn+oII0vK7FnJGjDdhhfVlfCXgLkg7P52zRt+X6eVWa8UayFkT3qMLlRYNWDAkyaxJ
2023-07-21 15:51:20,154 [main] INFO ch.iterate.hub.workflows.FirstLoginDeviceSetup - priv=MFcCAQAwEAYHKoZIzj0CAQYFK4EEACIEQDA+AgEBBDAxcuEdOGYwpL/8e8cNY0Fm6VyykwyD+tnQnHY7jyGsuclKSwWNAlwsggkczz6LJtegBwYFK4EEACI=
When I then go to the hub, user key recovery fails in the browser:
Recovering user key failed. DOMException: Data provided to an operation does not meet requirements
recover crypto.ts:340
recoverUserKey SetupUserKey.vue:249
_sfc_render/_cache[8]< SetupUserKey.vue:101
node_modules chunk-CMJ6ZCLF.js:8122
callWithErrorHandling runtime-core.esm-bundler.js:173
callWithAsyncErrorHandling runtime-core.esm-bundler.js:182
invoker runtime-dom.esm-bundler.js:345
Summary
client-side user key generation fails when user keys decrypted in hub.
Reproducibility
With historic key pair, not with newly generated key pairs any more.
Relevant Log Output
private key generated with
P384KeyPair.generate()
in Java causesin
UserKeys.recover
in hub in line