/// <summary> /// Sign the message with <see cref="ECKeyPair"/>. Only recovery id 0 or 1 is accepted, otherwise the method will continue to retry to sign til get recovery id is 0 or 1. /// </summary> /// <param name="message">message to be signed</param> /// <param name="keyPair"></param> /// <param name="needToHash">set true if the message to be hashed before signing. If it is true, hashed first,then sign. If it is false, signed directly.</param> /// <returns></returns> public static SignatureData SignMessage(byte[] message, ECKeyPair keyPair, bool needToHash) { var publicKey = keyPair.PublicKey; byte[] messageHash; messageHash = needToHash ? CryptoUtils.Blake2b(message) : message; int recId = -1; ECDSASignature sig; sig = keyPair.Sign(messageHash); for (int i = 0; i < 4; i++) { var k = RecoverFromSignature(i, sig, messageHash); if (k != null && k.Equals(publicKey)) { recId = i; break; } } if (recId == -1) { throw new SignException("Sign the data failed."); } if (recId == 2 || recId == 3) { throw new SignException("Recovery is not valid for VeChain MainNet."); } byte v = (byte)recId; var r = ByteUtils.ToBytesPadded(sig.R, 32); var s = ByteUtils.ToBytesPadded(sig.S, 32); return(new SignatureData(v, r, s)); }