Ejemplo n.º 1
0
 public PubKey Compress()
 {
     if (IsCompressed)
     {
         return(this);
     }
     return(ECKey.GetPubKey(true));
 }
Ejemplo n.º 2
0
        public PubKey Compress()
        {
            if (IsCompressed)
            {
                return(this);
            }
#if HAS_SPAN
            return(new PubKey(this._ECKey, true));
#else
            return(ECKey.GetPubKey(true));
#endif
        }
Ejemplo n.º 3
0
        public static PubKey RecoverCompact(uint256 hash, CompactSignature compactSignature)
        {
            if (compactSignature is null)
            {
                throw new ArgumentNullException(nameof(compactSignature));
            }
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(hash));
            }
#if HAS_SPAN
            Span <byte> msg = stackalloc byte[32];
            hash.ToBytes(msg);
            if (Secp256k1.SecpRecoverableECDSASignature.TryCreateFromCompact(compactSignature.Signature, compactSignature.RecoveryId, out var sig) &&
                Secp256k1.ECPubKey.TryRecover(NBitcoinContext.Instance, sig, msg, out var pubkey))
            {
                return(new PubKey(pubkey, true));
            }
            throw new InvalidOperationException("Impossible to recover the public key");
#else
            BigInteger r = new BigInteger(1, compactSignature.Signature.SafeSubarray(0, 32));
            BigInteger s = new BigInteger(1, compactSignature.Signature.SafeSubarray(32, 32));
#pragma warning disable 618
            var sig = new ECDSASignature(r, s);
#pragma warning restore 618
            ECKey key = ECKey.RecoverFromSignature(compactSignature.RecoveryId, sig, hash);
            return(key.GetPubKey(true));
#endif
        }
Ejemplo n.º 4
0
        public byte[] SignCompact(uint256 hash)
        {
            ECDSASignature sig = this._ECKey.Sign(hash);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            int recId = -1;

            for (int i = 0; i < 4; i++)
            {
                ECKey k = ECKey.RecoverFromSignature(i, sig, hash, this.IsCompressed);
                if (k != null && k.GetPubKey(this.IsCompressed).ToHex() == this.PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }

            int headerByte = recId + 27 + (this.IsCompressed ? 4 : 0);

            var sigData = new byte[65];  // 1 header + 32 bytes for R + 32 bytes for S

            sigData[0] = (byte)headerByte;

            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 1, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 33, 32);
            return(sigData);
        }
Ejemplo n.º 5
0
        public static byte[] RecoverPublickey(byte[] msgHash, byte[] signature)
        {
            if (signature.Length != 65)
            {
                throw new ArgumentException("signature invalid");
            }

            byte[] r = new byte[32];
            byte[] s = new byte[32];
            byte[] v = new byte[1];

            try
            {
                Array.Copy(signature, 0, r, 0, 32);
                Array.Copy(signature, 32, s, 0, 32);
                Array.Copy(signature, 64, v, 0, 1);

                int V = Convert.ToInt32(v[0]);

                if (V != 0 && V != 1)
                {
                    throw new ArgumentException("invalid signature recovery");
                }

                ECDSASignature sign  = new ECDSASignature(new DerInteger(r).PositiveValue, new DerInteger(s).PositiveValue);
                ECKey          ecKey = ECKey.RecoverFromSignature(V, sign, msgHash, false);
                return(ecKey.GetPubKey(false));
            }
            catch
            {
                throw new ArgumentException("signature invalid");
            }
        }
Ejemplo n.º 6
0
        public static PubKey RecoverCompact(uint256 hash, byte[] signatureEncoded)
        {
            if (signatureEncoded.Length < 65)
            {
                throw new ArgumentException("Signature truncated, expected 65 bytes and got " + signatureEncoded.Length);
            }


            int header = signatureEncoded[0];

            // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
            //                  0x1D = second key with even y, 0x1E = second key with odd y

            if (header < 27 || header > 34)
            {
                throw new ArgumentException("Header byte out of range: " + header);
            }

            ECDSASignature sig        = DecodeSig(signatureEncoded);
            bool           compressed = false;

            if (header >= 31)
            {
                compressed = true;
                header    -= 4;
            }
            int recId = header - 27;

            ECKey key = ECKey.RecoverFromSignature(recId, sig, hash, compressed);

            return(key.GetPubKey(compressed));
        }
Ejemplo n.º 7
0
 public PubKey Decompress()
 {
     if (!IsCompressed)
     {
         return(this);
     }
     return(ECKey.GetPubKey(false));
 }
Ejemplo n.º 8
0
        public static byte[] GetPubKeyNoPrefix(this ECKey key)
        {
            var pubKey = key.GetPubKey(false);
            var arr    = new byte[pubKey.Length - 1];

            //remove the prefix
            Array.Copy(pubKey, 1, arr, 0, arr.Length);
            return(arr);
        }
Ejemplo n.º 9
0
        public byte[] GeneratePublicKey(
            byte[] privateKey)
        {
            var ecKey = new ECKey(privateKey, true);

            return(ecKey
                   .GetPubKey(false)
                   .Skip(1) // Skipping prefix
                   .ToArray());
        }
Ejemplo n.º 10
0
        public static byte[] DerivePublicKey(byte[] privatekey)
        {
            if (IsValidPrivateKey(privatekey))
            {
                ECKey key = new ECKey(privatekey, true);
                return(key.GetPubKey(false));
            }

            throw new ArgumentException("invalid private key");
        }
Ejemplo n.º 11
0
 //Note: Y coordinates can only be forced, so it is assumed 0 and 1 will be the recId (even if implementation allows for 2 and 3)
 internal int CalculateRecId(ECDSASignature signature, byte[] hash)
 {
   var recId = -1;
   var thisKey = _ecKey.GetPubKey(false); // compressed
   for (var i = 0; i \      {
     var rec = ECKey.RecoverFromSignature(i, signature, hash, false);
     if (rec != null)
     {
       var k = rec.GetPubKey(false);
       if (k != null && k.SequenceEqual(thisKey))
       {
         recId = i;
         break;
       }
     }
   }
   if (recId == -1)
     throw new Exception("Could not construct a recoverable key. This should never happen.");
   return recId;
 }
Ejemplo n.º 12
0
        public void TestPublicKey()
        {
            var privateKey = "F43EBCC94E6C257EDBE559183D1A8778B2D5A08040902C0F0A77A3343A1D0EA5";

            var prvKey = privateKey.HexToByteArray();
            var ecKey  = new ECKey(prvKey, true);

            var publicKey0 = ecKey.GetPubKey();
            var publicKey1 = private2PublicDemo(prvKey);

            Assert.Equal(publicKey0, publicKey1);
        }
Ejemplo n.º 13
0
        public static PubKey RecoverCompact(uint256 hash, byte[] signatureEncoded)
        {
#if HAS_SPAN
            if (signatureEncoded.Length != 65)
            {
                throw new ArgumentException(paramName: nameof(signatureEncoded), message: "Signature truncated, expected 65");
            }
            Span <byte> msg = stackalloc byte[32];
            hash.ToBytes(msg);
            var  s     = signatureEncoded.AsSpan();
            int  recid = (s[0] - 27) & 3;
            bool fComp = ((s[0] - 27) & 4) != 0;
            Secp256k1.ECPubKey pubkey;
            Secp256k1.SecpRecoverableECDSASignature sig;
            if (Secp256k1.SecpRecoverableECDSASignature.TryCreateFromCompact(s.Slice(1), recid, out sig) && sig is Secp256k1.SecpRecoverableECDSASignature &&
                Secp256k1.ECPubKey.TryRecover(NBitcoinContext.Instance, sig, msg, out pubkey) && pubkey is Secp256k1.ECPubKey)
            {
                return(new PubKey(pubkey, fComp));
            }
            throw new InvalidOperationException("Impossible to recover the public key");
#else
            if (signatureEncoded.Length < 65)
            {
                throw new ArgumentException("Signature truncated, expected 65 bytes and got " + signatureEncoded.Length);
            }


            int header = signatureEncoded[0];

            // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
            //                  0x1D = second key with even y, 0x1E = second key with odd y

            if (header < 27 || header > 34)
            {
                throw new ArgumentException("Header byte out of range: " + header);
            }

            var  sig        = DecodeSig(signatureEncoded);
            bool compressed = false;

            if (header >= 31)
            {
                compressed = true;
                header    -= 4;
            }
            int recId = header - 27;

            ECKey key = ECKey.RecoverFromSignature(recId, sig, hash, compressed);
            return(key.GetPubKey(compressed));
#endif
        }
Ejemplo n.º 14
0
        //Note: Y coordinates can only be forced, so it is assumed 0 and 1 will be the recId (even if implementation allows for 2 and 3)
        internal int CalculateRecId(ECDSASignature signature, byte[] hash)
        {
            //var recId = -1;
            var thisKey = _ecKey.GetPubKey(false); // compressed

            return(CalculateRecId(signature, hash, thisKey));
            //for (var i = 0; i < 4; i++)
            //{
            //    var rec = ECKey.RecoverFromSignature(i, signature, hash, false);
            //    if (rec != null)
            //    {
            //        var k = rec.GetPubKey(false);
            //        if (k != null && k.SequenceEqual(thisKey))
            //        {
            //            recId = i;
            //            break;
            //        }
            //    }
            //}
            //if (recId == -1)
            //    throw new Exception("Could not construct a recoverable key. This should never happen.");
            //return recId;
        }
Ejemplo n.º 15
0
        public byte[] SignCompact(uint256 hash, bool forceLowR)
        {
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(hash));
            }
            AssertNotDisposed();
#if HAS_SPAN
            Span <byte> vchSig = stackalloc byte[65];
            int         rec    = -1;
            var         sig    = new Secp256k1.SecpRecoverableECDSASignature(_ECKey.Sign(hash, forceLowR, out rec), rec);
            sig.WriteToSpanCompact(vchSig.Slice(1), out int recid);
            vchSig[0] = (byte)(27 + rec + (IsCompressed ? 4 : 0));
            return(vchSig.ToArray());
#else
            var sig = _ECKey.Sign(hash, forceLowR);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            int recId = -1;
            for (int i = 0; i < 4; i++)
            {
                ECKey k = ECKey.RecoverFromSignature(i, sig, hash, IsCompressed);
                if (k != null && k.GetPubKey(IsCompressed).ToHex() == PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }

            int headerByte = recId + 27 + (IsCompressed ? 4 : 0);

            byte[] sigData = new byte[65];              // 1 header + 32 bytes for R + 32 bytes for S

            sigData[0] = (byte)headerByte;
#pragma warning disable 618
            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 1, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 33, 32);
#pragma warning restore 618
            return(sigData);
#endif
        }
Ejemplo n.º 16
0
        public CompactSignature SignCompact(uint256 hash, bool forceLowR)
        {
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(hash));
            }
            if (!IsCompressed)
            {
                throw new InvalidOperationException("This operation is only supported on compressed pubkey");
            }
            AssertNotDisposed();
#if HAS_SPAN
            byte[] sigBytes = new byte[64];
            var    sig      = new Secp256k1.SecpRecoverableECDSASignature(_ECKey.Sign(hash, forceLowR, out var rec), rec);
            sig.WriteToSpanCompact(sigBytes, out _);
            return(new CompactSignature(rec, sigBytes));
#else
            var sig = _ECKey.Sign(hash, forceLowR);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            int recId = -1;
            for (int i = 0; i < 4; i++)
            {
                ECKey k = ECKey.RecoverFromSignature(i, sig, hash);
                if (k != null && k.GetPubKey(true).ToHex() == PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }
#pragma warning disable 618
            byte[] sigData = new byte[64];              // 1 header + 32 bytes for R + 32 bytes for S
            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 0, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 32, 32);
#pragma warning restore 618
            return(new CompactSignature(recId, sigData));
#endif
        }
Ejemplo n.º 17
0
        public static int CalculateRecId(this ECKey key, ECDSASignature signature, byte[] hash)
        {
            var recId   = -1;
            var thisKey = key.GetPubKey(false); // compressed

            for (var i = 0; i < 4; i++)
            {
                var k = ECKey.RecoverFromSignature(i, signature, hash, false).GetPubKey(false);
                if (k != null && Enumerable.SequenceEqual(k, thisKey))
                {
                    recId = i;
                    break;
                }
            }
            if (recId == -1)
            {
                throw new Exception("Could not construct a recoverable key. This should never happen.");
            }
            return(recId);
        }
Ejemplo n.º 18
0
 public byte[] GetPubKey()
 {
     return(_ecKey.GetPubKey());
 }
Ejemplo n.º 19
0
        //Note: Y coordinates can only be forced, so it is assumed 0 and 1 will be the recId (even if implementation allows for 2 and 3)
        internal int CalculateRecId(ECDSASignature signature, byte[] hash)
        {
            var thisKey = _ecKey.GetPubKey(false); // compressed

            return(CalculateRecId(signature, hash, thisKey));
        }
Ejemplo n.º 20
0
        public static PubKey RecoverFromSignature(int recId, ECDSASignature sig, uint256 hash, bool compressed)
        {
            ECKey key = ECKey.RecoverFromSignature(recId, sig, hash, compressed);

            return(key?.GetPubKey(compressed));
        }
Ejemplo n.º 21
0
        private static int CalculateRecId(ECKey eckey, ECDSASignature signature, byte[] hash)
        {
            var thisKey = eckey.GetPubKey(false);

            return(CalculateRecId(signature, hash, thisKey));
        }