JWK-to-PEM for PKCS#1
This commit is contained in:
parent
81dd4bf89d
commit
895a29bf71
5 changed files with 55 additions and 1 deletions
11
fixtures/privkey-rsa-2048.jwt.json
Normal file
11
fixtures/privkey-rsa-2048.jwt.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"kty": "RSA",
|
||||||
|
"n": "m2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJefLukC-xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57qAZM6-I70on0_iDZm7-jcqOPgADAmbWHhy67BXkk4yy_YzD4yOGZFXZcNp915_TW5bRd__AKPHUHxJasPiyEFqlNKBR2DSD-LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps_50-CNw",
|
||||||
|
"e": "AQAB",
|
||||||
|
"d": "Cpfo7Mm9Nu8YMC_xrZ54W9mKHPkCG9rZ93Ds9PNp-RXUgb-ljTbFPZWsYxGNKLllFz8LNosr1pT2ZDMrwNk0Af1iWNvD6gkyXaiQdCyiDPSBsJyNv2LJZon-e85X74nv53UlIkmo9SYxdLz2JaJ-iIWEe8Qh-7llLktrTJV_xr98_tbhgSppz_IeOymq3SEZaQHM8pTU7w7XvCj2pb9r8fN0M0XcgWZIaf3LGEfkhF_WtX67XJ0C6-LbkT51jtlLRNGX6haGdscXS0OWWjKOJzKGuV-NbthEn5rmRtVnjRZ3yaxQ0ud8vC-NONn7yvGUlOur1IdDzJ_YfHPt9sHMQQ",
|
||||||
|
"p": "ynG-t9HwKCN3MWRYFdnFzi9-02Qcy3p8B5pu3ary2E70hYn2pHlUG2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU_UYEbAtPv_PxSmzpQp9n9XnYvBLBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCE",
|
||||||
|
"q": "xIkAjgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c_8397_DZDDo46fnFYjs6uPa03HpmKUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnFD2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1c",
|
||||||
|
"dp": "tzDGjECFOU0ehqtuqhcuT63a7h8hj19-7MJqoFwY9HQ-ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyhc_nAVfYPEC_2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k-q2tp3ieBYdVGAXJoGOdv5VpaZ7B1QE",
|
||||||
|
"dq": "kh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3xN7iUVmAg-ToKjwbVnG5-7eXiC779rQVwnrD_0yh1AFJ8wjRPqDIR7ObXGHikIxT1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7-NxLKWzqao_u4lhnDQaX9PKa12HFlny6K1daL48",
|
||||||
|
"qi": "AlHWbx1gp6Z9pbw_1hlS7HuXAgWoX7IjbTUelldf4gkriDWLOrj3QCZcO4ZvZvEwJhVlsny9LO8IkbwGJEL6cXraK08ByVS2mwQyflgTgGNnpzixyEUL_mrQLx6y145FHcxfeqNInMhep-0Mxn1D5nlhmIOgRApS0t9VoXtHhFU"
|
||||||
|
}
|
|
@ -15,6 +15,10 @@ Enc.bufToHex = function toHex(u8) {
|
||||||
return hex.join('').toLowerCase();
|
return hex.join('').toLowerCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Enc.hexToBuf = function (hex) {
|
||||||
|
return Buffer.from(hex, 'hex');
|
||||||
|
};
|
||||||
|
|
||||||
Enc.numToHex = function numToHex(d) {
|
Enc.numToHex = function numToHex(d) {
|
||||||
d = d.toString(16);
|
d = d.toString(16);
|
||||||
if (d.length % 2) {
|
if (d.length % 2) {
|
||||||
|
@ -23,6 +27,10 @@ Enc.numToHex = function numToHex(d) {
|
||||||
return d;
|
return d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Enc.base64ToHex = function base64ToHex(b64) {
|
||||||
|
return Enc.bufToHex(Enc.base64ToBuf(b64));
|
||||||
|
}
|
||||||
|
|
||||||
Enc.bufToBase64 = function toHex(u8) {
|
Enc.bufToBase64 = function toHex(u8) {
|
||||||
// we want to maintain api compatability with browser APIs,
|
// we want to maintain api compatability with browser APIs,
|
||||||
// so we assume that this could be a Uint8Array
|
// so we assume that this could be a Uint8Array
|
||||||
|
|
|
@ -37,3 +37,11 @@ PEM.parseBlock = function pemToDer(pem) {
|
||||||
|
|
||||||
return { kty: typ, pub: pub, der: der };
|
return { kty: typ, pub: pub, der: der };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PEM.packBlock = function (opts) {
|
||||||
|
// TODO allow for headers?
|
||||||
|
return '-----BEGIN ' + opts.type + '-----\n'
|
||||||
|
+ Enc.bufToBase64(opts.bytes).match(/.{1,64}/g).join('\n') + '\n'
|
||||||
|
+ '-----END ' + opts.type + '-----'
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
|
@ -90,7 +90,11 @@ RSA.pack = function (opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('pkcs1' === format) {
|
if ('pkcs1' === format) {
|
||||||
return PEM.packBlock({ type: "RSA PRIVATE KEY", bytes: x509.packPkcs1(jwk) });
|
if (jwk.d) {
|
||||||
|
return PEM.packBlock({ type: "RSA PRIVATE KEY", bytes: x509.packPkcs1(jwk) });
|
||||||
|
} else {
|
||||||
|
return PEM.packBlock({ type: "RSA PUBLIC KEY", bytes: x509.packPkcs1(jwk) });
|
||||||
|
}
|
||||||
} else if ('pkcs8' === format) {
|
} else if ('pkcs8' === format) {
|
||||||
return PEM.packBlock({ type: "PRIVATE KEY", bytes: x509.packPkcs8(jwk) });
|
return PEM.packBlock({ type: "PRIVATE KEY", bytes: x509.packPkcs8(jwk) });
|
||||||
} else if (-1 !== [ 'spki', 'pkix' ].indexOf(format)) {
|
} else if (-1 !== [ 'spki', 'pkix' ].indexOf(format)) {
|
||||||
|
|
23
lib/x509.js
23
lib/x509.js
|
@ -1,5 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// TODO fun idea: create a template from an existing file
|
||||||
|
|
||||||
var x509 = module.exports;
|
var x509 = module.exports;
|
||||||
var ASN1 = require('./asn1.js');
|
var ASN1 = require('./asn1.js');
|
||||||
var Enc = require('./encoding.js');
|
var Enc = require('./encoding.js');
|
||||||
|
@ -91,3 +93,24 @@ x509.parsePkcs8 = function parseRsaPkcs8(buf, asn1, jwk) {
|
||||||
}
|
}
|
||||||
return jwk;
|
return jwk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
x509.packPkcs1 = function (jwk) {
|
||||||
|
var n = ASN1.UInt(Enc.base64ToHex(jwk.n));
|
||||||
|
var e = ASN1.UInt(Enc.base64ToHex(jwk.e));
|
||||||
|
|
||||||
|
if (!jwk.d) {
|
||||||
|
return Enc.hexToBuf(ASN1('30', n, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Enc.hexToBuf(ASN1('30'
|
||||||
|
, ASN1.UInt('00')
|
||||||
|
, n
|
||||||
|
, e
|
||||||
|
, ASN1.UInt(Enc.base64ToHex(jwk.d))
|
||||||
|
, ASN1.UInt(Enc.base64ToHex(jwk.p))
|
||||||
|
, ASN1.UInt(Enc.base64ToHex(jwk.q))
|
||||||
|
, ASN1.UInt(Enc.base64ToHex(jwk.dp))
|
||||||
|
, ASN1.UInt(Enc.base64ToHex(jwk.dq))
|
||||||
|
, ASN1.UInt(Enc.base64ToHex(jwk.qi))
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue