@cdottori/ecdsa-node
Version:
fast openSSL-compatible implementation of the Elliptic Curve Digital Signature Algorithm (ECDSA)
113 lines (89 loc) • 3.42 kB
JavaScript
var RandomInteger = require("./utils/integer");
var BinaryAscii = require("./utils/binary");
var der = require("./utils/der");
var EcdsaCurve = require("./curve");
var EcdsaMath = require("./math");
var PublicKey = require("./publicKey").PublicKey;
var BigInt = require("big-integer");
hexAt = "\x00";
class PrivateKey {
constructor(curve=EcdsaCurve.secp256k1, secret=null) {
this.curve = curve;
if (secret) {
this.secret = secret;
} else {
this.secret = RandomInteger.between(BigInt(1), curve.N.minus(1));
}
};
publicKey () {
let curve = this.curve;
let publicPoint = EcdsaMath.multiply(curve.G, this.secret, curve.N, curve.A, curve.P);
return new PublicKey(publicPoint, curve);
};
toString () {
return BinaryAscii.stringFromNumber(this.secret, this.curve.length());
};
toDer () {
let encodedPublicKey = this.publicKey().toString(true);
return der.encodeSequence(
der.encodeInteger(BigInt(1)),
der.encodeOctetString(this.toString()),
der.encodeConstructed(0, der.encodeOid(this.curve.oid)),
der.encodeConstructed(1, der.encodeBitstring(encodedPublicKey))
);
}
toPem () {
return der.toPem(this.toDer(), "EC PRIVATE KEY");
};
static fromPem (string) {
let privateKeyPem = string.split("-----BEGIN EC PRIVATE KEY-----")[1];
return this.fromDer(der.fromPem(privateKeyPem));
};
static fromDer(string) {
let result = der.removeSequence(string);
let t = result[0];
let empty = result[1];
if (empty) {
throw new Error("trailing junk after DER private key: " + BinaryAscii.hexFromBinary(empty));
};
result = der.removeInteger(t);
let one = result[0];
t = result[1];
if (one != 1) {
throw new Error("expected '1' at start of DER private key, got " + one);
};
result = der.removeOctetString(t);
let privateKeyStr = result[0];
t = result[1];
result = der.removeConstructed(t);
let tag = result[0];
let curveOidStr = result[1];
t = result[2];
if (tag != 0) {
throw new Error("expected tag 0 in DER private key, got " + tag);
};
result = der.removeObject(curveOidStr);
let oidCurve = result[0];
empty = result[1];
if (empty) {
throw new Error("trailing junk after DER private key curve_oid: " + BinaryAscii.hexFromBinary(empty));
};
let curve = EcdsaCurve.curvesByOid[oidCurve];
if (!curve) {
let supportedCurvesNames = [];
EcdsaCurve.supportedCurves.forEach((x) => {supportedCurvesNames.push(x.name)})
throw new Error(
"Unknown curve with oid " + oidCurve
+ ". Only the following are available: " + supportedCurvesNames
);
};
if (privateKeyStr.length < curve.length()) {
privateKeyStr = hexAt.repeat(curve.length() - privateKeyStr.length) + privateKeyStr;
};
return this.fromString(privateKeyStr, curve);
};
static fromString (string, curve=EcdsaCurve.secp256k1) {
return new PrivateKey(curve, BinaryAscii.numberFromString(string));
};
};
exports.PrivateKey = PrivateKey;