Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undefined y point for kty OKP #348

Closed
2 tasks done
OR13 opened this issue Jan 22, 2022 · 1 comment
Closed
2 tasks done

undefined y point for kty OKP #348

OR13 opened this issue Jan 22, 2022 · 1 comment

Comments

@OR13
Copy link

OR13 commented Jan 22, 2022

What happened?

This is a very minor point, but it might confuse some folks less familiar with OKP.

decrypted unprotectedHeader epk contains undefined y point for kty okp.

I would not expect to see a y point for X25519 ever, even if it was undefined.

Version

4.3.8

Runtime

Node.js

Runtime Details

v14.15.5

Code to reproduce

import * as jose from 'jose';
import { TextEncoder, TextDecoder } from 'util';

const encoder = new TextEncoder();
const decoder = new TextDecoder();
const alg = 'ECDH-ES+A256KW';
const crv = 'X25519';
const enc = 'A256GCM';
it('can generate key pair', async () => {
  const { publicKey, privateKey } = await jose.generateKeyPair(alg, {
    crv,
  });

  const publicKeyJwk = await jose.exportJWK(publicKey);

  expect(publicKeyJwk.kty).toBe('OKP');
  expect(publicKeyJwk.crv).toBe(crv);
  expect(publicKeyJwk.x).toBeDefined();
  expect(publicKeyJwk.d).not.toBeDefined();

  const privateKeyJwk = await jose.exportJWK(privateKey);
  expect(privateKeyJwk.kty).toBe('OKP');
  expect(privateKeyJwk.crv).toBe(crv);
  expect(privateKeyJwk.x).toBeDefined();
  expect(privateKeyJwk.d).toBeDefined();
});

it('can encrypt / decrypt', async () => {
  const { publicKeyJwk, privateKeyJwk } = {
    publicKeyJwk: {
      kty: 'OKP',
      crv: 'X25519',
      x: 'sJ4qz3Dvax-H2TVRDYXkK1onaafdO3mRL-qLj-KKKEI',
    },
    privateKeyJwk: {
      kty: 'OKP',
      crv: 'X25519',
      x: 'sJ4qz3Dvax-H2TVRDYXkK1onaafdO3mRL-qLj-KKKEI',
      d: 'mK2jV5pAes3Zw6wZZ89_6lJtDtyB_RltGVZzRXoO2ns',
    },
  };
  const message = {
    message: 'It’s a dangerous business, Frodo, going out your door.',
  };
  const plaintext = encoder.encode(JSON.stringify(message));
  const encryptor = new jose.GeneralEncrypt(plaintext);
  encryptor.setProtectedHeader({ enc });
  encryptor
    .addRecipient(await jose.importJWK(publicKeyJwk, alg))
    .setUnprotectedHeader({ alg, kid: 'did:example:123#key-0' });
  encryptor
    .addRecipient(await jose.importJWK(publicKeyJwk, alg))
    .setUnprotectedHeader({ alg, kid: 'did:example:123#key-1' });
  const ciphertext = await encryptor.encrypt();
  console.log(JSON.stringify(ciphertext, null, 2));
  const decrypted = await jose.generalDecrypt(
    ciphertext,
    await jose.importJWK(privateKeyJwk, alg)
  );
  expect(JSON.parse(decoder.decode(decrypted.plaintext))).toEqual(message);
  console.log(decrypted);

  // {
  //   plaintext: <Buffer 7b 22 6d 65 73 73 61 67 65 22 3a 22 49 74 e2 80 99 73 20 61 20 64 61 6e 67 65 72 6f 75 73 20 62 75 73 69 6e 65 73 73 2c 20 46 72 6f 64 6f 2c 20 67 6f ... 20 more bytes>,
  //   protectedHeader: { enc: 'A256GCM' },
  //   unprotectedHeader: {
  //     alg: 'ECDH-ES+A256KW',
  //     kid: 'did:example:123#key-0',
  //     epk: {
  //       x: 'nLv1BtwDPz0oOJAJql1fGvu0LPeMuFnUXsC1wZ2tbh0',
  //       y: undefined,
  //       crv: 'X25519',
  //       kty: 'OKP'
  //     }
  //   }
  // }
});

Required

  • I have searched the issues tracker and discussions for similar topics and couldn't find anything related.
  • I agree to follow this project's Code of Conduct
@OR13 OR13 added the triage label Jan 22, 2022
@panva
Copy link
Owner

panva commented Jan 22, 2022

This is a very minor point

I agree! The problem is not decrypt, but rather encrypt that adds the y value even when ECDH was done with Curve25519 or Curve448. Decrypt then just echoes the unprotected header that was passed in. This is also only a problem for unprotected header since protected one is serialized as JSON then base64url encoded, so undefined is never a part of it.

I have a fix coming for this.

@panva panva closed this as completed in dd6775e Jan 22, 2022
@panva panva removed the triage label Jan 22, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Apr 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants