Skip to content

Instantly share code, notes, and snippets.

@GaiaAnn
Last active February 7, 2025 15:28
Show Gist options
  • Save GaiaAnn/29071961482462ff5334a121bd103166 to your computer and use it in GitHub Desktop.
Save GaiaAnn/29071961482462ff5334a121bd103166 to your computer and use it in GitHub Desktop.
RSA Encrypt/Decrypt & Sing/VerifySign C# sample
private static string Encrypt(string publicKey, string content)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
//Get publicKey information
RSAParameters parameters = ConvertFromPublicKey(publicKey);
rsa.ImportParameters(parameters);
//Convert to UTF8 bytes
var content_utf = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false);
//Convert to Base64String
var encryptString = Convert.ToBase64String(content_utf);
return encryptString;
}
private static string Decrypt(string privateKey,string encryptContent)
{
//Get privateKey information
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(Convert.FromBase64String(privateKey));
//Convert Base64String Into byte then do Decrypt
var desContent = rsa.Decrypt(Convert.FromBase64String(encryptContent), false);
//return UTF string result
return Encoding.UTF8.GetString(desContent);
}
public static string Sign(string content, string pvKey, string input_charset)
{
byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content);
byte[] privatekey;
privatekey = Convert.FromBase64String(pvKey);
RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(privatekey);
SHA1 sh = new SHA1CryptoServiceProvider();
byte[] signData = rsa.SignData(Data, sh);
return Convert.ToBase64String(signData);
}
public static bool VerifySign(string content, string signedString, string publicKey, string input_charset)
{
signedString = signedString.Replace("*", "+");
signedString = signedString.Replace("-", "/");
return JiJianverify(content, signedString, publicKey, input_charset);
}
/// <summary>
/// verify sign
/// </summary>
/// <param name="content"></param>
/// <param name="signedString"></param>
/// <param name="publicKey"></param>
/// <param name="input_charset"></param>
public static bool JiJianverify(string content, string signedString, string publicKey, string input_charset)
{
bool result = false;
byte[] Data = Encoding.GetEncoding(input_charset).GetBytes(content);
byte[] data = Convert.FromBase64String(signedString);
RSAParameters paraPub = ConvertFromPublicKey(publicKey);
RSACryptoServiceProvider rsaPub = new RSACryptoServiceProvider();
rsaPub.ImportParameters(paraPub);
SHA1 sh = new SHA1CryptoServiceProvider();
result = rsaPub.VerifyData(Data, sh, data);
return result;
}
private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
{
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
MemoryStream mem = new MemoryStream(privkey);
BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return null;
bt = binr.ReadByte();
if (bt != 0x00)
return null;
//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters RSAparams = new RSAParameters();
RSAparams.Modulus = MODULUS;
RSAparams.Exponent = E;
RSAparams.D = D;
RSAparams.P = P;
RSAparams.Q = Q;
RSAparams.DP = DP;
RSAparams.DQ = DQ;
RSAparams.InverseQ = IQ;
RSA.ImportParameters(RSAparams);
return RSA;
}
catch (Exception)
{
return null;
}
finally { binr.Close(); }
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82)
{
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
while (binr.ReadByte() == 0x00)
{ //remove high order zeros in data
count -= 1;
}
binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
return count;
}
private static RSAParameters ConvertFromPublicKey(string publicKey)
{
byte[] keyData = Convert.FromBase64String(publicKey);
if (keyData.Length < 162)
{
throw new ArgumentException("[PublicKey] .pem file content is incorrect.");
}
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(keyData);
RSAParameters para = new RSAParameters();
para.Modulus = publicKeyParam.Modulus.ToByteArrayUnsigned();
para.Exponent = publicKeyParam.Exponent.ToByteArrayUnsigned();
return para;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment