Ejemplo n.º 1
0
        public void MultipleSignatureWays()
        {
            var privKeyStr = Encoders.Hex.DecodeData("8e812436a0e3323166e1f0e8ba79e19e217b2c4a53c970d4cca0cfb1078979df");
            Key key        = new Key(privKeyStr);

            Assert.AreEqual("04a5bb3b28466f578e6e93fbfd5f75cee1ae86033aa4bbea690e3312c087181eb366f9a1d1d6a437a9bf9fc65ec853b9fd60fa322be3997c47144eb20da658b3d1", key.PubKey.Decompress().ToHex());

            var messageToSign = "159817a085f113d099d3d93c051410e9bfe043cc5c20e43aa9a083bf73660145";
            var messageBytes  = Encoders.Hex.DecodeData(messageToSign);

            ECDSASignature signature = key.Sign(new uint256(messageBytes), true);

            SecpECDSASignature.TryCreateFromDer(signature.ToDER(), out SecpECDSASignature sig);
            var(r, s) = sig;

            var R = r.ToBytes();
            var S = s.ToBytes();

            Assert.AreEqual("38b7dac5ee932ac1bf2bc62c05b792cd93c3b4af61dc02dbb4b93dacb758123f", R.ToHexString());
            Assert.AreEqual("08bf123eabe77480787d664ca280dc1f20d9205725320658c39c6c143fd5642d", S.ToHexString());

            // Compact signature
            byte[] signatureCompact = key.SignCompact(new uint256(messageBytes), true);
            if (signatureCompact.Length != 65)
            {
                throw new ArgumentException(paramName: nameof(signatureCompact), message: "Signature truncated, expected 65");
            }

            var ss = signatureCompact.AsSpan();

            int recid = (ss[0] - 27) & 3;

            if (!(
                    SecpRecoverableECDSASignature.TryCreateFromCompact(ss.Slice(1), recid, out SecpRecoverableECDSASignature sigR) && sigR is SecpRecoverableECDSASignature
                    )
                )
            {
                throw new InvalidOperationException("Impossible to recover the public key");
            }

            // V from comapct signature
            var(r1, s1, v1) = sigR;

            Assert.AreEqual(v1, 0);

            // Recoverable signature with Secp256k1 lib
            NBitcoin.Secp256k1.ECPrivKey privKey = Context.Instance.CreateECPrivKey(new Scalar(key.ToBytes()));
            Assert.AreEqual(key.PubKey.ToBytes(), privKey.CreatePubKey().ToBytes());

            privKey.TrySignRecoverable(messageBytes, out SecpRecoverableECDSASignature sigRec);

            var(r2, s2, v2) = sigRec;

            Assert.AreEqual(r2, r);
            Assert.AreEqual(s2, s);
            Assert.AreEqual(v2, v1);
        }
Ejemplo n.º 2
0
        public void CreatePubKey()
        {
            Console.WriteLine();

            uint256 N    = uint256.Parse("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
            Random  rand = new Random();

            byte[]  privateKey = new byte[32];
            uint256 candidateKey;

            do
            {
                rand.NextBytes(privateKey);
                candidateKey = new uint256(privateKey, false);
            } while (!(candidateKey > 0 && candidateKey < N));

            // Public key
            privateKey = Encoders.Hex.DecodeData("da7639a9e2ed4e918b57151509ee34b3f80ad4ab60fb52de59cc3a7386b19007");

            NBitcoin.Secp256k1.ECPrivKey privKey = Context.Instance.CreateECPrivKey(new Scalar(privateKey));
            ECPubKey pubKey = privKey.CreatePubKey();

            byte[] pubKeyBytes = pubKey.ToBytes();
            // Console.WriteLine($"Pub key             : {Encoders.Hex.EncodeData(pubKeyBytes)}");

            var x = pubKey.Q.x.ToBytes();
            var y = pubKey.Q.y.ToBytes();

            Console.WriteLine($"Pub key x           :   {Encoders.Hex.EncodeData(x)}");
            Console.WriteLine($"Pub key y           :   {string.Empty.PadLeft(16, '\t')}{Encoders.Hex.EncodeData(y)}");

            var pubKeyUncomp = Helper.Concat(new byte[] { (04) }, x, y);

            Console.WriteLine($"Pub key (uncomp.)   : {Encoders.Hex.EncodeData(pubKeyUncomp)}");

            BigInteger yBig = new BigInteger(y, isUnsigned: true, isBigEndian: true);

            byte pubKeyPrefix = (byte)(yBig % 2 == 0 ? 02 : 03);
            var  pubKeyComp   = Helper.Concat(new byte[] { pubKeyPrefix }, x);

            Console.WriteLine($"Pub key (comp.)     : {Encoders.Hex.EncodeData(pubKeyComp)}");
            Assert.AreEqual(pubKeyBytes, pubKeyComp);
        }
Ejemplo n.º 3
0
        public void ShouldEncodeAddress()
        {
            var privateKey = Encoders.Hex.DecodeData("08089C24EC3BAEB34254DDF5297CF8FBB8E031496FF67B4EFACA738FF9EBD455");

            NBitcoin.Secp256k1.ECPrivKey privKey = Context.Instance.CreateECPrivKey(new Scalar(privateKey));
            ECPubKey pubKey = privKey.CreatePubKey();

            var x = pubKey.Q.x.ToBytes();
            var y = pubKey.Q.y.ToBytes();

            var pubKeyUncomp = Helper.Concat(x, y);

            Assert.AreEqual(
                "ee63599802b5d31a29c95cc7df04f427e8f0a124bed9333f3a80404acfc3127659c540d0162dedb81ac5f74b2deb4962656efe112b252e54ac3ba1207cd1fb10",
                Encoders.Hex.EncodeData(pubKeyUncomp)
                );

            var pubKeyHash = new Sha3Keccack().CalculateHash(pubKeyUncomp);

            Assert.AreEqual("0837725ba59e30e8e52ba5ab95679f3aaf5211991781d49b30525dddfe9a18de", pubKeyHash.ToHexString());

            var sha3HashBytes = new byte[20];

            Array.Copy(pubKeyHash, pubKeyHash.Length - 20, sha3HashBytes, 0, 20);

            byte[] PKHWithVersionBytes = Helper.Concat(new byte[] { 65 }, sha3HashBytes);
            var    hexAddress          = PKHWithVersionBytes.ToHexString();

            Assert.AreEqual("4195679F3AAF5211991781D49B30525DDDFE9A18DE".ToLower(), hexAddress);

            var result = Encoders.Base58Check.EncodeData(PKHWithVersionBytes);

            Assert.AreEqual(
                "TPbBpRXnt6ztse8XkCLiJstZyqQZvxW2sx",
                result
                );
        }
        public void CreateAddress()
        {
            Console.WriteLine();

            // Priv key length
            int KEY_SIZE = 32;

            // Max priv key value
            // 115792089237316195423570985008687907852837564279074904382605163141518161494337
            uint256 N = uint256.Parse("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");

            // Randomizer
            Random rand = new Random();

            byte[] privateKey = new byte[KEY_SIZE];

            // Generate a valid random value
            uint256 candidateKey;

            do
            {
                rand.NextBytes(privateKey);
                candidateKey = new uint256(privateKey, false);
            } while (!(candidateKey > 0 && candidateKey < N));
            Console.WriteLine($"Private key (hex)   : { Encoders.Hex.EncodeData(privateKey) }");

            // base58 encoded private key
            byte[] privKeyWithVersionBytes = Helper.Concat(new byte[] { 128 }, privateKey);
            string privKeyBase58           = Encoders.Base58Check.EncodeData(privKeyWithVersionBytes);

            Console.WriteLine($"Priv. key (Base58)  : {privKeyBase58}");

            // base58 encoded compressed private key
            byte[] compPrivKeyWithVersionBytes = Helper.Concat(privKeyWithVersionBytes, new byte[] { 01 });
            var    compPrivKeyBase58           = Encoders.Base58Check.EncodeData(compPrivKeyWithVersionBytes);

            Console.WriteLine($"Priv. key (Base58)  : {compPrivKeyBase58} (Compressed)");

            // Elliptic curve multiplication (with help of NBitcoin)
            // privateKey = Encoders.Hex.DecodeData("da7639a9e2ed4e918b57151509ee34b3f80ad4ab60fb52de59cc3a7386b19007"); // for testing
            NBitcoin.Secp256k1.ECPrivKey privKey = Context.Instance.CreateECPrivKey(new Scalar(privateKey));
            ECPubKey pubKey = privKey.CreatePubKey();

            // X, Y
            var x = pubKey.Q.x.ToBytes();
            var y = pubKey.Q.y.ToBytes();

            // Uncompressed public key
            var pubKeyUncomp = Helper.Concat(new byte[] { (04) }, x, y);

            Console.WriteLine($"Pub key (uncomp.)   : {Encoders.Hex.EncodeData(pubKeyUncomp)}");

            // Compressed public key
            BigInteger yBig       = new BigInteger(y, isUnsigned: true, isBigEndian: true);
            var        pubKeyComp = Helper.Concat(new byte[] { (byte)(yBig % 2 == 0 ? 02 : 03) }, x);

            Console.WriteLine($"Pub key (comp.)     : {Encoders.Hex.EncodeData(pubKeyComp)}");

            //// Uncompressed Public Key
            // Public key hash (pkh)

            var pubKeyHash    = NBitcoin.Crypto.Hashes.SHA256(pubKeyUncomp);
            var pubKeyHash160 = NBitcoin.Crypto.Hashes.RIPEMD160(pubKeyHash, pubKeyHash.Length);

            Console.WriteLine($"Public key hash     : {Encoders.Hex.EncodeData(pubKeyHash160)}");

            // base58 encoded pkh : address
            byte[] PKHWithVersionBytes = Helper.Concat(new byte[] { 00 }, pubKeyHash160);
            var    address             = Encoders.Base58Check.EncodeData(PKHWithVersionBytes);

            Assert.DoesNotThrow(() =>   {
                BitcoinAddress.Create(str: address, Network.Main);
            });
            Console.WriteLine($"Address             : {address}");

            //// Uncompressed Public Key (w/ checksum calculation)
            var hash1           = NBitcoin.Crypto.Hashes.SHA256(PKHWithVersionBytes);
            var hash2           = NBitcoin.Crypto.Hashes.SHA256(hash1);
            var checksum        = hash2.Take(4).ToArray();
            var pkhWithChecksum = Helper.Concat(PKHWithVersionBytes, checksum);

            var address1 = Encoders.Base58.EncodeData(pkhWithChecksum);

            Assert.AreEqual(address, address1);

            //// Compressed Public Key
            // Public key hash (Compressed)
            var pubKeyCompHash    = NBitcoin.Crypto.Hashes.SHA256(pubKeyComp);
            var pubKeyCompHash160 = NBitcoin.Crypto.Hashes.RIPEMD160(pubKeyCompHash, pubKeyCompHash.Length);

            // base58 encoded compressed pkh : address
            byte[] compPKHWithVersionBytes = Helper.Concat(new byte[] { 00 }, pubKeyCompHash160);
            var    addressComp             = Encoders.Base58Check.EncodeData(compPKHWithVersionBytes);

            Assert.DoesNotThrow(() =>   {
                BitcoinAddress.Create(str: addressComp, Network.Main);
            });
            Console.WriteLine($"Address (Comp.)     : {addressComp}");
        }