[英]RSACryptoServiceProvider encrypt and decrypt using own public and private key
[英].NET RSACryptoServiceProvider encrypt with 4096 private key, how to decrypt it on Android
我正在使用帶有私鑰的RSACryptoServiceProvider加密.NET 中的消息。 (PKCS#1 v1.5)
當我嘗試使用以下使用公鑰的代碼在 .NET 中解密時,一切正常:
private static string Decrypt(string key, string content)
{
byte[] rgb = Convert.FromBase64String(content);
var cryptoServiceProvider = new RSACryptoServiceProvider(new CspParameters()
{
ProviderType = 1
});
cryptoServiceProvider.ImportCspBlob(Convert.FromBase64String(key));
return Convert.ToBase64String(cryptoServiceProvider.Decrypt(rgb, false));
}
另一方面,當我嘗試在 Android 中找到一種算法來制作相同的解密方法時,我無法使用公鑰對其進行正確解密。 我從 .NET 中的公鑰導出了模數和指數,以便在 Android 上正確加載它。
Android中的方法在這里:
public String Decrypt(String input) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
String modulusString = "mmGn1IXB+/NEm1ecLiUzgz7g2L6L5EE5DUcptppTNwZSqxeYKn0AuAccupL0iyX3LMPw6Dl9pjPXDjk93TQwYwyGgZaXOSRDQd/W2Y93g8erpGBRm/Olt7QN2GYhxP8Vn+cWUbNuikdD4yMfYX9NeD9UNt5WJGFf+jRkLk0zRK0A7ZIS+q0NvGJ/CgaRuoe3x4Mh1qYP9ZWNRw8rsDbZ6N2zyUa3Hk/WJkptRa6jrzc937r3QYF3eDTurVJZHwC7c3TJ474/8up3YNREnpK1p7hqwQ78fn35Tw4ZyTNxCevVJfYtc7pKHHiwfk36OxtOIesfKlMnHMs4vMWJm79ctixqAe3i9aFbbRj710dKAfZZ0FnwSnTpsoKO5g7N8mKY8nVpZej7tcLdTL44JqWEqnQkocRqgO/p3R8V/6To/OjQGf0r6ut9y/LnlM5qalnKJ1gFg1D7gCzZJ150TX4AO5kGSAFRyjkwGxnR0WLKf+BDZ8T/syOrFOrzg6b05OxiECwCvLWk0AaQiJkdu2uHbsFUj3J2BcwDYm/kZiD0Ri886xHqZMNExZshlIqiecqCskQhaMVC1+aCm+IFf16Qg/+eMYCd+3jm/deezT4rcMBOV/M+muownGYQ9WOdjEK53h9oVheahD3LqCW8MizABFimvXR3wAgkIUvhocVhSN0=";
String exponentString = "AQAB";
byte[] modulusBytes = Base64.decode(modulusString.getBytes("UTF-8"), Base64.DEFAULT);
byte[] dBytes = Base64.decode(exponentString.getBytes("UTF-8"), Base64.DEFAULT);
BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger d = new BigInteger(1, dBytes);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, d);
PublicKey key = keyFactory.generatePublic(keySpec);
//at one point I read somewhere that .net reverses the byte array so that it needs to be reversed for java, but who knows any more
/*byte[] inputArrayReversed = Base64.decode(input.getBytes("UTF-8"), Base64.DEFAULT);
for (int i = 0; i < inputArrayReversed.length / 2; i++) {
byte temp = inputArrayReversed[i];
inputArrayReversed[i] = inputArrayReversed[inputArrayReversed.length - 1];
inputArrayReversed[inputArrayReversed.length - 1] = temp;
}*/
byte[] decryptedText = null;
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
decryptedText = cipher.doFinal(Base64.decode(input.getBytes("UTF-8"), Base64.DEFAULT));
return Base64.encodeToString(decryptedText, Base64.NO_WRAP);
//return new String(decryptedText, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
實際上,我還嘗試了 Cypher 類中指定的不同算法,還嘗試了許多其他組合,嘗試使用 SpongyCastle 而不是內置的 Android RSA 提供程序,但沒有任何效果。 如果有人有任何線索為我指明正確的方向,我將不勝感激。
第一個提示是,來自 .NET 的解密字符串大約有 25 個字符長,當我讓 Android 毫無例外地返回解密字符串時,它通常要長得多,大約 500 個字節。
第二個提示已刪除
第三個提示我也試過 spongycastle,但沒有多大幫助
無論如何,在此先感謝您的幫助!!!
更新 1
第二個提示被刪除,因為是錯誤的,無視它。 現在我有一個問題,以下是否可以證明公鑰已正確加載,只是為了排除該問題。
上層 Android 代碼中的 BigInteger 模數和指數以及 .NET 中的以下 BigInteger 顯示相等的整數值。
var parameters = csp.ExportParameters(false);
var modulusInteger = new BigInteger(parameters.Modulus.Reverse().Concat(new byte[] { 0 }).ToArray());
var exponentInteger = new BigInteger(parameters.Exponent.Reverse().Concat(new byte[] { 0 }).ToArray());
更新 2
嘿,錯誤是基礎之一,我們有一個架構,我們用公鑰加密,用私鑰解密。 問題在於架構本身,因為在我們最初設置它時,我們將私鑰發送到我們所有的客戶端應用程序,這是一個很大的安全漏洞。
我的錯誤是我假設在客戶端上我們有公鑰,實際上我一直在嘗試加載公鑰然后解密。
如果我深入了解 PKI 並與我的同事更好地溝通,我可能會注意到以下幾點:
我已經知道或學到的東西很少,想與他人分享:
.NET 服務器代碼
public string Sign(string privateKey, string data)
{
_rsaProvider.ImportCspBlob(Convert.FromBase64String(privateKey));
//// Write the message to a byte array using UTF8 as the encoding.
var encoder = new UTF8Encoding();
byte[] byteData = encoder.GetBytes(data);
//// Sign the data, using SHA512 as the hashing algorithm
byte[] encryptedBytes = _rsaProvider.SignData(byteData, new SHA1CryptoServiceProvider());
return Convert.ToBase64String(encryptedBytes);
}
.NET 客戶端代碼 (Win Mobile)
private bool Verify(string key, string signature, string data)
{
CspParameters cspParams = new CspParameters { ProviderType = 1 };
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams);
rsaProvider.ImportCspBlob(Convert.FromBase64String(key));
byte[] signatureBytes = Convert.FromBase64String(signature);
var encoder = new UTF8Encoding();
byte[] dataBytes = encoder.GetBytes(data);
return rsaProvider.VerifyData(dataBytes, new SHA1CryptoServiceProvider(), signatureBytes);
}
安卓客戶端代碼:
public boolean Verify(RSAPublicKey key, String signature, String data)
{
try
{
Signature sign = Signature.getInstance("SHA1withRSA");
sign.initVerify(key);
sign.update(data.getBytes("UTF-8"));
return sign.verify(Base64.decode(signature.getBytes("UTF-8"), Base64.NO_WRAP));
}
catch (Exception e)
{
e.printStackTrace();
}
return false;
}
.NET 中的公鑰以 xml 格式導出,代碼如下:
public string ExportPublicToXML(string publicKey)
{
RSACryptoServiceProvider csp = new RSACryptoServiceProvider(new CspParameters()
{
ProviderType = 1
});
csp.ImportCspBlob(Convert.FromBase64String(publicKey));
return csp.ToXmlString(false);
}
然后在Android中使用模數和指數來加載公鑰:
private RSAPublicKey GetPublicKey(String keyXmlString) throws InvalidKeySpecException, UnsupportedEncodingException, NoSuchAlgorithmException
{
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
String modulusString = keyXmlString.substring(keyXmlString.indexOf("<Modulus>"), keyXmlString.indexOf("</Modulus>")).replace("<Modulus>", "");
String exponentString = keyXmlString.substring(keyXmlString.indexOf("<Exponent>"), keyXmlString.indexOf("</Exponent>")).replace("<Exponent>", "");
byte[] modulusBytes = Base64.decode(modulusString.getBytes("UTF-8"), Base64.DEFAULT);
byte[] dBytes = Base64.decode(exponentString.getBytes("UTF-8"), Base64.DEFAULT);
BigInteger modulus = new BigInteger(1, modulusBytes);
BigInteger d = new BigInteger(1, dBytes);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, d);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.