这是我试图转换为等效C#代码的Java加密代码:
import 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,
UnsupportedEncodingException
{
String[] ra = encodedCiphertextAndIv.split(":");
byte[] ciphertext = Base64.decodeBase64(ra[0]);
byte[] iv = Base64.decodeBase64(ra[1]);
/* Decrypt the message, given derived key and initialization vector. */
Cipher cipher = Cipher.getInstance(CIPHER_ALOGRITHM);
cipher.init(Cipher.DECRYPT_MODE, getSecret(password), new IvParameterSpec(iv));
String plaintext = new String(cipher.doFinal(ciphertext), ENCODING);
return plaintext;
}
static SecretKey getSecret(String password) throws GeneralSecurityException
{
byte[] salt = Arrays.copyOf(password.getBytes(), 8);
/* Derive the key, given password and salt. */
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALOGRITHM);
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 128);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), KEY_SPEC_ALOGRITHM);
return secret;
}
public static String encrypt(String password, String plainText) throws GeneralSecurityException,
UnsupportedEncodingException
{
if (plainText == null)
{
return plainText;
}
String[] plainTextValues = new String[]
{
plainText
};
String[] encryptedValues = encrypt(password, plainTextValues);
return encryptedValues[0];
}
public static String[] encrypt(String password, String[] plainTextValues) throws GeneralSecurityException,
UnsupportedEncodingException
{
if (plainTextValues == null || plainTextValues.length == 0)
{
return new String[] {};
}
Validate.notEmpty(password, "password must not be empty");
/* Encrypt the message. */
Cipher cipher = Cipher.getInstance(CIPHER_ALOGRITHM);
cipher.init(Cipher.ENCRYPT_MODE, getSecret(password));
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
String encodedIv = new String(Base64.encodeBase64(iv));
String[] encryptedValues = new String[plainTextValues.length];
for (int i = 0; i < plainTextValues.length; i++)
{
String plainText = plainTextValues[i];
if (plainText == null)
{
encryptedValues[i] = plainText;
}
else
{
byte[] ciphertext = cipher.doFinal(plainText.getBytes(ENCODING));
String encodedCiphertext = new String(Base64.encodeBase64(ciphertext));
encryptedValues[i] = encodedCiphertext + ":" + encodedIv;
}
}
return encryptedValues;
}
public static void main(String[] args) throws Exception
{
String password = "The Secret";
String plainText = "Hello, World!";
String enc = encrypt(password, plainText);
System.out.println(enc);
System.out.println(decrypt(password, enc));
}
}
这是我尝试过的C#代码:
using System;
using System.Text;
using System.Security.Cryptography;
namespace ConsoleApplication1
{
class Program
{
private const string CIPHER_ALOGRITHM = "AES/CBC/PKCS5Padding";
private const string KEY_ALOGRITHM = "PBKDF2WithHmacSHA1";
private const string KEY_SPEC_ALOGRITHM = "AES";
private const string ENCODING = "UTF-8";
static void Main(string[] args)
{
string key = "The Secret";
string plainTextValue = "Hello, World!";
Program p = new Program();
string encryptedvalue = p.Encrypt(key, plainTextValue);
//Console.WriteLine("encryptedvalaue:{0}", encryptedvalue);
string decryptedvalue = p.Decrypt(appsecret, encryptedvalue);
//Console.WriteLine("decryptedvalue:{0}", decryptedvalue);
}
public RijndaelManaged GetRijndaelManaged(String secretKey)
{
var keyBytes = new byte[16];
var secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
return new RijndaelManaged
{
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7,
KeySize = 128,
BlockSize = 128,
Key = keyBytes,
IV = keyBytes
};
}
public byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateEncryptor().TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}
public byte[] Decrypt(byte[] encryptedData, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
}
/// <summary>
/// Encrypts plaintext using AES 128bit key and a Chain Block Cipher and returns a base64 encoded string
/// </summary>
/// <param name="plainText">Plain text to encrypt</param>
/// <param name="key">Secret key</param>
/// <returns>Base64 encoded string</returns>
///
public String Encrypt(String key, String plainText)
{
var plainBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
}
/// <summary>
/// Decrypts a base64 encoded string using the given key (AES 128bit key and a Chain Block Cipher)
/// </summary>
/// <param name="encryptedText">Base64 Encoded String</param>
/// <param name="key">Secret Key</param>
/// <returns>Decrypted String</returns>
///
public String Decrypt(String key, String encryptedText)
{
var encryptedBytes = Convert.FromBase64String(encryptedText);
return Encoding.UTF8.GetString(Decrypt(encryptedBytes, GetRijndaelManaged(key)));
}
}
}
但是,使用Java代码解密时,在C#端进行的加密不会产生相同的值。方案是我的Web应用程序(基于.net C#构建)必须将加密数据传输到将解密它的Java应用程序。所以我需要确保.net上的加密等同于Java加密。
需要你的帮助。
答案 0 :(得分:1)
看起来你没有在C#实现中散列你的密钥。 这一行
cipher.init(Cipher.ENCRYPT_MODE, getSecret(password));
负责Java代码段中的内容。
但在C#中,您只需将秘密用作纯文本进行加密。
我做了类似的任务,这里是遗漏秘密的缺失部分,允许您为AES加密生成iv和key值:
var derivedPassword = new Rfc2898DeriveBytes(secretKey, saltBytes);
var symmetricKey = new RijndaelManaged();
byte[] keyBytes = derivedPassword.GetBytes(symmetricKey.KeySize/8);
byte[] initBytes = derivedPassword.GetBytes(symmetricKey.BlockSize/8);