Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
},
"dependencies": {
"ecc-jsbn": "0.0.1",
"ecc-qj": "git+https://github.com/rynomad/ecc.git",
"node-forge": "^0.6.20",
"polyfill-promise": "^4.0.1",
"sjcl": "^1.0.3"
Expand Down
66 changes: 66 additions & 0 deletions src/node/algorithms/ECDSA.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
var Algorithm = require("./abstract")("ECDSA")
, ECC = require("./shared/ECC")
, forge = require("node-forge")
, types = Algorithm.types
, public = types.public.usage
, private = types.private.usage;

ECC(Algorithm);

Algorithm.checkParams = checkParams;

public.verify = createVerify;
private.sign = createSign;

module.exports = Algorithm;

function checkParams(format, algorithm, usages) {
}

function createSign(key, alg1) {
return function ECDSA_SIGN(alg, buf) {
var forgehashKey = alg.hash.name.replace(/-/g, '').toLowerCase();
var md = forge.md[forgehashKey].create();
md.update(buf.toString("binary"));
var digest = md.digest().toHex();
var signature = key.sign(new Buffer(digest, 'hex'));
// Signature is DER encoded, remove it.
var decodedSignature = forge.asn1.fromDer(signature.toString("binary"));
// We take only the last 32 bytes because values could be padded with 0 at the beginning.
return Buffer.concat([
new Buffer(decodedSignature.value[0].value, 'binary').slice(-32),
new Buffer(decodedSignature.value[1].value, 'binary').slice(-32)
]);
};
}

function pad(buffer) {
if (buffer[0] & 0x80) {
// If the value starts with 1, we prepend a 0 to assure it is interpreted as a positive number.
return Buffer.concat([new Buffer([0]), buffer])
}
else {
return buffer;
}
}

function createVerify(key, alg1){
return function ECDSA_VERIFY(alg, buf, sig) {
var forgehashKey = alg.hash.name.replace(/-/g, '').toLowerCase();
var md = forge.md[forgehashKey].create();
md.update(buf.toString("binary"));
var digest = md.digest().getBytes();
var sigPart1 = pad(sig.slice(0, 32));
var sigPart2 = pad(sig.slice(32, 64));
var asn1 = forge.asn1;
var integer1 = sigPart1.toString("binary");
var integer2 = sigPart2.toString("binary");
var derSignature = asn1.toDer(asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, integer1),
asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, integer2)
])).getBytes();
return key.verifySignature(new Buffer(digest, 'binary'), new Buffer(derSignature, 'binary'));
}
}

module.exports = Algorithm;
1 change: 1 addition & 0 deletions src/node/algorithms/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ exports["RSASSA-PKCS1-v1_5"] = require("./RSASSA-PKCS1-v1_5");
exports["HMAC"] = require("./HMAC")
exports["AES-GCM"] = require("./AES-GCM")
exports["ECDH"] = require("./ECDH")
exports["ECDSA"] = require("./ECDSA")
21 changes: 20 additions & 1 deletion src/node/algorithms/shared/ECC.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var ecc = require("./ecc.node.js")
, spkiECCPad = new Buffer("3059301306072a8648ce3d020106082a8648ce3d030107034200","hex");
, pkcsPad1 = new Buffer("308187020100301306072A8648CE3D020106082A8648CE3D030107046D306B0201010420", "hex")
, pkcsPad2 = new Buffer("A144034200", "hex");

function getCurveKey(namedCurve){
return ("sec" + namedCurve.replace(/-/g, '').toLowerCase() + "r1");
Expand Down Expand Up @@ -28,6 +30,19 @@ function raw_import(publicBytes, alg){
return new ecc.ECKey(curve, publicBytes, true);
}

function pkcs8_import(privateBytes, algorithm) {
var curvekey = getCurveKey(algorithm.namedCurve)
, curve = ecc.ECCurves[curvekey];

curve.legacy = true;

return new ecc.ECKey(curve, privateBytes.slice(pkcsPad1.length, pkcsPad1.length + 32), false);
}

function pkcs8_export(Key) {
return Buffer.concat([pkcsPad1, Key.PrivateKey, pkcsPad2, raw_export(Key)]);
}

function generate(alg){
var curvekey = getCurveKey(alg.namedCurve)
, curve = ecc.ECCurves[curvekey];
Expand All @@ -40,7 +55,8 @@ function generate(alg){
function ECC(Algorithm){
var formats = Algorithm.formats
, raw = formats.raw
, spki = formats.spki;
, spki = formats.spki
, pkcs8 = formats.pkcs8;

// attach common generator
Algorithm.generate = generate;
Expand All @@ -52,6 +68,9 @@ function ECC(Algorithm){
spki.import = spki_import;
spki.export = spki_export;

pkcs8.import = pkcs8_import;
pkcs8.export = pkcs8_export;

return;
}

Expand Down