Esempio n. 1
0
        public Signature Sign(BigInteger z)
        {
            // Generate random number k (ephemeral private key)
            // TODO: this should be replaced with deterministic initialisation of k as shown here:
            // https://tools.ietf.org/html/rfc6979
            BigInteger k;

            do
            {
                var bytes = new byte[32];
                using (RandomNumberGenerator rng = new RNGCryptoServiceProvider())
                {
                    rng.GetBytes(bytes);
                }
                k = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(bytes);
            } while (k < 1 || k > Secp256k1Constants.N);

            // r is the x coordinate of the resulting point k*G (ephemeral public key)
            var r = BitcoinConstants.G.Multiply(k).X.Num;

            // 1/k = pow(k, N-2, N)
            var k_inv = BigInteger.ModPow(k, Secp256k1Constants.N - 2, Secp256k1Constants.N).Mod(Secp256k1Constants.N);

            // s = (z+r*prvKey) / k
            var s = ((z + (r * this.Value)) * k_inv).Mod(Secp256k1Constants.N);

            return(new Signature(r, s));
        }
Esempio n. 2
0
        public Signature Sign(byte[] data)
        {
            var hash = HashUtilities.Sha256(data);
            var z    = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(hash).Mod(Secp256k1Constants.N);

            return(Sign(z));
        }
Esempio n. 3
0
        public bool Verify(byte[] data, Signature s)
        {
            var hash = HashUtilities.Sha256(data);
            var z    = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(hash).Mod(Secp256k1Constants.N);

            return(Verify(z, s));
        }
Esempio n. 4
0
        public static PublicKey Parse(byte[] bytes, bool testNet = false)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }
            else if (bytes.Length == 33)
            {
                bool yIsEven;

                if (bytes[0] == 0x02)
                {
                    yIsEven = true;
                }
                else if (bytes[0] == 0x03)
                {
                    yIsEven = false;
                }
                else
                {
                    throw new Exception(string.Format("Compressed public key found (33 bytes) with invalid prefix. Expected 0x02 or 0x03, found 0x{0:X2}", bytes[0]));
                }

                var buffer = new byte[32];
                Buffer.BlockCopy(bytes, 1, buffer, 0, buffer.Length);
                var x = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(buffer);
                var y = Secp256k1Point.GetYCoordinate(new Secp256k1FieldElement(x), yIsEven);
                return(new PublicKey(x, y.Num, testNet, true));
            }
            else if (bytes.Length == 65)
            {
                if (bytes[0] != 0x04)
                {
                    throw new Exception(string.Format("Uncompressed public key found (65 bytes) with invalid prefix. Expected 0x04, found 0x{0:X2}", bytes[0]));
                }
                var buffer = new byte[32];
                Buffer.BlockCopy(bytes, 1, buffer, 0, buffer.Length);
                var x = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(buffer);
                Buffer.BlockCopy(bytes, 33, buffer, 0, buffer.Length);
                var y = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(buffer);
                return(new PublicKey(x, y, testNet, false));
            }
            else
            {
                throw new Exception(nameof(bytes) + " length is invalid, expected 33 bytes (compressed pub key) or 65 bytes (uncompressed pub key)");
            }
        }
Esempio n. 5
0
        public static PrivateKey CreateFromWifString(string wifString)
        {
            bool testNet;
            bool wifCompressed;

            byte[] rawBytes        = Base58Utilities.DecodeBase58Check(wifString);
            byte[] privateKeyBytes = new byte[32];

            // Compressed is 34 bytes, uncompressed is 33 bytes
            if (rawBytes.Length == 34 || rawBytes.Length == 33)
            {
                Buffer.BlockCopy(rawBytes, 1, privateKeyBytes, 0, 32);
                if (rawBytes[0] == 0xEF)
                {
                    testNet = true;
                }
                else if (rawBytes[0] == 0x80)
                {
                    testNet = false;
                }
                else
                {
                    throw new ArgumentException(nameof(wifString) + " prefix is invalid");
                }

                wifCompressed = rawBytes.Length == 34;
            }
            else
            {
                throw new ArgumentException(nameof(wifString) + " is invalid");
            }

            var val = BigIntegerUtilities.CreateFromUnsignedBigEndianBytes(privateKeyBytes);

            return(new PrivateKey(val, testNet, wifCompressed));
        }