JAVA RSA私钥 加密(签名) 对应 C# RSA私钥 加密(签名)
非对称密钥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私钥 加密(签名)的更多相关文章
- Java前端Rsa公钥加密,后端Rsa私钥解密(目前还不支持中文加密解密,其他都行)
Base64工具类,可以让rsa编码的乱码变成一串字符序列 package com.utils; import java.io.ByteArrayInputStream; import java.io ...
- java RSA加密解密实现(含分段加密)
该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar 下载地址:http://download.csdn.net/detail/centralperk/50255 ...
- 浅谈IM软件业务知识——非对称加密,RSA算法,数字签名,公钥,私钥
概述 首先了解一下相关概念:RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的.RSA就是取自他们三个人的名字. 算法基于一个数论:将两个大素数相乘很ea ...
- RSA加密、解密、公钥私钥生成
有时项目中需要用到一些加密和解密工具,这里之前整理了一个demo,记录一下,方便查询 package com.test; import java.security.KeyFactory; import ...
- rsa公钥和私钥到底哪个才是用来加密,哪个用来解密?
本文转自:91博客:原文地址:http://www.9191boke.com/138589019.html 公钥和私钥在一些银行系统.第三方支付系统SDK中经常会遇到,刚接触公钥私钥的朋友们估计很难区 ...
- 基于私钥加密公钥解密的RSA算法C#实现
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作. RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一 ...
- JAVA中使用RSA通过秘钥文件对字符串进行加密解密
技术交流群: 233513714 //字符串进行加密算法的名称 public static final String ALGORITHM = "RSA"; //字符串进行加密填充的 ...
- php/js/linux: js加密(rsa公钥加密) php解密(rsa私钥解密)
php/js/linux: js加密(rsa公钥加密) php解密(rsa私钥解密) 一: js rsa 插件 https://github.com/UFO0001/WX_RSA 或者: https: ...
- Delphi RSA加解密【 (RSA公钥加密,私钥解密)、(RSA私钥加密,公钥解密)、MD5加密、SHA加密】
作者QQ:(648437169) 点击下载➨delphi RSA加解密 [Delphi RSA加解密]支持 (RSA公钥加密,私钥解密).(RSA私钥加密,公钥解密).MD5加密.SHA1加密.SHA ...
随机推荐
- Pandas DataFrame学习笔记
对一个DF r1 r2 r3 c1 c2 c3 选行: df['r1'] df['r2':'r2'] #包含r2 df[df['c1']>5] #按条件选 选列: df['c1'] ...
- 浅谈压缩感知(七):常见测量矩阵的MATLAB实现
1.随机高斯测量矩阵 function [ Phi ] = GaussMtx( M,N ) %GaussMtx Summary of this function goes here % Generat ...
- 算法基础:删除字符串中出现次数最少的字符(Golang实现)
描写叙述: 实现删除字符串中出现次数最少的字符.若多个字符出现次数一样,则都删除.输出删除这些单词后的字符串. 字符串中其他字符保持原来的顺序. 输入: 字符串仅仅包括小写英文字母, 不考虑非法输入, ...
- Office办公 WPS如何设置页边距
打开页眉页脚,在选项里面可以设置顶部的一行文字距离边界的距离 此外在页面布局,页边距也可以查看和修改
- Java WebSockets
https://github.com/TooTallNate/Java-WebSocket Java WebSockets This repository contains a barebones W ...
- loadrunner脚本001
Action() { ; lr_start_transaction("login"); web_add_cookie("JSESSIONID=061460B7DFF2F7 ...
- MongoDB副本集配置系列六:定位MongoDB慢的原因
1:想知道哪些操作拖慢了MongoDB的速度,首先需要检查当前正在执行哪些操作. gechongrepl:PRIMARY> db.currentOp() "opid" : 7 ...
- Keepalived系列一:Keepalived.conf 详解
接上一篇博客: http://www.cnblogs.com/xiaoit/p/4499703.html 1:按照上篇博客安装后的配置文件在 /usr/local/etc/keepalived/kee ...
- ubuntu 下 cajview 替代方案
.caj 是知网提供的论文的标准格式,但是,知网只提供 win 版的工具.这里尝试了两个两个方案,均可行,做一下记录在此. 1. 使用 wine 版的 cajview pdf 可以正常用,但是 ca ...
- SpringMVC学习笔记六:使用 hibernate-validator注解式数据校验
对客户端传过来的参数,在使用前一般需要进行校验. SpringMVC框架内置了Validator验证接口,但是实现起来太麻烦.我们一般使用 hibernate-validator进行数据校验. 1:j ...