public static bool TryCreateFromCompact(ReadOnlySpan <byte> in64, int recid, [MaybeNullWhen(false)] out SecpRecoverableECDSASignature sig) { sig = null; if (SecpECDSASignature.TryCreateFromCompact(in64, out var compact) && compact is SecpECDSASignature) { sig = new SecpRecoverableECDSASignature(compact, recid); return(true); } return(false); }
public bool TrySignRecoverable(ReadOnlySpan <byte> msg32, INonceFunction?nonceFunction, out SecpRecoverableECDSASignature?recoverableSignature) { if (msg32.Length != 32) { throw new ArgumentException(paramName: nameof(msg32), message: "msg32 should be 32 bytes"); } if (this.TrySignECDSA(msg32, nonceFunction, out int recid, out SecpECDSASignature? sig) && sig is SecpECDSASignature) { recoverableSignature = new SecpRecoverableECDSASignature(sig, recid); return(true); } recoverableSignature = null; return(false); }
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 }