🔢C# Example
C# Example of RSA signature implementation with signature verify
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography; using System.Text;
using System.Threading.Tasks;
namespace Elixir {
public static class EndPoints {
static string baseURL = "https://kend.elixir.app";
// Verifies a signature against the signature verification endpoint
public static async Task<string> SignatureVerify(string body) {
try {
// Compose URL
WebRequest request = WebRequest.Create($"{baseURL}/sdk/v2/signature/verify"); // Use POST
request.Method = "POST";
// Get Epoch time in milliseconds.
string timeStamp = (System.DateTime.UtcNow - new System.DateTime(1970, 1, 1)).TotalMilliseconds.ToString();
// Calculate body signature
string signature = Crypto.SignFromFile(body, timeStamp, "key.pem");
// Set headers
request.Headers["content-type"] = "application/json";
request.Headers["x-api-token"] = timeStamp;
// Public key
request.Headers["x-api-key"] = File.ReadAllText("public.key");
// Signature
request.Headers["x-api-signature"] = signature;
// Body to binary
var data = Encoding.UTF8.GetBytes(body);
// Set request content length.
request.ContentLength = data.Length;
// Write data to request.
Stream newStream = request.GetRequestStream();
newStream.Write(data, 0, data.Length);
// Wait for response
WebResponse response = await request.GetResponseAsync();
// Read response data
var reader = new StreamReader(response.GetResponseStream(), ASCIIEncoding.UTF8);
return reader.ReadToEnd();
} catch(Exception e) {
return e.Message;
}
}
internal static class Crypto {
// Sign message reading PK from file
public static string SignFromFile(string body, string timeStamp, string file) {
return Sign(body, timeStamp, File.ReadAllText(file));
}
// Sign message given in body, with the given timestamp and private key
public static string Sign(string body, string timeStamp, string privateKey) {
RSACryptoServiceProvider provider = GetRSA(privateKey);
byte[] signature = provider.SignData(Encoding.UTF8.GetBytes($"{body}.{timeStamp}"), CryptoConfig.CreateFromName("SHA256"));
StringBuilder hex = new StringBuilder(signature.Length * 2);
foreach (byte b in signature) hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
const string KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
const string KEY_FOOTER = "-----END PRIVATE KEY-----";
internal static RSACryptoServiceProvider GetRSA(string pem) {
string keyFormatted = pem;
int cutIndex = keyFormatted.IndexOf(KEY_HEADER);
keyFormatted = keyFormatted.Substring(cutIndex, keyFormatted.Length - cutIndex);
cutIndex = keyFormatted.IndexOf(KEY_FOOTER);
keyFormatted = keyFormatted.Substring(0, cutIndex + KEY_FOOTER.Length); keyFormatted = keyFormatted.Replace(KEY_HEADER, "");
keyFormatted = keyFormatted.Replace(KEY_FOOTER, "");
keyFormatted = keyFormatted.Replace("\r", "");
keyFormatted = keyFormatted.Replace("\n", ""); keyFormatted = keyFormatted.Trim();
byte[] privateKeyRaw = System.Convert.FromBase64String(keyFormatted);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportPkcs8PrivateKey(new ReadOnlySpan<byte>(privateKeyRaw), out _);
return rsa;
}
Last updated