Example #1
0
        private TransactionSignature MakeHighS(TransactionSignature sig)
        {
            var curveOrder = new NBitcoin.BouncyCastle.Math.BigInteger("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10);
            var ecdsa      = new ECDSASignature(sig.Signature.R, sig.Signature.S.Negate().Mod(curveOrder));

            return(new TransactionSignature(ecdsa, sig.SigHash));
        }
Example #2
0
        private string EncodeTarget(double difficulty)
        {
            var diff     = BigInteger.ValueOf((long)(difficulty * 255d));
            var quotient = ZCashConstants.Diff1.Divide(diff).Multiply(BigInteger.ValueOf(255));
            var bytes    = quotient.ToByteArray();
            var padded   = ArrayPool <byte> .Shared.Rent(ZCashConstants.TargetPaddingLength);

            try
            {
                Array.Clear(padded, 0, ZCashConstants.TargetPaddingLength);
                var padLength = ZCashConstants.TargetPaddingLength - bytes.Length;

                if (padLength > 0)
                {
                    Array.Copy(bytes, 0, padded, padLength, bytes.Length);
                    bytes = padded;
                }

                var result = bytes.ToHexString(0, ZCashConstants.TargetPaddingLength);
                return(result);
            }

            finally
            {
                ArrayPool <byte> .Shared.Return(padded);
            }
        }
Example #3
0
        private static ECPoint DecompressKey(NBitcoin.BouncyCastle.Math.BigInteger xBN, bool yBit)
        {
            var curve = ECKey.Secp256k1.Curve;

            byte[] compEnc = X9IntegerConverter.IntegerToBytes(xBN, 1 + X9IntegerConverter.GetByteLength(curve));
            compEnc[0] = (byte)(yBit ? 0x03 : 0x02);
            return(curve.DecodePoint(compEnc));
        }
Example #4
0
        internal static Array BigIntegerToBytes(NBitcoin.BouncyCastle.Math.BigInteger b, int numBytes)
        {
            if (b == null)
            {
                return(null);
            }
            byte[] bytes   = new byte[numBytes];
            byte[] biBytes = b.ToByteArray();
            int    start   = (biBytes.Length == numBytes + 1) ? 1 : 0;
            int    length  = Math.Min(biBytes.Length, numBytes);

            Array.Copy(biBytes, start, bytes, numBytes - length, length);
            return(bytes);
        }
Example #5
0
        private string EncodeTarget(double difficulty)
        {
            var diff     = BigInteger.ValueOf((long)(difficulty * 255d));
            var quotient = ZCashConstants.Diff1.Divide(diff).Multiply(BigInteger.ValueOf(255));
            var bytes    = quotient.ToByteArray();
            var padded   = Enumerable.Repeat((byte)0, 32).ToArray();

            if (padded.Length - bytes.Length > 0)
            {
                Buffer.BlockCopy(bytes, 0, padded, padded.Length - bytes.Length, bytes.Length);
                bytes = padded;
            }

            var result = bytes.ToHexString();

            return(result);
        }
Example #6
0
 internal Target ChangeDifficulty(ChainedHeader header, int difficultyAdjustmentDivisor)
 {
     NBitcoin.BouncyCastle.Math.BigInteger newTarget = header.Header.Bits.ToBigInteger();
     newTarget = newTarget.Divide(NBitcoin.BouncyCastle.Math.BigInteger.ValueOf(difficultyAdjustmentDivisor));
     return(new Target(newTarget));
 }
Example #7
0
        public static ECKey RecoverFromSignature(int recId, ECDSASignature sig, uint256 message, bool compressed)
        {
            if (recId < 0)
            {
                throw new ArgumentException("recId should be positive");
            }
            if (sig.R.SignValue < 0)
            {
                throw new ArgumentException("r should be positive");
            }
            if (sig.S.SignValue < 0)
            {
                throw new ArgumentException("s should be positive");
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }


            var curve = ECKey.Secp256k1;

            // 1.0 For j from 0 to h   (h == recId here and the loop is outside this function)
            //   1.1 Let x = r + jn

            var n = curve.N;
            var i = NBitcoin.BouncyCastle.Math.BigInteger.ValueOf((long)recId / 2);
            var x = sig.R.Add(i.Multiply(n));

            //   1.2. Convert the integer x to an octet string X of length mlen using the conversion routine
            //        specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
            //   1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the
            //        conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then
            //        do another iteration of Step 1.
            //
            // More concisely, what these points mean is to use X as a compressed public key.
            var prime = ((SecP256K1Curve)curve.Curve).QQ;

            if (x.CompareTo(prime) >= 0)
            {
                return(null);
            }

            // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities.
            // So it's encoded in the recId.
            ECPoint R = DecompressKey(x, (recId & 1) == 1);

            //   1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility).

            if (!R.Multiply(n).IsInfinity)
            {
                return(null);
            }

            //   1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification.
            var e = new NBitcoin.BouncyCastle.Math.BigInteger(1, message.ToBytes());
            //   1.6. For k from 1 to 2 do the following.   (loop is outside this function via iterating recId)
            //   1.6.1. Compute a candidate public key as:
            //               Q = mi(r) * (sR - eG)
            //
            // Where mi(x) is the modular multiplicative inverse. We transform this into the following:
            //               Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
            // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation
            // ** is point multiplication and + is point addition (the EC group operator).
            //
            // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive
            // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8.

            var     eInv     = NBitcoin.BouncyCastle.Math.BigInteger.Zero.Subtract(e).Mod(n);
            var     rInv     = sig.R.ModInverse(n);
            var     srInv    = rInv.Multiply(sig.S).Mod(n);
            var     eInvrInv = rInv.Multiply(eInv).Mod(n);
            ECPoint q        = ECAlgorithms.SumOfTwoMultiplies(curve.G, eInvrInv, R, srInv);

            q = q.Normalize();
            if (compressed)
            {
                q = new SecP256K1Point(curve.Curve, q.XCoord, q.YCoord, true);
            }
            return(new ECKey(q.GetEncoded(), false));
        }