Created
January 23, 2020 14:01
-
-
Save apotox/4ecadd7aa1f274bd7a886f254cb1a114 to your computer and use it in GitHub Desktop.
RSA signature sample code without RSACryptoServiceProvider
This file contains 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; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Numerics; | |
using System.Security.Cryptography; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
using System.Globalization; | |
//RSA signature sample example | |
namespace RSASIGNATURE | |
{ | |
public class RSASIGNATURE | |
{ | |
public BigInteger e, p, q, n, phi; | |
private BigInteger Encrypt(BigInteger m, BigInteger e, BigInteger n) //encryption | |
{ | |
return BigInteger.ModPow(m, e, n); | |
} | |
private BigInteger Decrypt(BigInteger cResult, BigInteger d, BigInteger n) //decryption | |
{ | |
return BigInteger.ModPow(cResult, d, n); | |
} | |
private void generateParams(string p_str, string q_str) | |
{ | |
p = BigInteger.Parse(p_str); | |
q = BigInteger.Parse(q_str); | |
e = BigInteger.Parse("65537"); | |
n = p * q; | |
phi = (p - 1) * (q - 1); | |
} | |
private Tuple<BigInteger, BigInteger, BigInteger> generatePrivateKey() | |
{ | |
return egcd(e, phi); | |
} | |
Tuple<BigInteger, BigInteger, BigInteger> egcd(BigInteger a, BigInteger b) | |
{ | |
BigInteger x = 0, y = 1, u = 1, v = 0, gcd = 0; | |
while (a != 0) | |
{ | |
q = b / a; | |
BigInteger r = b % a; | |
BigInteger m = x - u * q; | |
BigInteger n = y - v * q; | |
b = a; | |
a = r; | |
x = u; | |
y = v; | |
u = m; | |
v = n; | |
gcd = b; | |
} | |
if (x < 0) x += phi; | |
if (y < 0) y += phi; | |
return Tuple.Create(gcd, x, y); | |
} | |
public string Sign(string message, string privatekey) | |
{ | |
string hash = CalculateMD5Hash(message); | |
var pr_object = JObject.Parse(GZIP.DecompressString(privatekey)); | |
var big = BigInteger.Parse(hash, NumberStyles.HexNumber); //new BigInteger(Encoding.ASCII.GetBytes(hash)); | |
var signature = this.Encrypt(big, BigInteger.Parse(pr_object.GetValue("d").ToString()), BigInteger.Parse(pr_object.GetValue("n").ToString())); // to hex | |
return signature.ToString("X"); | |
} | |
public string[] encodeKeys() | |
{ | |
var gcd_d_y = this.generatePrivateKey(); | |
var pk = new | |
{ | |
n = this.n, | |
e = this.e | |
}; | |
var pr = new | |
{ | |
n = this.n, | |
d = gcd_d_y.Item2 | |
}; | |
return new String[] { GZIP.CompressString(JsonConvert.SerializeObject(pk)), GZIP.CompressString(JsonConvert.SerializeObject(pr)) }; | |
} | |
public JObject[] decodeKeys(string pk, string pr) | |
{ | |
var pk_object = JObject.Parse(GZIP.DecompressString(pk)); | |
var pr_object = JObject.Parse(GZIP.DecompressString(pr)); | |
return new JObject[] { pk_object, pr_object }; | |
} | |
public bool Verify(string message, string publickey, string signature) | |
{ | |
var pk_object = JObject.Parse(GZIP.DecompressString(publickey)); | |
string hash = this.CalculateMD5Hash(message); | |
var signatureBig = BigInteger.Parse(signature, NumberStyles.HexNumber); | |
var dec = this.Decrypt(signatureBig, BigInteger.Parse(pk_object.GetValue("e").ToString()), BigInteger.Parse(pk_object.GetValue("n").ToString())); | |
return dec.ToString("X") == hash; | |
} | |
public string CalculateMD5Hash(string input) | |
{ | |
// step 1, calculate MD5 hash from input | |
MD5 md5 = System.Security.Cryptography.MD5.Create(); | |
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input); | |
byte[] hash = md5.ComputeHash(inputBytes); | |
// step 2, convert byte array to hex string | |
StringBuilder sb = new StringBuilder(); | |
for (int i = 0; i < hash.Length; i++) | |
{ | |
sb.Append(hash[i].ToString("X2")); | |
} | |
return sb.ToString(); | |
} | |
} | |
} | |
//main.cs | |
RSASIGNATURE rsa = new RSASIGNATURE(); | |
// p , q params | |
BigInteger p = "1090660992520643446103273789680343"; | |
BigInteger q = "1162435056374824133712043309728653"; | |
rsa.generateParams(p, q); | |
//encode private and public keys | |
string[] keyspair = rsa.encodeKeys(); | |
Console.WriteLine("Public key: "+ keyspair[0]); //<e,n> | |
Console.WriteLine("Private key: "+ keyspair[1]); //<d,n> | |
string message = "by safi"; | |
//generate signature | |
string signature = rsa.Sign(message,keyspair[1]); | |
Console.WriteLine("Signature: "+ signature); | |
//verify signature | |
bool verfied = rsa.Verify(message,keyspair[0],signature) | |
Assert.isTrue(verfied); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment