public static PublicKey fromString(byte[] str, string curve = "secp256k1", bool validatePoint = true) { CurveFp curveObject = Curves.getCurveByName(curve); int baseLen = curveObject.length(); if (str.Length != 2 * baseLen) { throw new ArgumentException("string length [" + str.Length + "] should be " + 2 * baseLen); } string xs = Utils.BinaryAscii.hexFromBinary(Utils.Bytes.sliceByteArray(str, 0, baseLen)); string ys = Utils.BinaryAscii.hexFromBinary(Utils.Bytes.sliceByteArray(str, baseLen)); Point p = new Point( Utils.BinaryAscii.numberFromHex(xs), Utils.BinaryAscii.numberFromHex(ys) ); if (validatePoint & !curveObject.contains(p)) { throw new ArgumentException( "point (" + p.x.ToString() + ", " + p.y.ToString() + ") is not valid for curve " + curveObject.name ); } return(new PublicKey(p, curveObject)); }
public static bool verify(string message, Signature signature, PublicKey publicKey) { string hashMessage = sha256(message); BigInteger numberMessage = Utils.BinaryAscii.numberFromHex(hashMessage); CurveFp curve = publicKey.curve; BigInteger sigR = signature.r; BigInteger sigS = signature.s; BigInteger inv = EcdsaMath.inv(sigS, curve.N); Point u1 = EcdsaMath.multiply( curve.G, Utils.Integer.modulo((numberMessage * inv), curve.N), curve.N, curve.A, curve.P ); Point u2 = EcdsaMath.multiply( publicKey.point, Utils.Integer.modulo((sigR * inv), curve.N), curve.N, curve.A, curve.P ); Point add = EcdsaMath.add( u1, u2, curve.A, curve.P ); return(sigR == add.x); }
public static Signature sign(string message, PrivateKey privateKey) { string hashMessage = sha256(message); BigInteger numberMessage = Utils.BinaryAscii.numberFromHex(hashMessage); CurveFp curve = privateKey.curve; BigInteger randNum = Utils.Integer.randomBetween(BigInteger.One, curve.N - 1); Point randSignPoint = EcdsaMath.multiply(curve.G, randNum, curve.N, curve.A, curve.P); BigInteger r = Utils.Integer.modulo(randSignPoint.x, curve.N); BigInteger s = Utils.Integer.modulo((numberMessage + r * privateKey.secret) * (EcdsaMath.inv(randNum, curve.N)), curve.N); return(new Signature(r, s)); }
public static PublicKey fromDer(byte[] der) { Tuple <byte[], byte[]> removeSequence1 = Utils.Der.removeSequence(der); byte[] s1 = removeSequence1.Item1; if (removeSequence1.Item2.Length > 0) { throw new ArgumentException( "trailing junk after DER public key: " + Utils.BinaryAscii.hexFromBinary(removeSequence1.Item2) ); } Tuple <byte[], byte[]> removeSequence2 = Utils.Der.removeSequence(s1); byte[] s2 = removeSequence2.Item1; byte[] pointBitString = removeSequence2.Item2; Tuple <int[], byte[]> removeObject1 = Utils.Der.removeObject(s2); byte[] rest = removeObject1.Item2; Tuple <int[], byte[]> removeObject2 = Utils.Der.removeObject(rest); int[] oidCurve = removeObject2.Item1; if (removeObject2.Item2.Length > 0) { throw new ArgumentException( "trailing junk after DER public key objects: " + Utils.BinaryAscii.hexFromBinary(removeObject2.Item2) ); } string stringOid = string.Join(",", oidCurve); if (!Curves.curvesByOid.ContainsKey(stringOid)) { int numCurves = Curves.supportedCurves.Length; string[] supportedCurves = new string[numCurves]; for (int i = 0; i < numCurves; i++) { supportedCurves[i] = Curves.supportedCurves[i].name; } throw new ArgumentException( "Unknown curve with oid [" + string.Join(", ", oidCurve) + "]. Only the following are available: " + string.Join(", ", supportedCurves) ); } CurveFp curve = Curves.curvesByOid[stringOid]; Tuple <byte[], byte[]> removeBitString = Utils.Der.removeBitString(pointBitString); byte[] pointString = removeBitString.Item1; if (removeBitString.Item2.Length > 0) { throw new ArgumentException("trailing junk after public key point-string"); } return(fromString(Utils.Bytes.sliceByteArray(pointString, 2), curve.name)); }
public PublicKey(Point point, CurveFp curve) { this.point = point; this.curve = curve; }
public static PrivateKey fromDer(byte[] der) { Tuple <byte[], byte[]> removeSequence = Utils.Der.removeSequence(der); if (removeSequence.Item2.Length > 0) { throw new ArgumentException("trailing junk after DER private key: " + Utils.BinaryAscii.hexFromBinary(removeSequence.Item2)); } Tuple <BigInteger, byte[]> removeInteger = Utils.Der.removeInteger(removeSequence.Item1); if (removeInteger.Item1 != 1) { throw new ArgumentException("expected '1' at start of DER private key, got " + removeInteger.Item1.ToString()); } Tuple <byte[], byte[]> removeOctetString = Utils.Der.removeOctetString(removeInteger.Item2); byte[] privateKeyStr = removeOctetString.Item1; Tuple <int, byte[], byte[]> removeConstructed = Utils.Der.removeConstructed(removeOctetString.Item2); int tag = removeConstructed.Item1; byte[] curveOidString = removeConstructed.Item2; if (tag != 0) { throw new ArgumentException("expected tag 0 in DER private key, got " + tag.ToString()); } Tuple <int[], byte[]> removeObject = Utils.Der.removeObject(curveOidString); int[] oidCurve = removeObject.Item1; if (removeObject.Item2.Length > 0) { throw new ArgumentException( "trailing junk after DER private key curve_oid: " + Utils.BinaryAscii.hexFromBinary(removeObject.Item2) ); } string stringOid = string.Join(",", oidCurve); if (!Curves.curvesByOid.ContainsKey(stringOid)) { int numCurves = Curves.supportedCurves.Length; string[] supportedCurves = new string[numCurves]; for (int i = 0; i < numCurves; i++) { supportedCurves[i] = Curves.supportedCurves[i].name; } throw new ArgumentException( "Unknown curve with oid [" + string.Join(", ", oidCurve) + "]. Only the following are available: " + string.Join(", ", supportedCurves) ); } CurveFp curve = Curves.curvesByOid[stringOid]; if (privateKeyStr.Length < curve.length()) { int length = curve.length() - privateKeyStr.Length; string padding = ""; for (int i = 0; i < length; i++) { padding += "00"; } privateKeyStr = Utils.Der.combineByteArrays(new List <byte[]> { Utils.BinaryAscii.binaryFromHex(padding), privateKeyStr }); } return(fromString(privateKeyStr, curve.name)); }