|
|
@ -32,7 +32,7 @@ EC.generate = function (opts) { |
|
|
|
+ " Please choose either 'P-256' or 'P-384'. " |
|
|
|
+ EC._stance)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var extractable = true; |
|
|
|
return window.crypto.subtle.generateKey( |
|
|
|
wcOpts |
|
|
@ -51,6 +51,59 @@ EC.generate = function (opts) { |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
EC.export = function (opts) { |
|
|
|
if (!opts || !opts.jwk || 'object' !== typeof opts.jwk) { |
|
|
|
throw new Error("must pass { jwk: jwk } as a JSON object"); |
|
|
|
} |
|
|
|
var jwk = JSON.parse(JSON.stringify(opts.jwk)); |
|
|
|
var format = opts.format; |
|
|
|
if (opts.public || -1 !== [ 'spki', 'pkix', 'ssh', 'rfc4716' ].indexOf(format)) { |
|
|
|
jwk.d = null; |
|
|
|
} |
|
|
|
if ('EC' !== jwk.kty) { |
|
|
|
throw new Error("options.jwk.kty must be 'EC' for EC keys"); |
|
|
|
} |
|
|
|
if (!jwk.d) { |
|
|
|
if (!format || -1 !== [ 'spki', 'pkix' ].indexOf(format)) { |
|
|
|
format = 'spki'; |
|
|
|
} else if (-1 !== [ 'ssh', 'rfc4716' ].indexOf(format)) { |
|
|
|
format = 'ssh'; |
|
|
|
} else { |
|
|
|
throw new Error("options.format must be 'spki' or 'ssh' for public EC keys, not (" |
|
|
|
+ typeof format + ") " + format); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (!format || 'sec1' === format) { |
|
|
|
format = 'sec1'; |
|
|
|
} else if ('pkcs8' !== format) { |
|
|
|
throw new Error("options.format must be 'sec1' or 'pkcs8' for private EC keys, not '" + format + "'"); |
|
|
|
} |
|
|
|
} |
|
|
|
if (-1 === [ 'P-256', 'P-384' ].indexOf(jwk.crv)) { |
|
|
|
throw new Error("options.jwk.crv must be either P-256 or P-384 for EC keys, not '" + jwk.crv + "'"); |
|
|
|
} |
|
|
|
if (!jwk.y) { |
|
|
|
throw new Error("options.jwk.y must be a urlsafe base64-encoded either P-256 or P-384"); |
|
|
|
} |
|
|
|
|
|
|
|
if ('sec1' === format) { |
|
|
|
return PEM.packBlock({ type: "EC PRIVATE KEY", bytes: x509.packSec1(jwk) }); |
|
|
|
} else if ('pkcs8' === format) { |
|
|
|
return PEM.packBlock({ type: "PRIVATE KEY", bytes: x509.packPkcs8(jwk) }); |
|
|
|
} else if (-1 !== [ 'spki', 'pkix' ].indexOf(format)) { |
|
|
|
return PEM.packBlock({ type: "PUBLIC KEY", bytes: x509.packSpki(jwk) }); |
|
|
|
} else if (-1 !== [ 'ssh', 'rfc4716' ].indexOf(format)) { |
|
|
|
return SSH.packSsh(jwk); |
|
|
|
} else { |
|
|
|
throw new Error("Sanity Error: reached unreachable code block with format: " + format); |
|
|
|
} |
|
|
|
}; |
|
|
|
EC.pack = function (opts) { |
|
|
|
return Promise.resolve().then(function () { |
|
|
|
return EC.exportSync(opts); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
// Chopping off the private parts is now part of the public API.
|
|
|
|
// I thought it sounded a little too crude at first, but it really is the best name in every possible way.
|
|
|
|
EC.neuter = function (opts) { |
|
|
|