我有一个需要用 C# 解密的 Java 加密例程。Java 例程正在使用我无法在 C# 中复制的 Bouncy Castle 行:
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
这是 Java 代码中对 Bouncy Castle 的唯一引用。
我无法控制 Java 端,只有 C# 端。我所有的 C# 解密尝试都给了我垃圾数据,与我的 C# 代码相比,我在 Java 代码中发现的唯一差异是 C# 端缺少 Bouncy Castle。有谁知道我如何将 BouncyCastle 指定为 C# 中的安全提供程序?我在他们的网站和网上浏览了 Bouncy Castle 源代码,但没有运气。
编辑:鉴于到目前为止的响应,我已经更新了我的代码以使用 Bouncy Castle。我在下面添加我的 C# 解密代码和 Java 加密代码。当我使用 Bouncy Castle 时,我仍然无法让解密正常工作。我必须忽略一些简单的东西,但我看不到它......任何想法都值得赞赏。
C#解密代码:
public string Decrypt(string stringToDecrypt, string encryption_Key, string init_Vector, string salt)
{
byte[] SALT = Convert.FromBase64String(salt);
int iterations = 12345;
var rfc2898 = new System.Security.Cryptography.Rfc2898DeriveBytes(encryption_Key, SALT, iterations);
byte[] KEY = rfc2898.GetBytes(16);
KeyParameter aesKeyParam = ParameterUtilities.CreateKeyParameter("AES", KEY);
byte[] IV = Encoding.UTF8.GetBytes(init_Vector);
ParametersWithIV aesIVKeyParam = new ParametersWithIV(aesKeyParam, IV);
IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CBC/PKCS5Padding");
cipher.Init(false, aesIVKeyParam);
//byte[] bytesToDecrypt = Convert.FromBase64String(stringToDecrypt);
// Gives me "pad block corrupted" error
//byte[] bytesToDecrypt = Encoding.UTF8.GetBytes(stringToDecrypt);
// Gives me "last block incomplete in decryption" error
byte[] bytesToDecrypt = Base64.Decode(Encoding.UTF8.GetBytes(stringToDecrypt));
// Gives me "pad block corrupted" error
byte[] output = cipher.DoFinal(bytesToDecrypt);
return Convert.ToBase64String(output);
}
Java代码:
public class testaes {
/**
* The iteration count for key generation algorithm.
*/
private static final int KEY_ITERATION_COUNT = 12345;
/**
* The key length in bits.
*/
private static final int KEY_LENGTH = 128;
/**
* The algorithm for cipher initialization.
*/
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
/**
* The algorithm for key factory selection.
*/
private static final String KEY_FACTORY_ALGORITHM = "PBKDF2WithHmacSHA1";
/**
* The algorithm for key generation.
*/
private static final String KEY_ALGORITHM = "AES";
/**
* The byte encoding.
*/
private static final String BYTE_ENCODING = "UTF-8";
private static testaes instance = null;
public testaes() {
super();
}
public static testaes getInstance() {
if (instance == null) {
instance = new testaes();
}
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
return instance;
}
/**
* Instantiates the cipher.
*/
private Cipher initCipher(int opmode) throws Exception, NoSuchAlgorithmException, InvalidKeySpecException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
String access = "XXXXX";
byte[] salt = "XXXXX".getBytes();
String ivString = "XXXXX";
// Build the key from password and salt.
char[] accessCharArray = access.toCharArray();
byte[] saltByteArray = Base64.decodeBase64(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
KeySpec spec = new PBEKeySpec(accessCharArray, saltByteArray, KEY_ITERATION_COUNT, KEY_LENGTH);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secretKey = new SecretKeySpec(tmp.getEncoded(), KEY_ALGORITHM);
// Create a cipher based on AES transformation.
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// Initialize cipher to with Secret Key and IV.
cipher.init(opmode, secretKey, new IvParameterSpec(ivString.getBytes(BYTE_ENCODING)));
return cipher;
}
/**
* Encrypts the data.
*
* @param originalString
* The data to be encrypted.
* @return The encrypted data as String.
*/
public String encryptAES(String originalString) {
String encryptedString = null;
try {
Cipher cipher = initCipher(Cipher.ENCRYPT_MODE);
byte[] encryptedBytes = cipher.doFinal(originalString.getBytes());
String base64Encoded = new String(Base64.encodeBase64(encryptedBytes), Charset.forName(BYTE_ENCODING));
String urlEncoded = URLEncoder.encode(base64Encoded, BYTE_ENCODING);
encryptedString = urlEncoded;
} catch (Exception e) {
e.printStackTrace();
}
return encryptedString;
}
/**
* Decrypts the data.
*
* @param encryptedString
* The encrypted data that is to be decrypted.
* @return The decrypted (original) data as string.
*/
public String decryptAES(String encryptedString) {
String decryptedString = null;
try {
Cipher cipher = initCipher(Cipher.DECRYPT_MODE);
String urlDecoded = URLDecoder.decode(encryptedString, BYTE_ENCODING);
byte[] encryptedBytes = Base64.decodeBase64(urlDecoded.getBytes(Charset.forName(BYTE_ENCODING)));
byte[] originalBytes = cipher.doFinal(encryptedBytes);
decryptedString = new String(originalBytes);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedString;
}