diff --git a/lib/templates/keyinfo.tpl.xml.js b/lib/templates/keyinfo.tpl.xml.js index b629b37..9859d5f 100644 --- a/lib/templates/keyinfo.tpl.xml.js +++ b/lib/templates/keyinfo.tpl.xml.js @@ -1,10 +1,22 @@ var escapehtml = require('escape-html'); -module.exports = ({ encryptionPublicCert, encryptedKey, keyEncryptionMethod, keyEncryptionDigest }) => ` +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' +}; + +module.exports = ({ encryptionPublicCert, encryptedKey, keyEncryptionMethod, keyEncryptionDigest }) => { + const digestUri = DIGEST_ALGORITHMS[keyEncryptionDigest] || keyEncryptionDigest; + + // 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 ` - + ${isOAEP ? `` : ''} ${encryptionPublicCert} @@ -15,4 +27,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..50fa39e 100644 --- a/lib/xmlenc.js +++ b/lib/xmlenc.js @@ -255,10 +255,12 @@ 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/2000/09/xmldsig#sha512': + case 'http://www.w3.org/2001/04/xmlenc#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 new file mode 100644 index 0000000..4994415 --- /dev/null +++ b/test/xmlenc.digest.js @@ -0,0 +1,152 @@ +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('does NOT include a DigestMethod for RSA-1.5', function () { + var xml = render({ keyEncryptionMethod: RSA_1_5, keyEncryptionDigest: 'sha256' }); + assert(!xml.includes('