• 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         }
  • 相关阅读:
    HTTP协议基础
    MySQL必知必会总结(二)
    MySQL必知必会总结(一)
    微信小程序开发总结
    从零开始搭建物联网平台(8):邮箱通知服务
    使用CDN优化首页加载速度
    Django+Vue前后端分离项目的部署
    Docker命令
    Django中间件执行流程和CSRF验证
    golang 快速排序及二分查找
  • 原文地址:https://www.cnblogs.com/wuweimin/p/7839335.html
Copyright © 2020-2023  润新知