非对称密钥RSA算法加解密在C#和Java之间交互的问题,这两天看了很多其他人写的文章,碰到了几个问题,最终解决问题。

参考地址:http://xw-z1985.iteye.com/blog/1837376

需求目的:完成c#请求端RSA加密(签名)问题,客户端采用C#开发,服务器端采用Java开发。服务器端给客户端提供私钥,进行数据加密(签名),客户端加密(签名)后提数据提交给服务器,服务器用公钥对数据解密,进行验证。

解决过程碰到的问题:

1.JAVA 需要的 RSA私钥 格式和 C# 需要的 RSA私钥 不一致。

JAVA 需要是 PKCS8格式私钥:

-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOwuOHH/OIRE+0if
mEPYGuhYRTyKdd6VLFIsNqy/SO5xZitHfA7xEymJKnpEUGgDJKr5zbFbytnWs5Jj
gen6TXkUh9LG/fhPGGHdUVB42pAHv5yzoyEaOnJxBAxd6UstoWTaEgbT6GUbzMr/
Az25zuxw7c+skAlnUETVE5GL3tD7AgMBAAECgYEAxdNZODMctb3J9OSo93rV3vPA
2prna87rVtDt4vg+MGsPtwSjZyiKcmoQCGWcK+MmHYgrwHkwihKKSv3KXZ9or3xQ
2wNZGuTHLymWEzqfEfVb0igvxbe85EGwsaN3qSK62CK8vok/Bi+fZVa3UNCn0WFs
lUS0qn+K3SECM9I1iwECQQD+2Pl2AJGQs2bRXSsnJk0FIwjpqdpGZFPlAUYaXkuT
MqpwefP/bwwiuWqq9QIt2vAAKgy5T16tpPBcGpT6cvxBAkEA7T+i1gVwrXcozTuT
9oCwkF2MGBaXkv3mN9H/Pfy/oIhTsgiDxX8t+0KapAEQogvCuAOq19JvGw5e91H2
g0suOwJAJOMnCIuAhl9RTJCdxGbo0wuFKL0rGPFAq28JxJtNeRrmTK16QcjDCuun
ouMf059TCdMMUG5Kl/u9xrcaRT4LgQJAZPiUYOnnzqvMHayhiGO0wXxOx2G2GMUe
Wdtx+fu7wqLCnB6rlj5OX4U1M1+QqKbAtHg7Gadhye4P1Mp5U9+HSQJBANLVzcCX
yAX2D12UPTPkhcNRaCRXFp3aJGMxI4iluUC+ukAdiapohqZ7vMQyWRq/tDyiwjir
qMcg/AJIuQWmPyc=
-----END PRIVATE KEY-----

C# 需要的是 PKCS1 格式私钥:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDsLjhx/ziERPtIn5hD2BroWEU8inXelSxSLDasv0jucWYrR3wO
8RMpiSp6RFBoAySq+c2xW8rZ1rOSY4Hp+k15FIfSxv34Txhh3VFQeNqQB7+cs6Mh
GjpycQQMXelLLaFk2hIG0+hlG8zK/wM9uc7scO3PrJAJZ1BE1RORi97Q+wIDAQAB
AoGBAMXTWTgzHLW9yfTkqPd61d7zwNqa52vO61bQ7eL4PjBrD7cEo2coinJqEAhl
nCvjJh2IK8B5MIoSikr9yl2faK98UNsDWRrkxy8plhM6nxH1W9IoL8W3vORBsLGj
d6kiutgivL6JPwYvn2VWt1DQp9FhbJVEtKp/it0hAjPSNYsBAkEA/tj5dgCRkLNm
0V0rJyZNBSMI6anaRmRT5QFGGl5LkzKqcHnz/28MIrlqqvUCLdrwACoMuU9eraTw
XBqU+nL8QQJBAO0/otYFcK13KM07k/aAsJBdjBgWl5L95jfR/z38v6CIU7IIg8V/
LftCmqQBEKILwrgDqtfSbxsOXvdR9oNLLjsCQCTjJwiLgIZfUUyQncRm6NMLhSi9
KxjxQKtvCcSbTXka5kytekHIwwrrp6LjH9OfUwnTDFBuSpf7vca3GkU+C4ECQGT4
lGDp586rzB2soYhjtMF8TsdhthjFHlnbcfn7u8Kiwpweq5Y+Tl+FNTNfkKimwLR4
OxmnYcnuD9TKeVPfh0kCQQDS1c3Al8gF9g9dlD0z5IXDUWgkVxad2iRjMSOIpblA
vrpAHYmqaIame7zEMlkav7Q8osI4q6jHIPwCSLkFpj8n
-----END RSA PRIVATE KEY-----

2.私钥格式之间的转换问题

转换工具:openssl工具:http://www.slproweb.com/products/Win32OpenSSL.html

转换参考地址: http://blog.csdn.net/hanzengyi/article/details/78029104

java 代码 , 注意这里的私钥:是Pem私钥文件中去除头(-----BEGIN PRIVATE KEY-----)和尾(-----END PRIVATE KEY-----)以及换行符后的字符串

 1    /**
2 * @data: 待加密的字符串
3 * @privateKey: 私钥
4 */
5 public static String sign(byte[] data, String privateKey) throws Exception {
6
7 byte[] keyBytes = new BASE64Decoder().decodeBuffer(privateKey);
8 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
9
10 KeyFactory keyFactory = KeyFactory.getInstance("RSA");
11
12 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
13
14 Signature signature = Signature.getInstance("SHA1withRSA");
15 signature.initSign(priKey);
16 signature.update(data);
17
18 return byte2hex(signature.sign());
19 }

c# 代码,注意这里的私钥:是Pem私钥文件中去除头(-----BEGIN RSA PRIVATE KEY-----)和尾(-----END RSA PRIVATE KEY-----)以及换行符后的字符串

  1       /// <summary>
2      /// 签名
3      /// </summary>
4      /// <param name="data">待加密的字符串</param>
5      /// <param name="privateKey">私钥</param>
6      /// <returns></returns>
7      public static string Sign(string data, string privateKey)
8 {
9 RSACryptoServiceProvider rsaCsp = LoadCertificate(privateKey);
10 byte[] dataBytes = Encoding.UTF8.GetBytes(data);
11 byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
12 return Hex_2To16(signatureBytes);
13 }
14
15 private static RSACryptoServiceProvider LoadCertificate(string privateKey)
16 {
17 byte[] res = res = Convert.FromBase64String(privateKey);
18 try
19 {
20 RSACryptoServiceProvider rsa = DecodeRSAPrivateKey(res);
21 return rsa;
22 }
23 catch (Exception ex)
24 {
25 }
26 return null;
27 }
28
29 private static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey)
30 {
31 byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
32
33 // --------- Set up stream to decode the asn.1 encoded RSA private key ------
34 MemoryStream mem = new MemoryStream(privkey);
35 BinaryReader binr = new BinaryReader(mem); //wrap Memory Stream with BinaryReader for easy reading
36 byte bt = 0;
37 ushort twobytes = 0;
38 int elems = 0;
39 try
40 {
41 twobytes = binr.ReadUInt16();
42 if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
43 binr.ReadByte(); //advance 1 byte
44 else if (twobytes == 0x8230)
45 binr.ReadInt16(); //advance 2 bytes
46 else
47 return null;
48
49 twobytes = binr.ReadUInt16();
50 if (twobytes != 0x0102) //version number
51 return null;
52 bt = binr.ReadByte();
53 if (bt != 0x00)
54 return null;
55
56
57 //------ all private key components are Integer sequences ----
58 elems = GetIntegerSize(binr);
59 MODULUS = binr.ReadBytes(elems);
60
61 elems = GetIntegerSize(binr);
62 E = binr.ReadBytes(elems);
63
64 elems = GetIntegerSize(binr);
65 D = binr.ReadBytes(elems);
66
67 elems = GetIntegerSize(binr);
68 P = binr.ReadBytes(elems);
69
70 elems = GetIntegerSize(binr);
71 Q = binr.ReadBytes(elems);
72
73 elems = GetIntegerSize(binr);
74 DP = binr.ReadBytes(elems);
75
76 elems = GetIntegerSize(binr);
77 DQ = binr.ReadBytes(elems);
78
79 elems = GetIntegerSize(binr);
80 IQ = binr.ReadBytes(elems);
81
82
83 // ------- create RSACryptoServiceProvider instance and initialize with public key -----
84 CspParameters CspParameters = new CspParameters();
85 CspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
86 RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(1024, CspParameters);
87 RSAParameters RSAparams = new RSAParameters();
88 RSAparams.Modulus = MODULUS;
89 RSAparams.Exponent = E;
90 RSAparams.D = D;
91 RSAparams.P = P;
92 RSAparams.Q = Q;
93 RSAparams.DP = DP;
94 RSAparams.DQ = DQ;
95 RSAparams.InverseQ = IQ;
96 RSA.ImportParameters(RSAparams);
97 return RSA;
98 }
99 catch (Exception ex)
100 {
101 return null;
102 }
103 finally
104 {
105 binr.Close();
106 }
107 }
108
109 private static int GetIntegerSize(BinaryReader binr)
110 {
111 byte bt = 0;
112 byte lowbyte = 0x00;
113 byte highbyte = 0x00;
114 int count = 0;
115 bt = binr.ReadByte();
116 if (bt != 0x02) //expect integer
117 return 0;
118 bt = binr.ReadByte();
119
120 if (bt == 0x81)
121 count = binr.ReadByte(); // data size in next byte
122 else
123 if (bt == 0x82)
124 {
125 highbyte = binr.ReadByte(); // data size in next 2 bytes
126 lowbyte = binr.ReadByte();
127 byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
128 count = BitConverter.ToInt32(modint, 0);
129 }
130 else
131 {
132 count = bt; // we already have the data size
133 }
134
135 while (binr.ReadByte() == 0x00)
136 { //remove high order zeros in data
137 count -= 1;
138 }
139 binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte
140 return count;
141 }
142
143
144 /// <summary>
145 /// 2进制转16进制
146 /// </summary>
147 public static String Hex_2To16(Byte[] bytes)
148 {
149 String hexString = String.Empty;
150 Int32 iLength = 65535;
151 if (bytes != null)
152 {
153 StringBuilder strB = new StringBuilder();
154
155 if (bytes.Length < iLength)
156 {
157 iLength = bytes.Length;
158 }
159
160 for (int i = 0; i < iLength; i++)
161 {
162 strB.Append(bytes[i].ToString("X2"));
163 }
164 hexString = strB.ToString();
165 }
166 return hexString;
167 }

JAVA RSA私钥 加密(签名) 对应 C# RSA私钥 加密(签名)的更多相关文章

  1. Java前端Rsa公钥加密,后端Rsa私钥解密(目前还不支持中文加密解密,其他都行)

    Base64工具类,可以让rsa编码的乱码变成一串字符序列 package com.utils; import java.io.ByteArrayInputStream; import java.io ...

  2. java RSA加密解密实现(含分段加密)

    该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar 下载地址:http://download.csdn.net/detail/centralperk/50255 ...

  3. 浅谈IM软件业务知识——非对称加密,RSA算法,数字签名,公钥,私钥

    概述 首先了解一下相关概念:RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的.RSA就是取自他们三个人的名字. 算法基于一个数论:将两个大素数相乘很ea ...

  4. RSA加密、解密、公钥私钥生成

    有时项目中需要用到一些加密和解密工具,这里之前整理了一个demo,记录一下,方便查询 package com.test; import java.security.KeyFactory; import ...

  5. rsa公钥和私钥到底哪个才是用来加密,哪个用来解密?

    本文转自:91博客:原文地址:http://www.9191boke.com/138589019.html 公钥和私钥在一些银行系统.第三方支付系统SDK中经常会遇到,刚接触公钥私钥的朋友们估计很难区 ...

  6. 基于私钥加密公钥解密的RSA算法C#实现

    RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作. RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一 ...

  7. JAVA中使用RSA通过秘钥文件对字符串进行加密解密

    技术交流群: 233513714 //字符串进行加密算法的名称 public static final String ALGORITHM = "RSA"; //字符串进行加密填充的 ...

  8. php/js/linux: js加密(rsa公钥加密) php解密(rsa私钥解密)

    php/js/linux: js加密(rsa公钥加密) php解密(rsa私钥解密) 一: js rsa 插件 https://github.com/UFO0001/WX_RSA 或者: https: ...

  9. Delphi RSA加解密【 (RSA公钥加密,私钥解密)、(RSA私钥加密,公钥解密)、MD5加密、SHA加密】

    作者QQ:(648437169) 点击下载➨delphi RSA加解密 [Delphi RSA加解密]支持 (RSA公钥加密,私钥解密).(RSA私钥加密,公钥解密).MD5加密.SHA1加密.SHA ...

随机推荐

  1. Spring(七):IOC&DI

    什么是IOC? IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源. 而应用了IOC之后, ...

  2. mongodb自动关闭:页面文件太小,无法完成操作

    在一台两G内存的win server 2008电脑上运行一个程序,一段时间后mongod自动停止,发现日志文件最后有这样的错误: 2014-11-30T00:32:32.914+0800 [conn3 ...

  3. wget获取整站

    wget -m -e robots=off https://www.baidu.com -m是克隆整个网站,-e robots=off是让wget忽视robots.txt 如果网站有中文路径,最好用以 ...

  4. (纪录片)数学的故事 The Story of Maths (2008)

    简介: 导演: Robin Dashwood编剧: Marcus du Sautoy主演: Marcus du Sautoy类型: 纪录片官方网站: www.bbc.co.uk/programmes/ ...

  5. HTML页面跳转的5种方式

    下面列了五个例子来详细说明,这几个例子的主要功能是:在5秒后,自动跳转到同目录下的hello.html(根据自己需要自行修改)文件. 1) html的实现 <head> <!-- 以 ...

  6. Asp.Net 之 禁用TextBox的记忆功能

    IE提供了一个自动完成功能可以记忆我们的输入内容(如登录帐号等),方便下一次快速地录入类似资料.这确实是一个非常友好的功能,在操作时只需用鼠标双击文本框或输入前几个字符,系统会自动列出以前的录入历史供 ...

  7. 第九周(1) Word邮件合并2

    第九周(1) Word邮件合并2 教学时间 2013-4-22 教学课时 2 教案序号 15 教学目标 1.进一步掌握邮件合并的技巧和方法.2.利用邮件合并制作准考证.3.掌握在同一页生成多个记录的方 ...

  8. Linux安装pear包

    一.安装pear包. 1.安装: $ sudo wget http://pear.php.net/go-pear.phar $ sudo php go-pear.har 2.查看pear下安装的包: ...

  9. 通过httpclient3实现文件下载以及获取文件下载名称

    package httpclient3test; import java.io.File; import java.io.FileNotFoundException; import java.io.F ...

  10. MapReduce实现大矩阵乘法

    来自:http://blog.csdn.net/xyilu/article/details/9066973 引言 何 为大矩阵?Excel.SPSS,甚至SAS处理不了或者处理起来非常困难,需要设计巧 ...