我在C#中有一個加密和解密字符串文本(基本的東西)的DLL,但現在我需要在Java中實現相同的加密方法,以便某些應用程序可以加密數據並將其發送到圖書館。Java加密和C#解密問題
我不能修改C#代碼,因爲它已經在生產中,但是Java沒有,所以請你在Java端做任何建議。
基本上我試圖在Java中實現相同的C#加密方法。這裏是我的C#代碼:
注意:密碼,鹽等值顯然只是參考。
const string PassPhrase = "IhDyHz6bgQyS0Ff1/1s=";
const string SaltValue = "0A0Qvv09OXd3GsYHVrA=";
const string HashAlgorithm = "SHA1";
const int PasswordIterations = 3;
const string InitVector = "GjrlRZ6INgNckBqv";
const int KeySize = 256;
public static string Encrypt(string plainText)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(InitVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(SaltValue);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
PasswordDeriveBytes password = new PasswordDeriveBytes(
PassPhrase,
saltValueBytes,
HashAlgorithm,
PasswordIterations);
byte[] keyBytes = password.GetBytes(KeySize/8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
keyBytes,
initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream,
encryptor,
CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string cipherText = Convert.ToBase64String(cipherTextBytes);
return cipherText;
}
public static string Decrypt(string cipherText)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(InitVector);
byte[] saltValueBytes = Encoding.ASCII.GetBytes(SaltValue);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
PasswordDeriveBytes password = new PasswordDeriveBytes(
PassPhrase,
saltValueBytes,
HashAlgorithm,
PasswordIterations);
byte[] keyBytes = password.GetBytes(KeySize/8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(
keyBytes,
initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream,
decryptor,
CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes,
0,
plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
string plainText = Encoding.UTF8.GetString(plainTextBytes,
0,
decryptedByteCount);
return plainText;
}
這裏是我的Java代碼,它加密的數據,而不是在相同的方式,C#的加密代碼,所以當我嘗試使用C#庫來解密它拋出的異常:「的長度數據的解密方法是無效的」
static final String PassPhrase = "IhDyHz6bgQyS0Ff1/1s=";
static final String SaltValue = "0A0Qvv09OXd3GsYHVrA=";
static final String HashAlgorithm = "SHA1";
static final int PasswordIterations = 3;
static final String InitVector = "GjrlRZ6INgNckBqv";
static final int KeySize = 256;
public static String encrypt(String plainText)
{
char[] password = PassPhrase.toCharArray();
byte[] salt = SaltValue.getBytes();
byte[] iv = InitVector.getBytes();
byte[] ciphertext = new byte[0];
SecretKeyFactory factory;
try {
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, PasswordIterations, 256);
SecretKey tmp;
tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
//iv = params.getParameterSpec(IvParameterSpec.class).getIV();
ciphertext = cipher.doFinal(plainText.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//catch (InvalidParameterSpecException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
//}
catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Base64.encode(new String(ciphertext));
}
EDIT 1:我固定在Java代碼的最後一個字節陣列轉換爲字符串,如喬恩斯基特建議。
謝謝你,你是正確的,有在Java的那部分的錯誤代碼,我修正了它,現在我得到正確的編碼文本,但仍然無法使用C#代碼解密(例外情況),例如我使用發佈的C#方法加密:Hello World並獲取[「fawkThB32M8FsbOxn05KEw ==」]而在Java中它更長[「bigIxbgKxaHDizUuP8OlR1bCsMOnw78 =」]爲什麼會發生這種情況?我是否應該在某個地方錯過初始向量? – lidermin
@lidermin:填充問題?不確定... –
要嘗試的事情:#1檢查使用的base64變體是否遵循相同的規則並添加換行符等。#2檢查編碼的文本是否可以被java解碼。 – Voo