前提:
需要調用JavaAPI進行簽名/驗籤、加密/解密,需要使用BouncyCastle 類庫進行Java與C#之間的數據互通。
加密理解點:
1:java 私鑰採用的是PKCS8 ;C# 私鑰採用的是PKCS1 格式
2:RSA加密 公鑰加密,私鑰解密或者私鑰加密和公鑰解密【這點和簽名sign不同,sign需要私鑰簽名】
3:如果 java RSA加密 最後生成16進制 C# 也需要統一。這點一般需要確認最後生成的爲base64還是16進制數據。
額外補充:
1:私鑰,公鑰注意去除空格,換行等(.Replace("\r", "").Replace("\n", "").Replace("\\s", ""))
2:加密 最後生成的一般爲 byte數組 ,但是由於java中byte的範圍在 [-128,127] 但是 C#中byte的範圍在 [0,255]
並且使用byte不好進行對比傳輸,所以我們在進行簽名或者加密時一般轉化爲字符串或者16進制。
BouncyCastle類庫下載:
https://download.csdn.net/download/u011791378/11236710
******************以下時加密解密(C#與Java互通)BouncyCastle *************************
/// <summary>
/// 私鑰加密2
/// </summary>
/// <param name="content">加密內容</param>
/// <param name="PrivateKey">PKCS8私鑰</param>
/// <returns></returns>
public string EncryptByPrivateKey2(string content, string PrivateKey)
{
RsaKeyParameters PrivateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(PrivateKey));
var original = new BigInteger(Encoding.UTF8.GetBytes(content));
//加密
var encrypted = original.ModPow(PrivateKeyParam.Exponent, PrivateKeyParam.Modulus);
//16進制
return PayUtils.byteArray2HexString(encrypted.ToByteArray());
//base64
//return Convert.ToBase64String(encrypted.ToByteArray());
}
/// <summary>
/// 公鑰解密2
/// </summary>
/// <param name="content">解密內容</param>
/// <param name="PublicKey">PKCS8公鑰</param>
/// <returns></returns>
public string DecryptByPublicKey2(string content, string PublicKey)
{
//base64
//byte[] byteData = Convert.FromBase64String(content);
//16進制
var data = PayUtils.hexString2ByteArray(content);
RsaKeyParameters PublicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(PublicKey));
var encrypted = new BigInteger(data);
//解密
var decrypted = encrypted.ModPow(PublicKeyParam.Exponent, PublicKeyParam.Modulus);
return Encoding.UTF8.GetString(decrypted.ToByteArray());
}
/// <summary>
/// RSA公鑰加密
/// </summary>
/// <param name="content">加密內容</param>
/// <param name="publickey">公鑰</param>
/// <returns></returns>
public string EncryptByPublicKey(string content, string publicKey)
{
RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));
var original = new BigInteger(Encoding.UTF8.GetBytes(content));
//加密
var encrypted = original.ModPow(publicKeyParam.Exponent, publicKeyParam.Modulus);
//16進制
return PayUtils.byteArray2HexString(encrypted.ToByteArray());
//base64
//return Convert.ToBase64String(encrypted.ToByteArray());
}
/// <summary>
/// RSA私鑰解密
/// </summary>
/// <param name="content">解密內容</param>
/// <param name="privateKey">私鑰</param>
/// <returns></returns>
public string DecryptByPrivateKey(string content, string privateKey)
{
//base64
//byte[] byteData = Convert.FromBase64String(content);
//16進制
var data = PayUtils.hexString2ByteArray(content);
RsaKeyParameters privateKeyParam = (RsaKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));
var encrypted = new BigInteger(data);
//解密
var decrypted = encrypted.ModPow(privateKeyParam.Exponent, privateKeyParam.Modulus);
return Encoding.UTF8.GetString(decrypted.ToByteArray());
}
*****************Bytes數組與16進制的轉換*************************
private static readonly string hexChars = "0123456789ABCDEF";
/// <summary>
/// Bytes數組轉爲16進制
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string byteArray2HexString(byte[] data)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
byte lo = (byte)(0xF & data[i]);
byte hi = (byte)((int)((uint)(0xF0 & data[i]) >> 4));
sb.Append(hexChars.Substring(hi, 1)).Append(hexChars.Substring(lo, 1));
}
return sb.ToString();
}
/// <summary>
/// 16進制轉爲Bytes數組
/// </summary>
/// <param name="hexStr"></param>
/// <returns></returns>
public static byte[] hexString2ByteArray(String hexStr)
{
if (hexStr.Length % 2 != 0)
{
return null;
}
byte[] data = new byte[hexStr.Length / 2];
for (int i = 0; i < hexStr.Length / 2; i++)
{
char hc = hexStr.Substring(2 * i, 1).ToCharArray()[0];//.charAt(2 * i);
char lc = hexStr.Substring(2 * i + 1, 1).ToCharArray()[0];//.charAt(2 * i + 1);
byte hb = hexChar2Byte(hc);
byte lb = hexChar2Byte(lc);
if ((hb < 0) || (lb < 0))
{
return null;
}
int n = hb << 4;
data[i] = ((byte)(n + lb));
}
return data;
}
private static byte hexChar2Byte(char c)
{
if ((c >= '0') && (c <= '9'))
{
return (byte)(c - '0');
}
if ((c >= 'a') && (c <= 'f'))
{
return (byte)(c - 'a' + 10);
}
if ((c >= 'A') && (c <= 'F'))
{
return (byte)(c - 'A' + 10);
}
return 0;
}