From 7e6ba6f42d1e25dde9c112e8098dbdafecc7f9c3 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 26 Nov 2019 16:29:49 +0100 Subject: [PATCH] fix: use shake256(m, 114) for Ed448 ID Token _hash claims This restricts the use of Ed448 OKP keys by the provider to a Node.js runtime that supports it (>=12.8.0) --- lib/helpers/initialize_keystore.js | 6 ++++++ lib/helpers/runtime_support.js | 3 +++ package.json | 4 ++-- .../keystore_configuration.test.js | 19 +++++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/helpers/initialize_keystore.js b/lib/helpers/initialize_keystore.js index c6716329f..a55dabbab 100644 --- a/lib/helpers/initialize_keystore.js +++ b/lib/helpers/initialize_keystore.js @@ -5,6 +5,7 @@ const isEqual = require('lodash/isEqual'); const { DEV_KEYSTORE } = require('../consts'); +const runtimeSupport = require('./runtime_support'); const attention = require('./attention'); const instance = require('./weak_cache'); @@ -60,6 +61,11 @@ provide your own in configuration "jwks" property'); } catch (err) { throw new Error('keystore must be a JSON Web Key Set formatted object'); } + + if (!runtimeSupport.shake256 && keystore.get({ kty: 'OKP', crv: 'Ed448' })) { + throw new Error('Ed448 keys are only fully supported to sign ID Tokens with in node runtime >= 12.8.0'); + } + instance(this).keystore = keystore; for (const key of keystore) { // eslint-disable-line no-restricted-syntax registerKey.call(this, key); diff --git a/lib/helpers/runtime_support.js b/lib/helpers/runtime_support.js index f298e0d86..f8af2c6d5 100644 --- a/lib/helpers/runtime_support.js +++ b/lib/helpers/runtime_support.js @@ -1,9 +1,12 @@ const crypto = require('crypto'); const [major, minor] = process.version.substr(1).split('.').map((x) => parseInt(x, 10)); +const xofOutputLength = major > 12 || (major === 12 && minor >= 8); +const shake256 = xofOutputLength && crypto.getHashes().includes('shake256'); module.exports = { 'RSA-OAEP-256': major > 12 || (major === 12 && minor >= 9), EdDSA: major >= 12, KeyObject: typeof crypto.KeyObject !== 'undefined', + shake256, }; diff --git a/package.json b/package.json index 6fdfac4c5..bd6ce5a99 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "debug": "^4.1.1", "ejs": "^2.7.1", "got": "^9.6.0", - "jose": "^1.12.0", + "jose": "^1.14.0", "jsesc": "^2.5.2", "koa": "^2.11.0", "koa-compose": "^4.1.0", @@ -58,7 +58,7 @@ "lru-cache": "^5.1.1", "nanoid": "^2.1.6", "object-hash": "^2.0.0", - "oidc-token-hash": "^4.0.0", + "oidc-token-hash": "^5.0.0", "raw-body": "^2.4.1" }, "devDependencies": { diff --git a/test/configuration/keystore_configuration.test.js b/test/configuration/keystore_configuration.test.js index a37de06a0..fd4749306 100644 --- a/test/configuration/keystore_configuration.test.js +++ b/test/configuration/keystore_configuration.test.js @@ -4,6 +4,7 @@ const jose = require('jose'); const { expect } = require('chai'); const { Provider } = require('../../lib'); +const { EdDSA, shake256 } = require('../../lib/helpers/runtime_support'); describe('configuration.jwks', () => { beforeEach(function () { @@ -52,4 +53,22 @@ describe('configuration.jwks', () => { jwks: this.keystore.toJWKS(true), }); }); + + if (EdDSA) { + it('only enables Ed448 in Node.js >= 12.8.0', async () => { + const ks = new jose.JWKS.KeyStore(); + ks.add(global.keystore.get({ alg: 'RS256' })); + await ks.generate('OKP', 'Ed448'); + + if (shake256) { + expect(() => { + new Provider('http://localhost', { jwks: ks.toJWKS(true) }); + }).not.to.throw(); + } else { + expect(() => { + new Provider('http://localhost', { jwks: ks.toJWKS(true) }); + }).to.throw('Ed448 keys are only fully supported to sign ID Tokens with in node runtime >= 12.8.0'); + } + }); + } });