using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Web; namespace RSA { class Signature { public static string PrivateKey { get { //此处为私钥文件的地址 return @"XXXXXX"; } } static void Main(string[] args) { var strSignature = string.Empty;//签名字符串 var dict = new Dictionary { {"key1", "value1"}, {"key2", "value2"} }; strSignature = SortByAscii(dict); var strCypherText = RSASign(strSignature);//签名完成后的字符串 Console.WriteLine(strCypherText); Console.ReadKey(); } public static string SortByAscii(Dictionary paramsMap) { var vDic = (from objDic in paramsMap orderby objDic.Key ascending select objDic); var str = new StringBuilder(); foreach (KeyValuePair kv in vDic) { var pkey = System.Web.HttpUtility.UrlEncode(kv.Key); var pvalue = System.Web.HttpUtility.UrlEncode(kv.Value); str.Append(pkey + "=" + pvalue + "&"); } return str.ToString().TrimEnd('&') + "," + ConvertDateTimeInt(DateTime.Now); } /// /// DateTime时间格式转换为Unix时间戳格式 /// /// DateTime时间格式 /// Unix时间戳格式 public static int ConvertDateTimeInt(System.DateTime time) { var startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); return (int)(time - startTime).TotalSeconds; } public static string RSASign(string data) { RSACryptoServiceProvider rsaCsp = LoadCertificateFile(PrivateKey); byte[] dataBytes = null; dataBytes = Encoding.UTF8.GetBytes(data); byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA256"); return Convert.ToBase64String(signatureBytes); } private static RSACryptoServiceProvider LoadCertificateFile(string filename) { using (System.IO.FileStream fs = System.IO.File.OpenRead(filename)) { byte[] data = new byte[fs.Length]; byte[] res = null; fs.Read(data, 0, data.Length); if (data[0] != 0x30) { res = GetPem("RSA PRIVATE KEY", data); } try { RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res); return rsa; } catch { throw; } } } private static byte[] GetPem(string type, byte[] data) { string pem = Encoding.UTF8.GetString(data); string header = String.Format("-----BEGIN {0}-----\\n", type); string footer = String.Format("-----END {0}-----", type); int start = pem.IndexOf(header) + header.Length; int end = pem.IndexOf(footer, start); string base64 = pem.Substring(start, (end - start)); return Convert.FromBase64String(base64); } 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 ----- CspParameters CspParameters = new CspParameters(); CspParameters.Flags = CspProviderFlags.UseMachineKeyStore; int bitLen = 1024; RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(bitLen, CspParameters); 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 ex) { 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; } } }