博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA RSA私钥 加密(签名) 对应 C# RSA私钥 加密(签名)
阅读量:5908 次
发布时间:2019-06-19

本文共 9101 字,大约阅读时间需要 30 分钟。

非对称密钥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+0ifmEPYGuhYRTyKdd6VLFIsNqy/SO5xZitHfA7xEymJKnpEUGgDJKr5zbFbytnWs5Jjgen6TXkUh9LG/fhPGGHdUVB42pAHv5yzoyEaOnJxBAxd6UstoWTaEgbT6GUbzMr/Az25zuxw7c+skAlnUETVE5GL3tD7AgMBAAECgYEAxdNZODMctb3J9OSo93rV3vPA2prna87rVtDt4vg+MGsPtwSjZyiKcmoQCGWcK+MmHYgrwHkwihKKSv3KXZ9or3xQ2wNZGuTHLymWEzqfEfVb0igvxbe85EGwsaN3qSK62CK8vok/Bi+fZVa3UNCn0WFslUS0qn+K3SECM9I1iwECQQD+2Pl2AJGQs2bRXSsnJk0FIwjpqdpGZFPlAUYaXkuTMqpwefP/bwwiuWqq9QIt2vAAKgy5T16tpPBcGpT6cvxBAkEA7T+i1gVwrXcozTuT9oCwkF2MGBaXkv3mN9H/Pfy/oIhTsgiDxX8t+0KapAEQogvCuAOq19JvGw5e91H2g0suOwJAJOMnCIuAhl9RTJCdxGbo0wuFKL0rGPFAq28JxJtNeRrmTK16QcjDCuunouMf059TCdMMUG5Kl/u9xrcaRT4LgQJAZPiUYOnnzqvMHayhiGO0wXxOx2G2GMUeWdtx+fu7wqLCnB6rlj5OX4U1M1+QqKbAtHg7Gadhye4P1Mp5U9+HSQJBANLVzcCXyAX2D12UPTPkhcNRaCRXFp3aJGMxI4iluUC+ukAdiapohqZ7vMQyWRq/tDyiwjirqMcg/AJIuQWmPyc=-----END PRIVATE KEY-----

 

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

 

-----BEGIN RSA PRIVATE KEY-----MIICXQIBAAKBgQDsLjhx/ziERPtIn5hD2BroWEU8inXelSxSLDasv0jucWYrR3wO8RMpiSp6RFBoAySq+c2xW8rZ1rOSY4Hp+k15FIfSxv34Txhh3VFQeNqQB7+cs6MhGjpycQQMXelLLaFk2hIG0+hlG8zK/wM9uc7scO3PrJAJZ1BE1RORi97Q+wIDAQABAoGBAMXTWTgzHLW9yfTkqPd61d7zwNqa52vO61bQ7eL4PjBrD7cEo2coinJqEAhlnCvjJh2IK8B5MIoSikr9yl2faK98UNsDWRrkxy8plhM6nxH1W9IoL8W3vORBsLGjd6kiutgivL6JPwYvn2VWt1DQp9FhbJVEtKp/it0hAjPSNYsBAkEA/tj5dgCRkLNm0V0rJyZNBSMI6anaRmRT5QFGGl5LkzKqcHnz/28MIrlqqvUCLdrwACoMuU9eraTwXBqU+nL8QQJBAO0/otYFcK13KM07k/aAsJBdjBgWl5L95jfR/z38v6CIU7IIg8V/LftCmqQBEKILwrgDqtfSbxsOXvdR9oNLLjsCQCTjJwiLgIZfUUyQncRm6NMLhSi9KxjxQKtvCcSbTXka5kytekHIwwrrp6LjH9OfUwnTDFBuSpf7vca3GkU+C4ECQGT4lGDp586rzB2soYhjtMF8TsdhthjFHlnbcfn7u8Kiwpweq5Y+Tl+FNTNfkKimwLR4OxmnYcnuD9TKeVPfh0kCQQDS1c3Al8gF9g9dlD0z5IXDUWgkVxad2iRjMSOIpblAvrpAHYmqaIame7zEMlkav7Q8osI4q6jHIPwCSLkFpj8n-----END RSA PRIVATE KEY-----

 

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

转换工具:openssl工具:

转换参考地址: 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       ///   2       /// 签名  3       ///   4       /// 待加密的字符串  5       /// 私钥  6       /// 
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 finally104 {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 integer117 return 0;118 bt = binr.ReadByte();119 120 if (bt == 0x81)121 count = binr.ReadByte(); // data size in next byte122 else123 if (bt == 0x82)124 {125 highbyte = binr.ReadByte(); // data size in next 2 bytes126 lowbyte = binr.ReadByte();127 byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };128 count = BitConverter.ToInt32(modint, 0);129 }130 else131 {132 count = bt; // we already have the data size133 }134 135 while (binr.ReadByte() == 0x00)136 { //remove high order zeros in data137 count -= 1;138 }139 binr.BaseStream.Seek(-1, SeekOrigin.Current); //last ReadByte wasn't a removed zero, so back up a byte140 return count;141 }142 143 144 /// 145 /// 2进制转16进制146 /// 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 }
你可能感兴趣的文章
Asp.Net Web Api 图片上传
查看>>
混沌的艺术--- YChaos通过数学公式生成混沌图像
查看>>
codechef Little Elephant and Permutations题解
查看>>
如何从github上面拷贝源码
查看>>
C++标准 bind函数用法与C#简单实现
查看>>
【POJ】2096 Collecting Bugs
查看>>
【Linux】linux经常使用基本命令
查看>>
[JAVA设计模式]第二部分:创建模式
查看>>
nyoj86-找球号(一) 【set 二分查找 hash】
查看>>
关于数组集合之间的转换
查看>>
Object-C 基础学习笔记(for,foreach,while,switch)
查看>>
[推荐]DDOS攻击与防范知识介绍
查看>>
Android SDK下载项的说明
查看>>
**PHP二维数组遍历时同时赋值
查看>>
Java读写Excel之POI超入门
查看>>
13.allegro 颜色设置[原创]
查看>>
vistual studio 2012 安装失败,提示Microsoft Vistual Studio 2012 Devenv找不到元素,等错误信息...
查看>>
linux 2.6 互斥锁的实现-源码分析
查看>>
SQL Server技术内幕笔记合集
查看>>
[数分提高]2014-2015-2第5教学周第2次课讲义 3.2 微分中值定理
查看>>