From cd68a98dedfdd9b231d5089b8110e468e066c585 Mon Sep 17 00:00:00 2001 From: Yamil Asusta Date: Wed, 7 Jan 2026 14:09:04 -0400 Subject: [PATCH 1/3] fix!: digest support --- lib/templates/keyinfo.tpl.xml.js | 17 ++++++++++++++--- lib/xmlenc.js | 4 +++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/templates/keyinfo.tpl.xml.js b/lib/templates/keyinfo.tpl.xml.js index b629b37..b66a00f 100644 --- a/lib/templates/keyinfo.tpl.xml.js +++ b/lib/templates/keyinfo.tpl.xml.js @@ -1,10 +1,21 @@ var escapehtml = require('escape-html'); -module.exports = ({ encryptionPublicCert, encryptedKey, keyEncryptionMethod, keyEncryptionDigest }) => ` +const DIGEST_ALGORITHMS = { + 'sha1': 'http://www.w3.org/2000/09/xmldsig#sha1', + 'sha256': 'http://www.w3.org/2001/04/xmlenc#sha256', + 'sha512': 'http://www.w3.org/2001/04/xmlenc#sha512' +}; + +module.exports = ({ encryptionPublicCert, encryptedKey, keyEncryptionMethod, keyEncryptionDigest }) => { + const digestUri = DIGEST_ALGORITHMS[keyEncryptionDigest] || keyEncryptionDigest; + + // RSA-OAEP requires it. RSA-1.5 must NOT have it. + const isOAEP = keyEncryptionMethod && keyEncryptionMethod.includes('rsa-oaep'); + return ` - + ${isOAEP ? `` : ''} ${encryptionPublicCert} @@ -15,4 +26,4 @@ module.exports = ({ encryptionPublicCert, encryptedKey, keyEncryptionMethod, key `; - +} \ No newline at end of file diff --git a/lib/xmlenc.js b/lib/xmlenc.js index 8b2bc11..587876d 100644 --- a/lib/xmlenc.js +++ b/lib/xmlenc.js @@ -255,9 +255,11 @@ function decryptKeyInfo(doc, options) { if (keyDigestMethod) { const keyDigestMethodAlgorithm = keyDigestMethod.getAttribute('Algorithm'); switch (keyDigestMethodAlgorithm) { - case 'http://www.w3.org/2000/09/xmldsig#sha256': + case 'http://www.w3.org/2001/04/xmlenc#sha256': + case 'http://www.w3.org/2000/09/xmldsig#sha256': // backwards compatibility for previous wrong usage oaepHash = 'sha256'; break; + case 'http://www.w3.org/2001/04/xmlenc#sha512': case 'http://www.w3.org/2000/09/xmldsig#sha512': oaepHash = 'sha512'; break; From 7f68d302880127f956da41229d0a6754b431bfff Mon Sep 17 00:00:00 2001 From: Adam Mcgrath Date: Tue, 30 Jun 2026 13:30:08 +0100 Subject: [PATCH 2/3] chore: add tests --- test/xmlenc.digest.js | 136 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 test/xmlenc.digest.js diff --git a/test/xmlenc.digest.js b/test/xmlenc.digest.js new file mode 100644 index 0000000..e579a43 --- /dev/null +++ b/test/xmlenc.digest.js @@ -0,0 +1,136 @@ +var assert = require('assert'); +var fs = require('fs'); +var xmlenc = require('../lib'); +var keyinfoTemplate = require('../lib/templates/keyinfo.tpl.xml'); + +var RSA_OAEP = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p'; +var RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'; + +describe('keyEncryptionDigest', function () { + + describe('keyinfo template DigestMethod', function () { + function render(overrides) { + return keyinfoTemplate(Object.assign({ + encryptionPublicCert: '', + encryptedKey: 'ZW5jcnlwdGVkS2V5', + keyEncryptionMethod: RSA_OAEP, + keyEncryptionDigest: 'sha1' + }, overrides)); + } + + it('maps sha1 to the xmldsig sha1 URI', function () { + var xml = render({ keyEncryptionDigest: 'sha1' }); + assert(xml.includes('')); + }); + + it('maps sha256 to the xmlenc sha256 URI', function () { + var xml = render({ keyEncryptionDigest: 'sha256' }); + assert(xml.includes('')); + }); + + it('maps sha512 to the xmlenc sha512 URI', function () { + var xml = render({ keyEncryptionDigest: 'sha512' }); + assert(xml.includes('')); + }); + + it('passes through an unknown digest value unchanged', function () { + var custom = 'http://example.org/custom#sha3-256'; + var xml = render({ keyEncryptionDigest: custom }); + assert(xml.includes('')); + }); + + it('includes a DigestMethod for RSA-OAEP', function () { + var xml = render({ keyEncryptionMethod: RSA_OAEP, keyEncryptionDigest: 'sha256' }); + assert(xml.includes(' Date: Wed, 1 Jul 2026 09:45:44 +0100 Subject: [PATCH 3/3] chore: comment and test updates --- lib/templates/keyinfo.tpl.xml.js | 3 ++- lib/xmlenc.js | 2 +- test/xmlenc.digest.js | 26 +++++++++++++++++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/templates/keyinfo.tpl.xml.js b/lib/templates/keyinfo.tpl.xml.js index b66a00f..9859d5f 100644 --- a/lib/templates/keyinfo.tpl.xml.js +++ b/lib/templates/keyinfo.tpl.xml.js @@ -1,6 +1,7 @@ var escapehtml = require('escape-html'); const DIGEST_ALGORITHMS = { + // SHA-2 was published after 2000/09/xmldsig was locked, so sha256/sha512 live under 2001/04/xmlenc. 'sha1': 'http://www.w3.org/2000/09/xmldsig#sha1', 'sha256': 'http://www.w3.org/2001/04/xmlenc#sha256', 'sha512': 'http://www.w3.org/2001/04/xmlenc#sha512' @@ -9,7 +10,7 @@ const DIGEST_ALGORITHMS = { module.exports = ({ encryptionPublicCert, encryptedKey, keyEncryptionMethod, keyEncryptionDigest }) => { const digestUri = DIGEST_ALGORITHMS[keyEncryptionDigest] || keyEncryptionDigest; - // RSA-OAEP requires it. RSA-1.5 must NOT have it. + // RSA-1.5 doesn't hash the key, so it has no digest or DigestMethod. RSA-OAEP does. const isOAEP = keyEncryptionMethod && keyEncryptionMethod.includes('rsa-oaep'); return ` diff --git a/lib/xmlenc.js b/lib/xmlenc.js index 587876d..50fa39e 100644 --- a/lib/xmlenc.js +++ b/lib/xmlenc.js @@ -260,7 +260,7 @@ function decryptKeyInfo(doc, options) { oaepHash = 'sha256'; break; case 'http://www.w3.org/2001/04/xmlenc#sha512': - case 'http://www.w3.org/2000/09/xmldsig#sha512': + case 'http://www.w3.org/2000/09/xmldsig#sha512': // backwards compatibility for previous wrong usage oaepHash = 'sha512'; break; } diff --git a/test/xmlenc.digest.js b/test/xmlenc.digest.js index e579a43..4994415 100644 --- a/test/xmlenc.digest.js +++ b/test/xmlenc.digest.js @@ -39,11 +39,6 @@ describe('keyEncryptionDigest', function () { assert(xml.includes('')); }); - it('includes a DigestMethod for RSA-OAEP', function () { - var xml = render({ keyEncryptionMethod: RSA_OAEP, keyEncryptionDigest: 'sha256' }); - assert(xml.includes('