这是我尝试将其转换为等效 C# 代码的 Java 加密代码:
nhập java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.Validate;
public class Encryptor
{
private static final String CIPHER_ALOGRITHM = "AES/CBC/PKCS5Padding";
private static final String KEY_ALOGRITHM = "PBKDF2WithHmacSHA1";
private static final String KEY_SPEC_ALOGRITHM = "AES";
private static final String ENCODING = "UTF-8";
public static String decrypt(String password, String encodedCiphertextAndIv) throws GeneralSecurityException,
Ngoại lệ mã hóa không được hỗ trợ
{
String[] ra = mã hóaCiphertextAndIv.split(://);
byte[] bản mã = Base64.decodeBase64(ra[0]);
byte[] iv = Base64.decodeBase64(ra[1]);
/* Giải mã tin nhắn, cho trước khóa dẫn xuất và vectơ khởi tạo */
Mật mã = Cipher.getInstance(CIPHER_ALOGRITHM);
cipher.init(Cipher.DECRYPT_MODE, getSecret(password), IvParameterSpec(iv) mới);
Chuỗi bản rõ = Chuỗi mới(cipher.doFinal(bản mã), ENCODING);
trả lại bản rõ;
}
tĩnh SecretKey getSecret(Chuỗi mật khẩu) ném GeneralSecurityException
{
byte[] salt = Arrays.copyOf(password.getBytes(), 8);
/* Lấy khóa, mật khẩu và muối đã cho */
Nhà máy SecretKeyFactory = SecretKeyFactory.getInstance(KEY_ALOGRITHM);
Thông số KeySpec = PBEKeySpec mới(password.toCharArray(), salt, 1024, 128);
SecretKey tmp = Factory.generateSecret(spec);
Bí mật SecretKey = SecretKeySpec mới(tmp.getEncoded(), KEY_SPEC_ALOGRITHM);
trả lại bí mật;
}
Mã hóa chuỗi tĩnh công khai (Mật khẩu chuỗi, Chuỗi plainText) ném GeneralSecurityException,
Ngoại lệ mã hóa không được hỗ trợ
{
nếu (plainText == null)
{
trả về plainText;
}
Chuỗi[] plainTextValues = Chuỗi mới[]
{
văn bản đơn giản
};
Chuỗi[] mã hóaValues = mã hóa (mật khẩu, plainTextValues);
trả về các giá trị được mã hóa[0];
}
chuỗi tĩnh công khai [] mã hóa (Mật khẩu chuỗi, Chuỗi [] plainTextValues) ném GeneralSecurityException,
Ngoại lệ mã hóa không được hỗ trợ
{
if (plainTextValues == null || plainTextValues.length == 0)
{
trả về Chuỗi mới[] {};
}
Validate.notEmpty(password, "password không được để trống");
/* Mã hóa tin nhắn */
Mật mã = Cipher.getInstance(CIPHER_ALOGRITHM);
cipher.init(Cipher.ENCRYPT_MODE, getSecret(password));
Thông số AlgorithmParameters = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
Chuỗi được mã hóaIv = Chuỗi mới(Base64.encodeBase64(iv));
Chuỗi [] mã hóaValues = Chuỗi mới [plainTextValues.length];
for (int i = 0; i < plainTextValues.length; i++)
{
Chuỗi plainText = plainTextValues[i];
nếu (plainText == null)
{
mã hóaValues[i] = plainText;
}
khác
{
byte[] ciphertext = cipher.doFinal(plainText.getBytes(ENCODING));
Chuỗi được mã hóaCiphertext = Chuỗi mới (Base64.encodeBase64 (bản mã));
mã hóaValues[i] = mã hóaCiphertext + ://> + mã hóaIv;
}
}
trả về các giá trị được mã hóa;
}
public static void main(String[] args) ném ngoại lệ
{
Chuỗi mật khẩu = "Bí mật";
String plainText = "Xin chào thế giới!";
Chuỗi enc = mã hóa (mật khẩu, plainText);
System.out.println(enc);
System.out.println(decrypt(password, enc));
}
}
Đây là mã C# tôi đã thử:
using System;
using System.Text;
sử dụng System.Security.Cryptography;
không gian tên ConsoleApplication1
{
class Program
{
chuỗi const riêng CIPHER_ALOGRITHM = "AES/CBC/PKCS5Padding";
chuỗi const riêng KEY_ALOGRITHM = "PBKDF2WithHmacSHA1";
chuỗi const riêng KEY_SPEC_ALOGRITHM = "AES";
chuỗi const riêng ENCODING = "UTF-8";
static void Main(string[] args)
{
string key = "Bí mật";
string plainTextValue = "Xin chào thế giới!";
Chương trình p = Chương trình mới();
chuỗi mã hóa giá trị = p.Encrypt(key, plainTextValue);
//Console.WriteLine("encryptedvalue:{0}", mã hóa giá trị);
chuỗi decryptedvalue = p.Decrypt(appsecret, Encryptedvalue);
//Console.WriteLine("decryptedvalue:{0}", decryptedvalue);
}
public RijndaelĐược quản lý GetRijndaelĐược quản lý(Chuỗi bí mật)
{
var keyBytes = byte mới[16];
var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
trả lại Rijndael mớiĐược quản lý
{
Chế độ = CipherMode.CBC,
Phần đệm = PaddingMode.PKCS7,
Kích thước khóa = 128,
Kích thước khối = 128,
Khóa = keyBytes,
IV = keyByte
};
}
byte công khai[] Mã hóa(byte[] plainBytes, RijndaelĐược quản lý rijndaelĐược quản lý)
{
trả về rijndaelQuản lý.CreateEncryptor().TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}
byte công khai[] Giải mã(byte[] dữ liệu mã hóa, RijndaelĐược quản lý rijndaelĐược quản lý)
{
trả về rijndaelQuản lý.CreateDecryptor().TransformFinalBlock(encryptedData, 0, mã hóaData.Length);
}
///
/// Mã hóa văn bản gốc bằng khóa AES 128bit và Mật mã khối chuỗi và trả về chuỗi được mã hóa base64
///
/// Văn bản thuần túy để mã hóa
/// Khóa bí mật
/// Chuỗi được mã hóa Base64
///
Mã hóa chuỗi công khai (Khóa chuỗi, Chuỗi văn bản thuần túy)
{
var plainBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(Encrypt(plainBytes, GetRijndael Managed(key)));
}
///
/// Giải mã chuỗi được mã hóa base64 bằng khóa đã cho (khóa AES 128bit và Mật mã khối chuỗi)
///
/// Chuỗi mã hóa Base64
/// Khóa bí mật
/// Chuỗi được giải mã
///
Giải mã chuỗi công khai(Khóa chuỗi, Văn bản được mã hóa chuỗi)
{
var mã hóaBytes = Convert.FromBase64String(encryptedText);
return Encoding.UTF8.GetString(Decrypt(encryptedBytes, GetRijndaelQuản lý(key)));
}
}
}
Nhưng mã hóa được thực hiện ở phía C# không mang lại cùng giá trị khi được giải mã bằng mã Java. Tình huống là ứng dụng web của tôi (được xây dựng trên .net C#) phải chuyển dữ liệu được mã hóa sang ứng dụng java để giải mã nó. Vì vậy tôi cần đảm bảo mã hóa trên .net tương đương với mã hóa Java.
Cần sự giúp đỡ của bạn.
Có vẻ như bạn không băm khóa trong quá trình triển khai C# của mình. dòng này
cipher.init(Cipher.ENCRYPT_MODE, getSecret(password));
Chịu trách nhiệm về các hoạt động trong đoạn mã Java.
Nhưng trong C# bạn chỉ sử dụng khóa dưới dạng văn bản thuần túy để mã hóa.
Tôi đã thực hiện một nhiệm vụ tương tự và đây là phần còn thiếu, nó băm bí mật và cho phép bạn tạo các giá trị iv và key để mã hóa AES:
var có nguồn gốcPassword = Rfc2898DeriveBytes mới (secretKey, saltBytes);
var đối xứngKey = new RijndaelQuản lý();
byte[] keyBytes = có nguồn gốcPassword.GetBytes(Đối xứngKey.KeySize/8);
byte[] initBytes = có nguồn gốcPassword.GetBytes(Đối xứngKey.BlockSize/8);
Tôi là một lập trình viên xuất sắc, rất giỏi!