New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

jwk-to-pem

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jwk-to-pem - npm Package Compare versions

Comparing version 1.1.4 to 1.2.0

src/b64-to-bn.js

8

package.json
{
"name": "jwk-to-pem",
"version": "1.1.4",
"version": "1.2.0",
"description": "Convert a JSON Web Key to a PEM",

@@ -27,6 +27,5 @@ "main": "src/jwk-to-pem.js",

"dependencies": {
"asn1.js": "^2.0.3",
"asn1.js": "^2.2.0",
"asn1.js-rfc3280": "^2.1.0",
"elliptic": "^3.0.4",
"rsa-pem-from-mod-exp": "^0.8.4"
"elliptic": "^3.0.4"
},

@@ -37,4 +36,5 @@ "devDependencies": {

"istanbul": "^0.3.15",
"jwa": "^1.1.0",
"mocha": "^2.2.5"
}
}

@@ -30,2 +30,20 @@ # jwk-to-pem

### API
---
#### `jwkToPem(Object jwk[, Object options])` -> `String`
The first parameter should be an Object representing the jwk, it may be public
or private. By default, either of the two will be made into a public PEM. The
call will throw if the input jwk is malformed or does not represent a valid
key.
##### Option: private `Boolean` _(false)_
You may optionally specify that you would like a private PEM. This can be done
by passing `true` to the `private` option. The call will throw if the necessary
private parameters are not available.
## Contributing

@@ -32,0 +50,0 @@

'use strict';
var asn1 = require('asn1.js'),
BN = asn1.bignum,
curves = require('./ec-curves'),
rfc3280 = require('asn1.js-rfc3280');
function jwkParamToBigNum (val) {
val = new Buffer(val, 'base64');
val = new BN(val, 10, 'be').iabs();
return val;
}
var b64ToBn = require('./b64-to-bn');
function ecJwkToBuffer (jwk) {
function ecJwkToBuffer (jwk, opts) {
if ('string' !== typeof jwk.crv) {

@@ -19,10 +14,19 @@ throw new TypeError('Expected "jwk.crv" to be a String');

if ('string' !== typeof jwk.x) {
var hasD = 'string' === typeof jwk.d;
var xyTypes = hasD
? ['undefined', 'string']
: ['string'];
if (-1 === xyTypes.indexOf(typeof jwk.x)) {
throw new TypeError('Expected "jwk.x" to be a String');
}
if ('string' !== typeof jwk.y) {
if (-1 === xyTypes.indexOf(typeof jwk.y)) {
throw new TypeError('Expected "jwk.y" to be a String');
}
if (opts.private && !hasD) {
throw new TypeError('Expected "jwk.d" to be a String');
}
var curve = curves[jwk.crv];

@@ -33,7 +37,18 @@ if (!curve) {

var x = jwkParamToBigNum(jwk.x),
y = jwkParamToBigNum(jwk.y);
var key = {};
var key = curve.keyFromPublic({ x: x, y: y });
var hasPub = jwk.x && jwk.y;
if (hasPub) {
key.pub = {
x: b64ToBn(jwk.x),
y: b64ToBn(jwk.y)
};
}
if (opts.private || !hasPub) {
key.priv = b64ToBn(jwk.d);
}
key = curve.keyPair(key);
var keyValidation = key.validate();

@@ -44,3 +59,3 @@ if (!keyValidation.result) {

var result = keyToPem(jwk.crv, key);
var result = keyToPem(jwk.crv, key, opts);

@@ -50,3 +65,3 @@ return result;

function keyToPem (crv, key) {
function keyToPem (crv, key, opts) {
var oid;

@@ -74,31 +89,43 @@ switch (crv) {

subjectPublicKey = new Buffer(subjectPublicKey, 'hex');
subjectPublicKey = {
unused: 0,
data: subjectPublicKey
};
var result = rfc3280.SubjectPublicKeyInfo.encode({
algorithm: {
algorithm: [1, 2, 840, 10045, 2, 1],
parameters: ECParameters.encode({
type: 'namedCurve',
value: oid
}, 'der')
},
subjectPublicKey: {
unused: 0,
data: subjectPublicKey
}
var parameters = ECParameters.encode({
type: 'namedCurve',
value: oid
}, 'der');
result = result.toString('base64');
result = guardDer(result);
var result;
if (opts.private) {
var privateKey = key.getPrivate('hex');
privateKey = new Buffer(privateKey, 'hex');
return result;
}
result = ECPrivateKey.encode({
version: ecPrivkeyVer1,
privateKey: privateKey,
parameters: parameters,
publicKey: subjectPublicKey
}, 'pem', {
label: 'EC PRIVATE KEY'
});
} else {
result = rfc3280.SubjectPublicKeyInfo.encode({
algorithm: {
algorithm: [1, 2, 840, 10045, 2, 1],
parameters: parameters
},
subjectPublicKey: subjectPublicKey
}, 'pem', {
label: 'PUBLIC KEY'
});
}
function guardDer (der) {
var openGuard = '-----BEGIN PUBLIC KEY-----\n',
endGuard = '-----END PUBLIC KEY-----\n';
// This is in an if incase asn1.js adds a trailing \n
// istanbul ignore else
if ('\n' !== result.slice(-1)) {
result += '\n';
}
der = der.match(/.{1,64}/g).join('\n') + '\n';
var result = openGuard + der + endGuard;
return result;

@@ -113,2 +140,13 @@ }

var ecPrivkeyVer1 = 1;
var ECPrivateKey = asn1.define('ECPrivateKey', function () {
this.seq().obj(
this.key('version').int(),
this.key('privateKey').octstr(),
this.key('parameters').explicit(0).optional().any(),
this.key('publicKey').explicit(1).optional().bitstr()
);
});
module.exports = ecJwkToBuffer;

@@ -6,3 +6,3 @@ 'use strict';

function jwkToBuffer (jwk) {
function jwkToBuffer (jwk, opts) {
if ('object' !== typeof jwk || null === jwk) {

@@ -17,8 +17,11 @@ throw new TypeError('Expected "jwk" to be an Object');

opts = opts || {};
opts.private = opts.private === true;
switch (kty) {
case 'EC': {
return ec(jwk);
return ec(jwk, opts);
}
case 'RSA': {
return rsa(jwk);
return rsa(jwk, opts);
}

@@ -25,0 +28,0 @@ default: {

'use strict';
var getPem = require('rsa-pem-from-mod-exp');
var asn1 = require('asn1.js');
function rsaJwkToBuffer (jwk) {
var b64ToBn = require('./b64-to-bn');
var Version = asn1.define('Version', function () {
this.int();
});
var RSAPrivateKey = asn1.define('RSAPrivateKey', function () {
this.seq().obj(
this.key('version').use(Version),
this.key('modulus').int(),
this.key('publicExponent').int(),
this.key('privateExponent').int(),
this.key('prime1').int(),
this.key('prime2').int(),
this.key('exponent1').int(),
this.key('exponent2').int(),
this.key('coefficient').int()
);
});
var RSAPublicKey = asn1.define('RSAPublicKey', function () {
this.seq().obj(
this.key('modulus').int(),
this.key('publicExponent').int()
);
});
function rsaJwkToBuffer (jwk, opts) {
if ('string' !== typeof jwk.e) {

@@ -14,4 +41,58 @@ throw new TypeError('Expected "jwk.e" to be a String');

var pem = getPem(jwk.n, jwk.e);
if (opts.private) {
if ('string' !== typeof jwk.d) {
throw new TypeError('Expected "jwk.d" to be a String');
}
if ('string' !== typeof jwk.p) {
throw new TypeError('Expected "jwk.p" to be a String');
}
if ('string' !== typeof jwk.q) {
throw new TypeError('Expected "jwk.q" to be a String');
}
if ('string' !== typeof jwk.dp) {
throw new TypeError('Expected "jwk.dp" to be a String');
}
if ('string' !== typeof jwk.dq) {
throw new TypeError('Expected "jwk.dq" to be a String');
}
if ('string' !== typeof jwk.qi) {
throw new TypeError('Expected "jwk.qi" to be a String');
}
}
var pem;
if (opts.private) {
pem = RSAPrivateKey.encode({
version: 0,
modulus: b64ToBn(jwk.n),
publicExponent: b64ToBn(jwk.e),
privateExponent: b64ToBn(jwk.d),
prime1: b64ToBn(jwk.p),
prime2: b64ToBn(jwk.q),
exponent1: b64ToBn(jwk.dp),
exponent2: b64ToBn(jwk.dq),
coefficient: b64ToBn(jwk.qi)
}, 'pem', {
label: 'RSA PRIVATE KEY'
});
} else {
pem = RSAPublicKey.encode({
modulus: b64ToBn(jwk.n),
publicExponent: b64ToBn(jwk.e)
}, 'pem', {
label: 'RSA PUBLIC KEY'
});
}
// This is in an if incase asn1.js adds a trailing \n
// istanbul ignore else
if ('\n' !== pem.slice(-1)) {
pem += '\n';
}
return pem;

@@ -18,0 +99,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc