|
|
@ -10,10 +10,19 @@ var Keypairs = module.exports; |
|
|
|
Keypairs.generate = function (opts) { |
|
|
|
opts = opts || {}; |
|
|
|
var kty = opts.kty || opts.type; |
|
|
|
var p; |
|
|
|
if ('RSA' === kty) { |
|
|
|
return Rasha.generate(opts); |
|
|
|
p = Rasha.generate(opts); |
|
|
|
} else { |
|
|
|
p = Eckles.generate(opts); |
|
|
|
} |
|
|
|
return Eckles.generate(opts); |
|
|
|
return p.then(function (pair) { |
|
|
|
return Keypairs.thumbprint({ jwk: pair.public }).then(function (thumb) { |
|
|
|
pair.private.kid = thumb; // maybe not the same id on the private key?
|
|
|
|
pair.public.kid = thumb; |
|
|
|
return pair; |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
Keypairs.parse = function (opts) { |
|
|
@ -24,22 +33,26 @@ Keypairs.parse = function (opts) { |
|
|
|
var pem; |
|
|
|
var p; |
|
|
|
|
|
|
|
try { |
|
|
|
jwk = JSON.parse(opts.key); |
|
|
|
p = Keypairs.export({ jwk: jwk }).catch(function (e) { |
|
|
|
pem = opts.key; |
|
|
|
err = new Error("Not a valid jwk '" + JSON.stringify(jwk) + "':" + e.message); |
|
|
|
err.code = "EINVALID"; |
|
|
|
return Promise.reject(err); |
|
|
|
}).then(function () { |
|
|
|
return jwk; |
|
|
|
}); |
|
|
|
} catch(e) { |
|
|
|
p = Keypairs.import({ pem: opts.key }).catch(function (e) { |
|
|
|
err = new Error("Could not parse key (type " + typeof opts.key + ") '" + opts.key + "': " + e.message); |
|
|
|
err.code = "EPARSE"; |
|
|
|
return Promise.reject(err); |
|
|
|
}); |
|
|
|
if (!opts.key || !opts.key.kty) { |
|
|
|
try { |
|
|
|
jwk = JSON.parse(opts.key); |
|
|
|
p = Keypairs.export({ jwk: jwk }).catch(function (e) { |
|
|
|
pem = opts.key; |
|
|
|
err = new Error("Not a valid jwk '" + JSON.stringify(jwk) + "':" + e.message); |
|
|
|
err.code = "EINVALID"; |
|
|
|
return Promise.reject(err); |
|
|
|
}).then(function () { |
|
|
|
return jwk; |
|
|
|
}); |
|
|
|
} catch(e) { |
|
|
|
p = Keypairs.import({ pem: opts.key }).catch(function (e) { |
|
|
|
err = new Error("Could not parse key (type " + typeof opts.key + ") '" + opts.key + "': " + e.message); |
|
|
|
err.code = "EPARSE"; |
|
|
|
return Promise.reject(err); |
|
|
|
}); |
|
|
|
} |
|
|
|
} else { |
|
|
|
p = Promise.resolve(opts.key); |
|
|
|
} |
|
|
|
|
|
|
|
return p.then(function (jwk) { |
|
|
@ -74,6 +87,11 @@ Keypairs.parseOrGenerate = function (opts) { |
|
|
|
Keypairs.import = function (opts) { |
|
|
|
return Eckles.import(opts).catch(function () { |
|
|
|
return Rasha.import(opts); |
|
|
|
}).then(function (jwk) { |
|
|
|
return Keypairs.thumbprint({ jwk: jwk }).then(function (thumb) { |
|
|
|
jwk.kid = thumb; |
|
|
|
return jwk; |
|
|
|
}); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
@ -93,6 +111,7 @@ Keypairs.neuter = Keypairs._neuter = function (opts) { |
|
|
|
// trying to find the best balance of an immutable copy with custom attributes
|
|
|
|
var jwk = {}; |
|
|
|
Object.keys(opts.jwk).forEach(function (k) { |
|
|
|
if ('undefined' === typeof opts.jwk[k]) { return; } |
|
|
|
// ignore RSA and EC private parts
|
|
|
|
if (-1 !== ['d', 'p', 'q', 'dp', 'dq', 'qi'].indexOf(k)) { return; } |
|
|
|
jwk[k] = JSON.parse(JSON.stringify(opts.jwk[k])); |
|
|
@ -111,7 +130,7 @@ Keypairs.publish = function (opts) { |
|
|
|
} else { |
|
|
|
if (opts.exp) { jwk.exp = setTime(opts.exp); } |
|
|
|
else if (opts.expiresIn) { jwk.exp = Math.round(Date.now()/1000) + opts.expiresIn; } |
|
|
|
else { jwk.exp = opts.expiresAt; } |
|
|
|
else if (opts.expiresAt) { jwk.exp = opts.expiresAt; } |
|
|
|
} |
|
|
|
if (!jwk.use && false !== jwk.use) { jwk.use = "sig"; } |
|
|
|
|
|
|
|