public static BigInteger ComputeSecretKey( BigInteger privateGen, uint accountNumber) { ECPoint publicGen = ComputePublicGenerator(privateGen); return ComputeScalar(publicGen.GetEncoded(true), accountNumber) .Add(privateGen).Mod(Secp256K1.Order()); }
private EcdsaSignature CreateEcdsaSignature(byte[] hash) { BigInteger[] sigs = _signer.GenerateSignature(hash); var r = sigs[0]; var s = sigs[1]; var otherS = Secp256K1.Order().Subtract(s); if (s.CompareTo(otherS) == 1) { s = otherS; } return(new EcdsaSignature(r, s)); }
/// <param name="seedBytes"> - a bytes sequence of arbitrary length which will be hashed </param> /// <param name="discriminator"> - nullable optional uint32 to hash </param> /// <returns> a number between [1, order -1] suitable as a private key /// </returns> public static BigInteger ComputeScalar(byte[] seedBytes, uint?discriminator) { BigInteger key = null; for (uint i = 0; i <= 0xFFFFFFFFL; i++) { var sha512 = new Sha512(seedBytes); if (discriminator != null) { sha512.AddU32(discriminator.Value); } sha512.AddU32(i); byte[] keyBytes = sha512.Finish256(); key = Misc.UBigInt(keyBytes); if (key.CompareTo(BigInteger.Zero) == 1 && key.CompareTo(Secp256K1.Order()) == -1) { break; } } return(key); }
public static bool CheckIsCanonical(byte[] sig, bool strict) { // Make sure signature is canonical // To protect against signature morphing attacks // Signature should be: // \\ \\ [ \\ \\ \\ ] [ \\ \\ \\ ] // where // 6 \\ 72)) { return(false); } if ((sig[0] != 0x30) || (sig[1] != (sigLen - 2))) { return(false); } // Find R and check its length int rPos = 4, rLen = sig[rPos - 1]; if ((rLen \ \ 33) || ((rLen + 7) \ > \ sigLen)) { return(false); } // Find S and check its length int sPos = rLen + 6, sLen = sig[sPos - 1]; if ((sLen \ \ 33) || ((rLen + sLen + 6) != sigLen)) { return(false); } if ((sig[rPos - 2] != 0x02) || (sig[sPos - 2] != 0x02)) { return(false); // R or S have wrong type } if ((sig[rPos] & 0x80) != 0) { return(false); // R is negative } if ((sig[rPos] == 0) && rLen == 1) { return(false); // R is zero } if ((sig[rPos] == 0) && ((sig[rPos + 1] & 0x80) == 0)) { return(false); // R is padded } if ((sig[sPos] & 0x80) != 0) { return(false); // S is negative } if ((sig[sPos] == 0) && sLen == 1) { return(false); // S is zero } if ((sig[sPos] == 0) && ((sig[sPos + 1] & 0x80) == 0)) { return(false); // S is padded } byte[] rBytes = new byte[rLen]; byte[] bytes = new byte[sLen]; Array.Copy(sig, rPos, rBytes, 0, rLen); Array.Copy(sig, sPos, bytes, 0, sLen); BigInteger r = new BigInteger(1, rBytes), s = new BigInteger(1, bytes); BigInteger order = Secp256K1.Order(); if (r.CompareTo(order) != -1 || s.CompareTo(order) != -1) { return(false); // R or S greater than modulus } if (strict) { return(order.Subtract(s).CompareTo(s) != -1); } else { return(true); } }