Skip to content

Commit 65445e2

Browse files
committed
Adding support for PKCS1 and PKCS8
1 parent 0a07d06 commit 65445e2

File tree

7 files changed

+148
-10
lines changed

7 files changed

+148
-10
lines changed

lib/mcapi/crypto/crypto.js

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,19 @@ function Crypto(config) {
2121
if (config.privateKey) {
2222
this.privateKey = loadPrivateKey(config.privateKey);
2323
} else if (config.keyStore) {
24-
this.privateKey = getPrivateKey(config.keyStore, config.keyStoreAlias, config.keyStorePassword);
24+
if(config.keyStore.includes(".p12")) {
25+
this.privateKey = getPrivateKey12(config.keyStore, config.keyStoreAlias, config.keyStorePassword);
26+
}
27+
if(config.keyStore.includes(".pem")) {
28+
this.privateKey = getPrivateKeyPem(config.keyStore);
29+
}
30+
if(config.keyStore.includes(".der")) {
31+
this.privateKey = getPrivateKeyDer(config.keyStore);
32+
}
2533
}
2634

35+
36+
2737
this.encoding = config.dataEncoding;
2838

2939
this.publicKeyFingerprint = config.publicKeyFingerprint || computePublicFingerprint.call(this, config);
@@ -196,7 +206,7 @@ function readPublicCertificate(publicCertificatePath) {
196206
/**
197207
* @private
198208
*/
199-
function getPrivateKey(p12Path, alias, password) {
209+
function getPrivateKey12(p12Path, alias, password) {
200210
const p12Content = fs.readFileSync(p12Path, 'binary');
201211

202212
if (!p12Content || p12Content.length <= 1) {
@@ -230,6 +240,38 @@ function getPrivateKey(p12Path, alias, password) {
230240
return keyObj.key;
231241
}
232242

243+
244+
/**
245+
* @private
246+
*/
247+
function getPrivateKeyPem(pemPath) {
248+
let pemContent = fs.readFileSync(pemPath, 'binary');
249+
250+
if (!pemContent || pemContent.length <= 1) {
251+
throw new Error('pem keystore content is empty');
252+
}
253+
254+
pemContent = pemContent.replace("\n", "");
255+
pemContent = pemContent.replace("\r\n", "");
256+
257+
return forge.pki.privateKeyFromPem(pemContent);
258+
}
259+
260+
/**
261+
* @private
262+
*/
263+
function getPrivateKeyDer(derPath) {
264+
const derContent = fs.readFileSync(derPath, 'binary');
265+
266+
if (!derContent || derContent.length <= 1) {
267+
throw new Error('der keystore content is empty');
268+
}
269+
270+
const pkeyAsn1 = forge.asn1.fromDer(derContent);
271+
return forge.pki.privateKeyFromAsn1(pkeyAsn1);
272+
}
273+
274+
233275
/**
234276
* @private
235277
* @param config Configuration object

test/crypto.test.js

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe("Crypto", () => {
5757
it("with valid config with private keystore", () => {
5858
const config = JSON.parse(JSON.stringify(testConfig));
5959
delete config.privateKey;
60-
config.keyStore = "./test/res/test_key.p12";
60+
config.keyStore = "./test/res/keys/pkcs12/test_key.p12";
6161
config.keyStoreAlias = "mykeyalias";
6262
config.keyStorePassword = "Password1";
6363
assert.doesNotThrow(() => {
@@ -66,6 +66,36 @@ describe("Crypto", () => {
6666
);
6767
});
6868

69+
it("with valid config with private pkcs1 pem keystore", () => {
70+
const config = JSON.parse(JSON.stringify(testConfig));
71+
delete config.privateKey;
72+
config.keyStore = "./test/res/keys/pkcs1/test_key_pkcs1-1024.pem";
73+
assert.doesNotThrow(() => {
74+
new Crypto(config);
75+
}
76+
);
77+
});
78+
79+
it("with valid config with private pkcs8 pem keystore", () => {
80+
const config = JSON.parse(JSON.stringify(testConfig));
81+
delete config.privateKey;
82+
config.keyStore = "./test/res/keys/pkcs8/test_key_pkcs8-1024.pem";
83+
assert.doesNotThrow(() => {
84+
new Crypto(config);
85+
}
86+
);
87+
});
88+
89+
it("with valid config with private pkcs8 der keystore", () => {
90+
const config = JSON.parse(JSON.stringify(testConfig));
91+
delete config.privateKey;
92+
config.keyStore = "./test/res/keys/pkcs8/test_key_pkcs8-1024.der";
93+
assert.doesNotThrow(() => {
94+
new Crypto(config);
95+
}
96+
);
97+
});
98+
6999
it("with valid config header", () => {
70100
assert.doesNotThrow(() =>
71101
new Crypto(testConfigHeader)
@@ -233,8 +263,8 @@ describe("Crypto", () => {
233263
});
234264
});
235265

236-
describe("#getPrivateKey", () => {
237-
const getPrivateKey = Crypto.__get__("getPrivateKey");
266+
describe("#getPrivateKey12", () => {
267+
const getPrivateKey = Crypto.__get__("getPrivateKey12");
238268

239269
it("not valid key", () => {
240270
assert.throws(() => {
@@ -244,30 +274,65 @@ describe("Crypto", () => {
244274

245275
it("empty alias", () => {
246276
assert.throws(() => {
247-
getPrivateKey("./test/res/test_key_container.p12");
277+
getPrivateKey("./test/res/keys/pkcs12/test_key_container.p12");
248278
}, /Key alias is not set/);
249279
});
250280

251281
it("empty password", () => {
252282
assert.throws(() => {
253-
getPrivateKey("./test/res/test_key_container.p12", "keyalias");
283+
getPrivateKey("./test/res/keys/pkcs12/test_key_container.p12", "keyalias");
254284
}, /Keystore password is not set/);
255285
});
256286

257287
it("valid p12", () => {
258-
const pk = getPrivateKey("./test/res/test_key_container.p12", "mykeyalias", "Password1");
288+
const pk = getPrivateKey("./test/res/keys/pkcs12/test_key_container.p12", "mykeyalias", "Password1");
259289
assert.ok(pk);
260290
});
261291

262292
it("valid p12, alias not found", () => {
263293
assert.throws(() => {
264-
getPrivateKey("./test/res/test_key_container.p12", "mykeyalias1", "Password1");
294+
getPrivateKey("./test/res/keys/pkcs12/test_key_container.p12", "mykeyalias1", "Password1");
265295
}, /No key found for alias \[mykeyalias1\]/);
266296
});
267297
});
268298

299+
describe("#getPrivateKeyPem", () => {
300+
const getPrivateKeyPem = Crypto.__get__("getPrivateKeyPem");
301+
302+
it("valid pkcs8 pem", () => {
303+
const pk = getPrivateKeyPem("./test/res/keys/pkcs8/test_key_pkcs8-1024.pem");
304+
assert.ok(pk);
305+
});
306+
307+
it("valid pkcs1 pem", () => {
308+
const pk = getPrivateKeyPem("./test/res/keys/pkcs1/test_key_pkcs1-1024.pem");
309+
assert.ok(pk);
310+
});
311+
312+
it("not valid key", () => {
313+
assert.throws(() => {
314+
getPrivateKeyPem("./test/res/empty.key");
315+
}, /pem keystore content is empty/);
316+
});
317+
});
318+
319+
describe("#getPrivateKeyDer", () => {
320+
const getPrivateKeyDer = Crypto.__get__("getPrivateKeyDer");
321+
322+
it("valid pkcs8 der", () => {
323+
const pk = getPrivateKeyDer("./test/res/keys/pkcs8/test_key_pkcs8-1024.der");
324+
assert.ok(pk);
325+
});
326+
327+
it("not valid key", () => {
328+
assert.throws(() => {
329+
getPrivateKeyDer("./test/res/empty.key");
330+
}, /der keystore content is empty/);
331+
});
332+
333+
})
269334

270-
describe("#newEncryptionParams", () => {
335+
describe("#newEncryptionParams", () => {
271336
let crypto;
272337
before(() => {
273338
crypto = new Crypto(testConfig);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIICXQIBAAKBgQDHul8A7MM3ynx1XRxmLCRZ1Lr66QppWP5ZaEotsQPpFtyq3w/x
3+
dLWZd5XXQcIb/wUQWcbxBWYJPMk/GVQ3pvkIKEqC+h08VdXtfbBlM+RE8OYaQW5O
4+
Fg7YjHgL/WvCka6VJ990RuX9Zdj9TUu8GyqERll/XUDACs85atbSW6PBQQIDAQAB
5+
AoGBAL9acs0LCZn5OLalB6FoJ0edhasA/MWjysRUI8WU898s1SwsXDUEkTxAk2HR
6+
kayK7woUSYL/nhu5jkIS/Vn4clvH7XRkch22cjAAs4oGZXUUlVrcXFDiR0o2OqAI
7+
Xh24ESM/tpDWmn/N30afn31TBAKxgY5Ej2SrmK5gjSeMGI9xAkEA+gPM/P+jLiwy
8+
wuiS4QRYxeDFtluaafl7UHR/I6vL9VaqOptwV1e/JlytKNMCwoMqadd739/BAX9d
9+
qNgpniHC9QJBAMyCZBAc8PIjfM1h4seEDeb2mxl1Y2DmcDUVWIt+E4Zs3m1I59we
10+
VgY/BwX4UIElhgsVjNo6qXYPbWiql4/tzZ0CQQCLJ6RnyO2NXIJgY8yku6Ohd6r0
11+
BeZbR8XwEPdW5l8eTb9v4WZU5vz4oCqtB02I8DKiOJK1F7g4WijKOo5neoklAkBt
12+
G9/w7M/sD9zk4qWQVrboE4faRFPZ/fe9in7sJT6biHf/DFePi6vPt06y87FXxcJH
13+
JZ85SvTgZQi1P9aO1ovNAkAVxgJq94CKCZjOiks5xTro6V0pYdsx0tuuIlx/vGVG
14+
H3bcmpSm/S54nSovzbEDN7gKr4CSSsAQqC6oPwJSQN6m
15+
-----END RSA PRIVATE KEY-----
File renamed without changes.
634 Bytes
Binary file not shown.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALCcqlioDdtVqSIW
3+
/Y0PUM0YX5Us76B6VSS5e9LwFeK9g/jsrfGs72WdRxEX1uHTzZXHGimMmmODqv4M
4+
bZ5Qbbs7dCZwSKlqNlSKLx40zwy4xZh1ie/UJ2CgUhu62wXDnUMg4HE0l9oY5g/P
5+
BXvSbuGM87gMnNOk0E+pfWHjQbvlAgMBAAECgYBggfuD3rFTvYdinXWH82qP6FWy
6+
yo9W/gIwwzqqlY8gC7dl+s9CVOGsgTkoWgKN/JNG2Tmuoqpq3rQ9hsUP0Ztj32ty
7+
VfEWqKipDtC0x2xi2D7I25gxVLu521tqLhoaWN1oWdPraflXEkEY9p8CD8tzxc6Q
8+
wi6ShZ8TSacuLvivgQJBAOd/X4iNmmPZ0AY+ZVri4Ic+YXOOapagkXuR2Y5pcRfw
9+
3jueEwZMIo142L+dFZMDORsqPhFwwCzOcbn2NEID4ckCQQDDTh607HbkvXAwYHDZ
10+
6gpczrhSAkpjQ0fffOFuF8sI5A64KjnTGte+fm8ic5Mess1oP6LdaS0HvJs4n+m7
11+
nPc9AkEApTwbOmKoQoEjpHFA8wBhducls8+BcQYnEWZnPOkyGf6JAVCxD5ukRgpt
12+
20cKMSbpyeP67YPnB5RLRIrhfgU7UQJAX3d5NRD9UPR0uYD6yNpJNHJr0NKD0B+c
13+
K1dczjbdLTxlIYqqd1GAsgIViu6ZtIDMPTAWCUqXE1gTO8uXMfkZNQJASgdEiTiI
14+
EnZLto+1hRr/fYNzIJHDelJ2oGtzbRmUtXQ8d489obsZusK2kSPWgX1lzXjvrv07
15+
jznkRk0QtDG8Vw==
16+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)