本人被要求实现.net的签名验签,还是个.net菜鸡,来分享下采坑过程

依然,签名验签使用的证书格式依然是pem,有关使用openssl将.p12和der转pem的命令请转到php实现签名验签

.net不像php只要将pem文件读出来就可以签名验签,需要解析pem文件的主体内容,获取参数装载特定类,具体看一下代码:


  1. //有些函数我也不知道是干嘛的,反正.net的实现要这样,采百家之长,签的了名,验的了签就对了
    //自己去单元测试下
    //pem文件是我使用的是绝对路径
    public class Signature
  2. {
  3. //签名,返回256位字节数组
  4. public static byte[] Sign(string content,string path,string code)
  5. {
  6. RSACryptoServiceProvider rsaCsp = RSAProviderPrivate(path);
  7. byte[] dataBytes = Encoding.UTF8.GetBytes(content);
  8. byte[] signatureBytes = rsaCsp.SignData(dataBytes, code);
  9. return signatureBytes;
  10. }
  11.  
  12. //验签
  13. public static Boolean Verify(string content, byte[] signContent, string path, string code)
  14. {
  15. byte[] dataBytes = Encoding.UTF8.GetBytes(content);
  16. byte[] publicPemBytes = LoadCertificateFile(path, "PUBLIC KEY");
  17.  
  18. RSACryptoServiceProvider rsaPub = CreateRsaProviderFromPublicKey(publicPemBytes);
  19. Boolean flag= rsaPub.VerifyData(dataBytes,code, signContent);
  20. return flag;
  21. }
  22.  
  23. //加载公私钥证书文件
  24. private static byte[] LoadCertificateFile(String filePath,string type)
  25. {
  26. using (System.IO.FileStream fs = System.IO.File.OpenRead(filePath))
  27. {
  28. byte[] data = new byte[fs.Length];
  29. byte[] res = null;
  30. fs.Read(data, 0, data.Length);
  31. if (data[0] != 0x30)
  32. {
  33. res = GetPem(type, data);
  34. }
  35. return res;
  36. }
  37. }
  38.  
  39. private static RSACryptoServiceProvider RSAProviderPrivate(String filePath)
  40. {
  41. byte[] res = LoadCertificateFile(filePath, "RSA PRIVATE KEY");
  42.  
  43. try
  44. {
  45. RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
  46. return rsa;
  47. }
  48. catch (Exception e)
  49. {
  50. Console.WriteLine(e);
  51. }
  52. return null;
  53.  
  54. }
  55.  
  56. //获取pem文件的主体内容,并转换成字节数组
  57. private static byte[] GetPem(String type, byte[] data)
  58. {
  59. string pem = Encoding.UTF8.GetString(data);
  60. string header = String.Format("-----BEGIN {0}-----\\n", type);
  61. string footer = String.Format("-----END {0}-----", type);
  62. int start = pem.IndexOf(header) + header.Length;
  63. int end = pem.IndexOf(footer, start);
  64. string base64 = pem.Substring(start, (end - start));
  65. return Convert.FromBase64String(base64);
  66. }
  67.  
  68. private static bool CompareBytearrays(byte[] a, byte[] b)
  69. {
  70. if (a.Length != b.Length)
  71. return false;
  72. int i = 0;
  73. foreach (byte c in a)
  74. {
  75. if (c != b[i])
  76. return false;
  77. i++;
  78. }
  79. return true;
  80. }
  81.  
  82. private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
  83. {
  84. byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
  85.  
  86. // --------- Set up stream to decode the asn.1 encoded RSA private key ------
  87. MemoryStream mem = new MemoryStream(privkey);
  88. BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
  89. byte bt = 0;
  90. ushort twobytes = 0;
  91. int elems = 0;
  92. try
  93. {
  94. twobytes = binr.ReadUInt16();
  95. if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
  96. binr.ReadByte(); //advance 1 byte
  97. else if (twobytes == 0x8230)
  98. binr.ReadInt16(); //advance 2 bytes
  99. else
  100. return null;
  101.  
  102. twobytes = binr.ReadUInt16();
  103. if (twobytes != 0x0102) //version number
  104. return null;
  105. bt = binr.ReadByte();
  106. if (bt != 0x00)
  107. return null;
  108.  
  109. //------ all private key components are Integer sequences ----
  110. elems = GetIntegerSize(binr);
  111. MODULUS = binr.ReadBytes(elems);
  112.  
  113. elems = GetIntegerSize(binr);
  114. E = binr.ReadBytes(elems);
  115.  
  116. elems = GetIntegerSize(binr);
  117. D = binr.ReadBytes(elems);
  118.  
  119. elems = GetIntegerSize(binr);
  120. P = binr.ReadBytes(elems);
  121.  
  122. elems = GetIntegerSize(binr);
  123. Q = binr.ReadBytes(elems);
  124.  
  125. elems = GetIntegerSize(binr);
  126. DP = binr.ReadBytes(elems);
  127.  
  128. elems = GetIntegerSize(binr);
  129. DQ = binr.ReadBytes(elems);
  130.  
  131. elems = GetIntegerSize(binr);
  132. IQ = binr.ReadBytes(elems);
  133.  
  134. // ------- create RSACryptoServiceProvider instance and initialize with public key -----
  135. CspParameters CspParameters = new CspParameters();
  136. CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
  137. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
  138. RSAParameters RSAparams = new RSAParameters();
  139. RSAparams.Modulus = MODULUS;
  140. RSAparams.Exponent = E;
  141. RSAparams.D = D;
  142. RSAparams.P = P;
  143. RSAparams.Q = Q;
  144. RSAparams.DP = DP;
  145. RSAparams.DQ = DQ;
  146. RSAparams.InverseQ = IQ;
  147. RSA.ImportParameters(RSAparams);
  148. return RSA;
  149. }
  150. catch (Exception e)
  151. {
  152. Console.WriteLine(e);
  153. return null;
  154. }
  155. finally
  156. {
  157. binr.Close();
  158. }
  159. }
  160.  
  161. private static int GetIntegerSize(BinaryReader binr)
  162. {
  163. byte bt = 0;
  164. byte lowbyte = 0x00;
  165. byte highbyte = 0x00;
  166. int count = 0;
  167. bt = binr.ReadByte();
  168. if (bt != 0x02) //expect integer
  169. return 0;
  170. bt = binr.ReadByte();
  171.  
  172. if (bt == 0x81)
  173. count = binr.ReadByte(); // data size in next byte
  174. else
  175. if (bt == 0x82)
  176. {
  177. highbyte = binr.ReadByte(); // data size in next 2 bytes
  178. lowbyte = binr.ReadByte();
  179. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  180. count = BitConverter.ToInt32(modint, 0);
  181. }
  182. else
  183. {
  184. count = bt; // we already have the data size
  185. }
  186.  
  187. while (binr.ReadByte() == 0x00)
  188. { //remove high order zeros in data
  189. count -= 1;
  190. }
  191. binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
  192. return count;
  193. }
  194.  
  195. private static RSAParameters ConvertFromPublicKey(byte[] publicPemBytes)
  196. {
  197.  
  198. byte[] keyData = publicPemBytes;
  199. if (keyData.Length < 162)
  200. {
  201. throw new ArgumentException("pem file content is incorrect.");
  202. }
  203. byte[] pemModulus = new byte[128];
  204. byte[] pemPublicExponent = new byte[3];
  205. Array.Copy(keyData, 29, pemModulus, 0, 128);
  206. Array.Copy(keyData, 159, pemPublicExponent, 0, 3);
  207. RSAParameters para = new RSAParameters();
  208. para.Modulus = pemModulus;
  209. para.Exponent = pemPublicExponent;
  210. return para;
  211. }
  212.  
  213. public static RSACryptoServiceProvider CreateRsaProviderFromPublicKey(byte[] publicKeyBytes)
  214. {
  215. byte[] SeqOID = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
  216. byte[] x509key;
  217. byte[] seq = new byte[15];
  218. int x509size;
  219.  
  220. x509key = publicKeyBytes;
  221. x509size = x509key.Length;
  222.  
  223. using (MemoryStream mem = new MemoryStream(x509key))
  224. {
  225. using (BinaryReader binr = new BinaryReader(mem))
  226. {
  227. byte bt = 0;
  228. ushort twobytes = 0;
  229.  
  230. twobytes = binr.ReadUInt16();
  231. if (twobytes == 0x8130)
  232. binr.ReadByte();
  233. else if (twobytes == 0x8230)
  234. binr.ReadInt16();
  235. else
  236. return null;
  237.  
  238. seq = binr.ReadBytes(15);
  239. if (!CompareBytearrays(seq, SeqOID))
  240. return null;
  241.  
  242. twobytes = binr.ReadUInt16();
  243. if (twobytes == 0x8103)
  244. binr.ReadByte();
  245. else if (twobytes == 0x8203)
  246. binr.ReadInt16();
  247. else
  248. return null;
  249.  
  250. bt = binr.ReadByte();
  251. if (bt != 0x00)
  252. return null;
  253.  
  254. twobytes = binr.ReadUInt16();
  255. if (twobytes == 0x8130)
  256. binr.ReadByte();
  257. else if (twobytes == 0x8230)
  258. binr.ReadInt16();
  259. else
  260. return null;
  261.  
  262. twobytes = binr.ReadUInt16();
  263. byte lowbyte = 0x00;
  264. byte highbyte = 0x00;
  265.  
  266. if (twobytes == 0x8102)
  267. lowbyte = binr.ReadByte();
  268. else if (twobytes == 0x8202)
  269. {
  270. highbyte = binr.ReadByte();
  271. lowbyte = binr.ReadByte();
  272. }
  273. else
  274. return null;
  275. byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
  276. int modsize = BitConverter.ToInt32(modint, 0);
  277.  
  278. int firstbyte = binr.PeekChar();
  279. if (firstbyte == 0x00)
  280. {
  281. binr.ReadByte();
  282. modsize -= 1;
  283. }
  284.  
  285. byte[] modulus = binr.ReadBytes(modsize);
  286.  
  287. if (binr.ReadByte() != 0x02)
  288. return null;
  289. int expbytes = (int)binr.ReadByte();
  290. byte[] exponent = binr.ReadBytes(expbytes);
  291.  
  292. RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  293. RSAParameters RSAKeyInfo = new RSAParameters();
  294. RSAKeyInfo.Modulus = modulus;
  295. RSAKeyInfo.Exponent = exponent;
  296. RSA.ImportParameters(RSAKeyInfo);
  297.  
  298. return RSA;
  299. }
  300.  
  301. }
  302. }
  303.  
  304. }

.net 实现签名验签的更多相关文章

  1. RSA签名验签

    import android.util.Base64; import java.security.KeyFactory; import java.security.PrivateKey; import ...

  2. 利用SHA-1算法和RSA秘钥进行签名验签(带注释)

    背景介绍 1.SHA 安全散列算法SHA (Secure Hash Algorithm)是美国国家标准和技术局发布的国家标准FIPS PUB 180-1,一般称为SHA-1.其对长度不超过264二进制 ...

  3. RSA密钥生成、加密解密、签名验签

    RSA 非对称加密公钥加密,私钥解密 私钥签名,公钥验签 下面是生成随机密钥对: //随机生成密钥对 KeyPairGenerator keyPairGen = null; try { keyPair ...

  4. C# RSACryptoServiceProvider加密解密签名验签和DESCryptoServic

    C#在using System.Security.Cryptography下有 DESCryptoServiceProvider RSACryptoServiceProvider DESCryptoS ...

  5. RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密

    原文:RSACryptoServiceProvider加密解密签名验签和DESCryptoServiceProvider加解密 C#在using System.Security.Cryptograph ...

  6. 数据安全管理:RSA加密算法,签名验签流程详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.RSA算法简介 1.加密解密 RSA加密是一种非对称加密,在公开密钥加密和电子商业中RSA被广泛使用.可以在不直接传递密钥的情况下,完成加 ...

  7. js rsa sign使用笔记(加密,解密,签名,验签)

    你将会收获: js如何加密, 解密 js如何签名, 验签 js和Java交互如何相互解密, 验签(重点) 通过谷歌, 发现jsrsasign库使用者较多. 查看api发现这个库功能很健全. 本文使用方 ...

  8. [Python3] RSA的加解密和签名/验签实现 -- 使用pycrytodome

    Crypto 包介绍: pycrypto,pycrytodome 和 crypto 是一个东西,crypto 在 python 上面的名字是 pycrypto 它是一个第三方库,但是已经停止更新,所以 ...

  9. php 实现签名验签

    本人php菜鸟,主要使用php实现简单的签名验签功能 以下php代码使用的密钥格式为pem格式,其他证书格式可以使用openssl进行转换(未安装请实现安装): 以下是.p12文件导出pem格式公私钥 ...

随机推荐

  1. Python下的图像处理库,你选哪个?

    奥里给~ 转载:https://blog.csdn.net/chen801090/article/details/105795068/ 在进行数字图像处理时,我们经常需要对图像进行读取.保存.缩放.裁 ...

  2. [学习笔记] Tarjan算法求桥和割点

    在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥.割点,也是和上篇有博客有类似之处的. 关于桥和割点: 桥:在一个有向图中,如果删去一条边,而 ...

  3. 超详细的TCP、Sokcket和SuperSocket与TCP入门指导

    前言 本文主要介绍TCP.Sokcket和SuperSocket的基础使用. 创建实例模式的SuperSocket服务 首先创建控制台项目,然后Nuget添加引用SuperSocket.Engine. ...

  4. 扩展、接管MVC都不会,还会用Spring Boot?

    持续原创输出,点击上方蓝字关注我 目录 前言 Spring Boot 版本 如何扩展MVC? 如何自定义一个拦截器? 什么都不配置为什么依然能运行MVC相关的功能? 如何全面接管MVC?[不推荐] 为 ...

  5. 你想了解的《javaScript语言精粹》(三)

    # javaScript语言精粹  # 第三章 对象 - javaScript 数据类型     1. 基础数据类型         Number String Boolean Undefined N ...

  6. 多测师讲解 ———python2和Python3区别

    python3.x和python2.x的区别:1.Python3.X源码文件默认使用utf-8编码,而python2.x的编译最前端需要加上#coding=utf-82.python3.x里打印pri ...

  7. JVM 第六篇:极致优化 IDEA 启动速度

    本文内容过于硬核,建议有 Java 相关经验人士阅读. 1. 引言 相信做 Java 开发的同学,对 IDEA 这个工具应该都不陌生,即使不使用 IDEA 做开发,那么对 Eclipse 这个工具应该 ...

  8. MeteoInfoLab脚本示例:FY-3C全球火点HDF数据

    FY-3C全球火点HDF数据包含一个FIRES二维变量,第一维是火点数,第二维是一些属性,其中第3.4列分别是火点的纬度和经度.下面的脚本示例读出所有火点经纬度并绘图.脚本程序: #Add data ...

  9. 【UER #1】DZY Loves Graph

    UOJ小清新题表 题目内容 UOJ链接 DZY开始有\(n\)个点,现在他对这\(n\)个点进行了\(m\)次操作,对于第\(i\)个操作(从\(1\)开始编号)有可能的三种情况: Add a b: ...

  10. Spring Aop 详解一

    Aop 是一个编程思想,最初是一个理论,最后落地成了很多的技术实现. 我们写一个系统,都希望尽量少写点儿重复的东西.而很多时候呢,又不得不写一些重复的东西.比如访问某些方法的权限,执行某些方法性能的日 ...