JAVA RSA私钥 加密(签名) 对应 C# RSA私钥 加密(签名)

摘要:
在非对称密钥RSA算法的加密和解密中,C#和Java之间的交互问题。在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私钥 加密(签名)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇UILabel的顶对齐解决方法MFC TeeChart 用法整理一下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

DataFrame数据合并

一、join 作用:默认情况下,他是把行索引相同的数据合并到一起注意:以左为准,没有的部分用NaN补全 例子 import pandas as pd import numpy as np df1 = pd.DataFrame(data=np.zeros((2, 5)), index=list('AB'), columns=list('VWXYZ')) #...

VirtualBox 在Win10上的蓝屏问题

今天也是第一次使用VirtualBox ,因为比VM更轻量,当然主要还是版权,结果装完虚拟机后,每次打开虚拟机就蓝屏,系统报错。 这是出现在WIN10上的问题啊。 解决办法: 找到Control Panel -> Programs and Features -> Turn Windows features on or off 看到Hyper-V...

showdoc升级问题,showdoc错误日志

showdoc自带错误日志。目录位于网站根目录的server/Application/Runtime/Logs/Api目录下,如果没有任何内容需要添加可写权限。 showdoc升级后,建议把MySQL改成Sqlite,这里我们没改。后期出现了一系列问题,观察这个位置的日志就能解决。 建议升级的用户看一下网站根目录下server/Application/Ho...

【BIEE】04_当维度表中的维不存在事实表中,需要展示所有维度并且数据类展示为0

有时候,我们往往会存在这样的需求 例如:事实表的数据如下 EMP_FACT表示事实表,DIM_LEVEL是维度表 预期效果:(根据员工信息,分析各等级员工工资与员工个数) 我们在BIEE报表中新建报表,然后展示报表,展示结果如下: 图1 那么这个效果跟我们的预期效果可是差别比较大的!我们如何来改变这种差别呢? 首先我们分析上面2个表,我们需要解决2个...

C# 与 SQLite的操作

1、通过Add References引用SQLite ADO .NET安装目录的bin目录下的System.Data.SQLite.DLL。 2、创建数据库文件:因为始终是个0字节文件,应该利用IO也可以(?!)。 System.Data.SQLite.SQLiteConnection.CreateFile(datasource);3、连接数据库 Syst...

C#中使用SQLite

(1) 从下面的网址下载了 SQLite 版本(sqlite-netFx40-setup-bundle-x64-2010-1.0.83.0):http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki安 .cs 文件中使用了 using:using System.Data.SQ...