Last active
April 30, 2023 10:41
-
-
Save mvanhalen/e37e384e2d4a2199f0ff23b458a81833 to your computer and use it in GitHub Desktop.
Sign DeSo transaction correct version. Working after April Fork.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections.Generic; | |
| using System.Linq; | |
| using System.Net.Http; | |
| using System.Net.Http.Headers; | |
| using System.Text; | |
| using System.Threading.Tasks; | |
| using Newtonsoft.Json; | |
| using Org.BouncyCastle.Asn1; | |
| using Org.BouncyCastle.Asn1.Sec; | |
| using Org.BouncyCastle.Crypto.Digests; | |
| using Org.BouncyCastle.Crypto.Parameters; | |
| using Org.BouncyCastle.Crypto.Signers; | |
| using Org.BouncyCastle.Math; | |
| public partial class TransactionHelpers | |
| { | |
| public static async Task<long> GetSignatureFieldLenght(string transactionHex) | |
| { | |
| long result = 0; | |
| HttpClient hc = new HttpClient(); | |
| Txn data = new Txn() | |
| { | |
| TransactionHex = transactionHex, | |
| }; | |
| string path = "api/v0/signature-index"; | |
| StringContent content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json"); | |
| hc.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); | |
| content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); | |
| HttpResponseMessage response = await hc.PostAsync(apiUrl + path, content); | |
| if (response.StatusCode == System.Net.HttpStatusCode.OK) | |
| { | |
| string json = await response.Content.ReadAsStringAsync(); | |
| if (!string.IsNullOrEmpty(json)) | |
| { | |
| IndexTxnResponse signatureIndex = JsonConvert.DeserializeObject<IndexTxnResponse>(json); | |
| result = signatureIndex.SignatureIndex; | |
| } | |
| } | |
| return result; | |
| } | |
| public static async Task<string> SignTransaction(string privateKey, string txnHex) | |
| { | |
| var curve = SecNamedCurves.GetByName("secp256k1"); | |
| var domain = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H); | |
| var keyParameters = new ECPrivateKeyParameters(new BigInteger(privateKey, 16), domain); | |
| var signer = new ECDsaSigner(new HMacDsaKCalculator(new Sha256Digest())); | |
| signer.Init(true, keyParameters); | |
| var txnBytes = Convert(txnHex); | |
| var hash = GetHash(GetHash(txnBytes)); | |
| var signature = signer.GenerateSignature(hash); | |
| var r = signature[0]; | |
| var s = signature[1]; | |
| var otherS = curve.Curve.Order.Subtract(s); | |
| if (s.CompareTo(otherS) == 1) | |
| { | |
| s = otherS; | |
| } | |
| var derSignature = new DerSequence | |
| ( | |
| new DerInteger(new BigInteger(1, r.ToByteArray())), | |
| new DerInteger(new BigInteger(1, s.ToByteArray())) | |
| ) | |
| .GetDerEncoded(); | |
| long signatureIndex = await GetSignatureFieldLenght(txnHex); | |
| byte[] v0FieldsWithoutSignature = txnBytes.Take((int)signatureIndex).ToArray(); | |
| byte[] v1FieldsBuffer = txnBytes.Skip((int)signatureIndex + 1).ToArray(); | |
| var sigBytes =new List<byte>(); | |
| foreach(var item in v0FieldsWithoutSignature) | |
| { | |
| sigBytes.Add(item); | |
| } | |
| sigBytes.Add((byte)(derSignature.Length)); | |
| foreach(var item in derSignature) | |
| { | |
| sigBytes.Add(item); | |
| } | |
| foreach(var item in v1FieldsBuffer) | |
| { | |
| sigBytes.Add(item); | |
| } | |
| string signedTxn = Convert(sigBytes.ToArray()); | |
| return signedTxn; | |
| } | |
| private static byte[] GetHash(byte[] data) | |
| { | |
| var digest = new Sha256Digest(); | |
| var hash = new byte[digest.GetDigestSize()]; | |
| digest.BlockUpdate(data, 0, data.Length); | |
| digest.DoFinal(hash, 0); | |
| return hash; | |
| } | |
| public static string Convert(byte[] input) | |
| { | |
| return string.Concat(input.Select(x => x.ToString("x2"))); | |
| } | |
| public static byte[] Convert(string input) | |
| { | |
| if (input.StartsWith("0x")) input = input.Remove(0, 2); | |
| return Enumerable.Range(0, input.Length / 2).Select(x => System.Convert.ToByte(input.Substring(x * 2, 2), 16)).ToArray(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment