Skip to content

Commit b342c2b

Browse files
authored
Merge pull request #39 from rfeelin/feature/improving-public-key-fingerprint
Allowing encoding type to be set for publickey fingerprint
2 parents 0f874cb + 1afa9ea commit b342c2b

File tree

7 files changed

+75
-41
lines changed

7 files changed

+75
-41
lines changed

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,6 @@ const config = {
290290
],
291291
mode: "JWE",
292292
encryptedValueFieldName: "encryptedData",
293-
publicKeyFingerprintType: "certificate",
294293
encryptionCertificate: "./path/to/public.cert",
295294
privateKey: "./path/to/your/private.key",
296295
};
@@ -394,7 +393,6 @@ const config = {
394393
],
395394
mode: "JWE",
396395
encryptedValueFieldName: "encryptedData",
397-
publicKeyFingerprintType: "certificate",
398396
encryptionCertificate: "./path/to/public.cert",
399397
privateKey: "./path/to/your/private.key",
400398
};
@@ -443,7 +441,6 @@ const config = {
443441
],
444442
mode: "JWE",
445443
encryptedValueFieldName: "encryptedData",
446-
publicKeyFingerprintType: "certificate",
447444
encryptionCertificate: "./path/to/public.cert",
448445
privateKey: "./path/to/your/private.key",
449446
};

lib/mcapi/crypto/jwe-crypto.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,17 @@ function getPrivateKey(config) {
202202
*/
203203
function computePublicFingerprint(config, encryptionCertificate) {
204204
if (config && encryptionCertificate) {
205-
return utils.computePublicFingerprint(
206-
config,
207-
forge.pki.certificateFromPem(encryptionCertificate),
208-
c.BASE64
209-
);
205+
if(config.publicKeyFingerprintType) {
206+
return utils.computePublicFingerprint(
207+
config,
208+
forge.pki.certificateFromPem(encryptionCertificate),
209+
config.dataEncoding
210+
);
211+
} else {
212+
return utils.publicKeyFingerprint(
213+
forge.pki.certificateFromPem(encryptionCertificate)
214+
);
215+
}
210216
} else {
211217
return null;
212218
}
@@ -232,14 +238,25 @@ function isValidConfig(config) {
232238
*/
233239
function validateFingerprint(config, contains) {
234240
const propertiesFingerprint = ["publicKeyFingerprintType"];
241+
const propertiesOptionalDataEncoding = ["dataEncoding"];
235242
const propertiesOptionalFingerprint = ["publicKeyFingerprint"];
236243
if (
237-
!contains(propertiesOptionalFingerprint) &&
244+
contains(propertiesFingerprint) &&
238245
config[propertiesFingerprint[0]] !== "certificate" &&
239246
config[propertiesFingerprint[0]] !== "publicKey"
240247
) {
241248
throw Error(
242-
"Config not valid: propertiesFingerprint should be: 'certificate' or 'publicKey'"
249+
"Config not valid: publicKeyFingerprintType should be: 'certificate' or 'publicKey'"
250+
);
251+
}
252+
if (
253+
!contains(propertiesOptionalFingerprint) &&
254+
config[propertiesFingerprint[0]] === "certificate" &&
255+
!(config[propertiesOptionalDataEncoding[0]] === c.BASE64 ||
256+
config[propertiesOptionalDataEncoding[0]] === c.HEX)
257+
) {
258+
throw Error(
259+
"Config not valid: if publicKeyFingerprintType is 'certificate' dataEncoding must be either 'base64' or 'hex'"
243260
);
244261
}
245262
}

lib/mcapi/encryption/field-level-encryption.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,7 @@ function encryptBody(path, body) {
103103
const elem = utils.elemFromPath(path.element, body);
104104
if (elem && elem.node) {
105105
const encryptedData = this.crypto.encryptData({ data: elem.node });
106-
body = utils.mutateObjectProperty(path.obj, encryptedData, body);
107-
// delete encrypted field if not overridden
108-
if (
109-
!utils.isJsonRoot(path.obj) &&
110-
path.element !== path.obj + "." + this.config.encryptedValueFieldName
111-
) {
112-
utils.deleteNode(path.element, body);
113-
}
106+
body = utils.addEncryptedDataToBody(encryptedData, path, this.config.encryptedValueFieldName, body);
114107
}
115108
return body;
116109
}

lib/mcapi/encryption/jwe-encryption.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,7 @@ function encryptBody(path, body) {
6767
const elem = utils.elemFromPath(path.element, body);
6868
if (elem && elem.node) {
6969
const encryptedData = this.crypto.encryptData({ data: elem.node });
70-
body = utils.mutateObjectProperty(path.obj, encryptedData, body);
71-
// delete encrypted field if not overridden
72-
if (
73-
!utils.isJsonRoot(path.obj) &&
74-
path.element !== path.obj + "." + this.config.encryptedValueFieldName
75-
) {
76-
utils.deleteNode(path.element, body);
77-
}
70+
body = utils.addEncryptedDataToBody(encryptedData, path, this.config.encryptedValueFieldName, body);
7871
}
7972
return body;
8073
}

lib/mcapi/utils/utils.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ module.exports.computePublicFingerprint = function (
273273
);
274274
break;
275275
case "publicKey":
276-
fingerprint = publicKeyFingerprint(encryptionCertificate);
276+
fingerprint = this.publicKeyFingerprint(encryptionCertificate);
277277
break;
278278
}
279279
}
@@ -289,13 +289,13 @@ function publicCertificateFingerprint(publicCertificate, encoding) {
289289
return bytesToString(md.digest().getBytes(), encoding);
290290
}
291291

292-
function publicKeyFingerprint(publicCertificate) {
292+
module.exports.publicKeyFingerprint = function(publicCertificate) {
293293
return forge.pki.getPublicKeyFingerprint(publicCertificate.publicKey, {
294294
type: "SubjectPublicKeyInfo",
295295
md: createMessageDigest("SHA-256"),
296296
encoding: c.HEX,
297297
});
298-
}
298+
};
299299

300300
function createMessageDigest(digest) {
301301
switch (digest.toUpperCase()) {
@@ -415,6 +415,17 @@ function hasEncryptionParam(encParams, bodyMap) {
415415
return encParams && encParams.length === 1 && bodyMap && bodyMap[0];
416416
}
417417

418+
module.exports.addEncryptedDataToBody = function(encryptedData, path, encryptedValueFieldName, body) {
419+
body = this.mutateObjectProperty(path.obj, encryptedData, body);
420+
if (
421+
!isJsonRoot(path.obj) &&
422+
path.element !== path.obj + "." + encryptedValueFieldName
423+
) {
424+
this.deleteNode(path.element, body);
425+
}
426+
return body;
427+
};
428+
418429
module.exports.readPublicCertificateContent = function (config) {
419430
if (!config.encryptionCertificate || config.encryptionCertificate.length <= 1) {
420431
throw new Error("Public certificate content is not valid");
@@ -427,4 +438,4 @@ module.exports.getPrivateKeyFromContent = function(config) {
427438
return forge.pki.privateKeyFromPem(config.privateKey);
428439
}
429440
return null;
430-
}
441+
}

test/jwe-crypto.test.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,6 @@ describe("JWE Crypto", () => {
8787
});
8888
});
8989

90-
it("without publicKeyFingerprintType", () => {
91-
const config = JSON.parse(JSON.stringify(testConfig));
92-
delete config["publicKeyFingerprintType"];
93-
assert.throws(
94-
() => new Crypto(config),
95-
/Config not valid: propertiesFingerprint should be: 'certificate' or 'publicKey'/
96-
);
97-
});
98-
9990
it("without publicKeyFingerprintType, but providing the publicKeyFingerprint", () => {
10091
const config = JSON.parse(JSON.stringify(testConfig));
10192
delete config["publicKeyFingerprintType"];
@@ -108,16 +99,34 @@ describe("JWE Crypto", () => {
10899
config.publicKeyFingerprintType = "foobar";
109100
assert.throws(
110101
() => new Crypto(config),
111-
/Config not valid: propertiesFingerprint should be: 'certificate' or 'publicKey'/
102+
/Config not valid: publicKeyFingerprintType should be: 'certificate' or 'publicKey'/
112103
);
113104
});
114105

115-
it("with right publicKeyFingerprintType: certificate", () => {
106+
it("with right publicKeyFingerprintType: certificate and dataEncoding: base64", () => {
116107
const config = JSON.parse(JSON.stringify(testConfig));
117108
config.publicKeyFingerprintType = "certificate";
109+
config.dataEncoding = "base64";
118110
assert.doesNotThrow(() => new Crypto(config));
119111
});
120112

113+
it("with right publicKeyFingerprintType: certificate and dataEncoding: hex", () => {
114+
const config = JSON.parse(JSON.stringify(testConfig));
115+
config.publicKeyFingerprintType = "certificate";
116+
config.dataEncoding = "hex";
117+
assert.doesNotThrow(() => new Crypto(config));
118+
});
119+
120+
it("with right publicKeyFingerprintType: certificate and dataEncoding: null", () => {
121+
const config = JSON.parse(JSON.stringify(testConfig));
122+
config.publicKeyFingerprintType = "certificate";
123+
delete config["dataEncoding"];
124+
assert.throws(
125+
() => new Crypto(config),
126+
/Config not valid: if publicKeyFingerprintType is 'certificate' dataEncoding must be either 'base64' or 'hex'/
127+
);
128+
});
129+
121130
it("with right publicKeyFingerprintType: publicKey", () => {
122131
const config = JSON.parse(JSON.stringify(testConfig));
123132
config.publicKeyFingerprintType = "publicKey";
@@ -249,5 +258,18 @@ describe("JWE Crypto", () => {
249258
})
250259
);
251260
});
261+
262+
it("compute public fingerprint: defaults to publicKey with publicKeyFingerprintType set", () => {
263+
const strippedConfig = JSON.parse(JSON.stringify(testConfig));
264+
delete strippedConfig["publicKeyFingerprintType"];
265+
delete strippedConfig["dataEncoding"];
266+
267+
assert.ok(
268+
"80810fc13a8319fcf0e2ec322c82a4c304b782cc3ce671176343cfe8160c2279",
269+
computePublicFingerprint.call(crypto, {
270+
strippedConfig
271+
})
272+
);
273+
});
252274
});
253275
});

test/mock/jwe-config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ module.exports = {
6464
mode: "JWE",
6565
encryptedValueFieldName: "encryptedData",
6666
publicKeyFingerprintType: "certificate",
67+
dataEncoding: "base64",
6768
encryptionCertificate: "./test/res/test_certificate.cert",
6869
privateKey: "./test/res/test_key.der",
6970
};

0 commit comments

Comments
 (0)