From e8ad38993e29747098f7fd1594dde4ce893ba802 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Wed, 1 Jul 2020 13:13:34 +0200 Subject: [PATCH] fix: handle private EC keys without public component (#86) Only possible to handle when KeyObject API is available in the runtime. closes #85 --- lib/help/key_utils.js | 18 +++++++++++++++--- test/jwk/import.test.js | 27 ++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/help/key_utils.js b/lib/help/key_utils.js index 887855ea00..efd7f90bec 100644 --- a/lib/help/key_utils.js +++ b/lib/help/key_utils.js @@ -4,6 +4,7 @@ const { EOL } = require('os') const errors = require('../errors') +const { keyObjectSupported } = require('./runtime_support') const { createPublicKey } = require('./key_object') const base64url = require('./base64url') const asn1 = require('./asn1') @@ -89,10 +90,21 @@ const keyObjectToJWK = { const ECPrivateKey = asn1.get('ECPrivateKey') const { privateKey, algorithm: { parameters: { value: crv } } } = PrivateKeyInfo.decode(der) - const { privateKey: d, publicKey: { data: publicKey } } = ECPrivateKey.decode(privateKey) + const { privateKey: d, publicKey } = ECPrivateKey.decode(privateKey) + + if (typeof publicKey === 'undefined') { + if (keyObjectSupported) { + return { + ...keyObjectToJWK.ec.public(createPublicKey(keyObject)), + d: base64url.encodeBuffer(d) + } + } - const x = publicKey.slice(1, ((publicKey.length - 1) / 2) + 1) - const y = publicKey.slice(((publicKey.length - 1) / 2) + 1) + throw new errors.JOSENotSupported('Private EC keys without the public key embedded are not supported in your Node.js runtime version') + } + + const x = publicKey.data.slice(1, ((publicKey.data.length - 1) / 2) + 1) + const y = publicKey.data.slice(((publicKey.data.length - 1) / 2) + 1) return { kty: 'EC', diff --git a/test/jwk/import.test.js b/test/jwk/import.test.js index a9aed164a4..dc21e1b731 100644 --- a/test/jwk/import.test.js +++ b/test/jwk/import.test.js @@ -3,7 +3,7 @@ const test = require('ava') const { JWS, JWE, JWK: { asKey, importKey, generate }, errors } = require('../..') const { edDSASupported, keyObjectSupported } = require('../../lib/help/runtime_support') -const { createSecretKey } = require('../../lib/help/key_object') +const { createSecretKey, createPrivateKey } = require('../../lib/help/key_object') const { generateKeyPairSync } = require('../macros/generate') const fixtures = require('../fixtures') @@ -177,3 +177,28 @@ if (keyObjectSupported) { }, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'X.509 certificates are not supported in your Node.js runtime version' }) }) } + +// https://github.com/panva/jose/issues/85 +{ + const pem = `-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCXpUVoM4DfOtMyRVtC +eGSpVL+1tMBirnUGJHY6Y7mSHg== +-----END PRIVATE KEY-----` + + if (keyObjectSupported) { + test('EC private keys without public one', t => { + asKey(createPrivateKey(pem)) + asKey(pem) + t.pass() + }) + } else { + test('EC private keys without public one', t => { + t.throws(() => { + asKey(createPrivateKey(pem)) + }, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'Private EC keys without the public key embedded are not supported in your Node.js runtime version' }) + t.throws(() => { + asKey(pem) + }, { instanceOf: errors.JOSENotSupported, code: 'ERR_JOSE_NOT_SUPPORTED', message: 'Private EC keys without the public key embedded are not supported in your Node.js runtime version' }) + }) + } +}