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));
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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));
        }