我必须创建一个weservice,它使用AES,盐大小为32和给定密码发送加密的字符串。我正在尝试使我的代码工作,但当我尝试解密一个字符串时,他们让我检查解密是否正常工作我得到一个错误:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
我的代码如下:
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
/**
* parts of this code were copied from the StandardPBEByteEncryptor class from the Jasypt (www.jasypt.org) project
*/
public class AESCrypt {
//private final String KEY_ALGORITHM = "PBEWITHSHA256AND128BITAES-CBC-BC";
private final String KEY_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
private final String MODE_PADDING = "/CBC/PKCS5Padding";
private final int DEFAULT_SALT_SIZE_BYTES = 32;
private final SecureRandom rand;
private final String passwd = "8g5qT74KdUY";
public AESCrypt() throws Exception {
rand = SecureRandom.getInstance("SHA1PRNG");
}
private byte[] generateSalt(int size) {
byte[] salt = new byte[size];
rand.nextBytes(salt);
return salt;
}
private SecretKey generateKey(String algorithm, int keySize, byte[] salt) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray(), salt, 100000);
SecretKey tmpKey = factory.generateSecret(pbeKeySpec);
byte[] keyBytes = new byte[keySize / 8];
System.arraycopy(tmpKey.getEncoded(), 0, keyBytes, 0, keyBytes.length);
return new SecretKeySpec(keyBytes, algorithm);
}
private byte[] generateIV(Cipher cipher) {
byte[] iv = new byte[cipher.getBlockSize()];
rand.nextBytes(iv);
return iv;
}
private byte[] appendArrays(byte[] firstArray, byte[] secondArray) {
final byte[] result = new byte[firstArray.length + secondArray.length];
System.arraycopy(firstArray, 0, result, 0, firstArray.length);
System.arraycopy(secondArray, 0, result, firstArray.length, secondArray.length);
return result;
}
public byte[] encrypt(String algorithm, int keySize, final byte[] message) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);
// The salt size for the chosen algorithm is set to be equal
// to the algorithm's block size (if it is a block algorithm).
int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
int algorithmBlockSize = cipher.getBlockSize();
if (algorithmBlockSize > 0) {
saltSizeBytes = algorithmBlockSize;
}
// Create salt
final byte[] salt = generateSalt(saltSizeBytes);
SecretKey key = generateKey(algorithm, keySize, salt);
// create a new IV for each encryption
final IvParameterSpec ivParamSpec = new IvParameterSpec(generateIV(cipher));
// Perform encryption using the Cipher
cipher.init(Cipher.ENCRYPT_MODE, key, ivParamSpec);
byte[] encryptedMessage = cipher.doFinal(message);
// append the IV and salt
encryptedMessage = appendArrays(ivParamSpec.getIV(), encryptedMessage);
encryptedMessage = appendArrays(salt, encryptedMessage);
return encryptedMessage;
}
public byte[] decrypt(String algorithm, int keySize, final byte[] encryptedMessage) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);
// determine the salt size for the first layer of encryption
int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
int algorithmBlockSize = cipher.getBlockSize();
if (algorithmBlockSize > 0) {
saltSizeBytes = algorithmBlockSize;
}
System.out.println("saltSizeBytes:"+saltSizeBytes);
byte[] decryptedMessage = new byte[encryptedMessage.length];
System.arraycopy(encryptedMessage, 0, decryptedMessage, 0, encryptedMessage.length);
// extract the salt and IV from the incoming message
byte[] salt = null;
byte[] iv = null;
byte[] encryptedMessageKernel = null;
final int saltStart = 0;
final int saltSize = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes : decryptedMessage.length);
//final int saltSize = 32;
//System.out.println("saltSize:"+saltSize);
final int ivStart = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes : decryptedMessage.length);
final int ivSize = cipher.getBlockSize();
final int encMesKernelStart = (saltSizeBytes + ivSize < decryptedMessage.length ? saltSizeBytes + ivSize : decryptedMessage.length);
final int encMesKernelSize = (saltSizeBytes + ivSize < decryptedMessage.length ? (decryptedMessage.length - saltSizeBytes - ivSize) : 0);
salt = new byte[saltSize];
iv = new byte[ivSize];
System.out.println("saltSize:"+saltSize);
System.out.println("ivSize:"+ivSize);
encryptedMessageKernel = new byte[encMesKernelSize];
System.out.println("encryptedMessageKernel");
System.arraycopy(decryptedMessage, saltStart, salt, 0, saltSize);
System.arraycopy(decryptedMessage, ivStart, iv, 0, ivSize);
System.arraycopy(decryptedMessage, encMesKernelStart, encryptedMessageKernel, 0, encMesKernelSize);
SecretKey key = generateKey(algorithm, keySize, salt);
System.out.println("ekey");
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
// Perform decryption using the Cipher
cipher.init(Cipher.DECRYPT_MODE, key, ivParamSpec);
decryptedMessage = cipher.doFinal(encryptedMessageKernel);
// Return the results
return decryptedMessage;
}
现在我有了这些信息,我知道它已被加密,我想解密:
Original String: 12334567
Crypted String: SsH6NO9a64g0U7szvFwSbCkdUF5dNgmxgpt2jU/nFVntG3r2nYxgxLRXri4MW9Z2
Password: 8g5qT74KdUY
当我尝试解密SsH...
时,我得到了给定的错误。问题出在哪儿?这就是我的工作:
String toDecrypt = "SsH6NO9a64g0U7szvFwSbCkdUF5dNgmxgpt2jU/nFVntG3r2nYxgxLRXri4MW9Z2";
byte[] criptata = Base64.decode(toDecrypt);
byte[] decriptata = engine.decrypt("AES", 128, criptata);
String msgdecriptato = new String(decriptata);
这给了我一个错误。
以下是C#中用于解密的代码:
private const int SaltSize = 32;
/// <summary>
/// Decrypts the ciphertext using the Key.
/// </summary>
/// <param name="ciphertext">The ciphertext to decrypt.</param>
/// <param name="key">The plain text encryption key.</param>
/// <returns>The decrypted text.</returns>
public string Decrypt(string ciphertext, string key)
{
if (string.IsNullOrEmpty(ciphertext))
throw new ArgumentNullException("ciphertext");
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key");
// Extract the salt from our ciphertext
var allTheBytes = Convert.FromBase64String(ciphertext);
var saltBytes = allTheBytes.Take(SaltSize).ToArray();
var ciphertextBytes = allTheBytes.Skip(SaltSize).Take(allTheBytes.Length - SaltSize).ToArray();
using (var keyDerivationFunction = new Rfc2898DeriveBytes(key, saltBytes))
{
// Derive the previous IV from the Key and Salt
var keyBytes = keyDerivationFunction.GetBytes(32);
var ivBytes = keyDerivationFunction.GetBytes(16);
// Create a decrytor to perform the stream transform.
// Create the streams used for decryption.
// The default Cipher Mode is CBC and the Padding is PKCS7 which are both good
using (var aesManaged = new AesManaged())
using (var decryptor = aesManaged.CreateDecryptor(keyBytes, ivBytes))
using (var memoryStream = new MemoryStream(ciphertextBytes))
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
using (var streamReader = new StreamReader(cryptoStream))
{
// Return the decrypted bytes from the decrypting stream.
return streamReader.ReadToEnd();
}
}
}
任何提示?
答案 0 :(得分:1)
我运行了你的代码,这似乎是你的原始字符串的问题。您必须知道,如果使用128位密钥加密,则无法使用256位密钥加密。如果密钥大小不匹配,则会出现填充错误。这是一个有效的主代码:
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
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.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
/**
* parts of this code were copied from the StandardPBEByteEncryptor class from
* the Jasypt (www.jasypt.org) project
*/
public class AESCrypt {
// private final String KEY_ALGORITHM = "PBEWITHSHA256AND128BITAES-CBC-BC";
private final String KEY_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
private final String MODE_PADDING = "/CBC/PKCS5Padding";
private final int DEFAULT_SALT_SIZE_BYTES = 32;
private final SecureRandom rand;
private final String passwd = "8g5qT74KdUY";
public AESCrypt() throws Exception {
rand = SecureRandom.getInstance("SHA1PRNG");
}
private byte[] generateSalt(int size) {
byte[] salt = new byte[size];
rand.nextBytes(salt);
return salt;
}
private SecretKey generateKey(String algorithm, int keySize, byte[] salt)
throws NoSuchProviderException, NoSuchAlgorithmException,
InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray(), salt,
100000);
SecretKey tmpKey = factory.generateSecret(pbeKeySpec);
byte[] keyBytes = new byte[keySize / 8];
System.arraycopy(tmpKey.getEncoded(), 0, keyBytes, 0, keyBytes.length);
return new SecretKeySpec(keyBytes, algorithm);
}
private byte[] generateIV(Cipher cipher) {
byte[] iv = new byte[cipher.getBlockSize()];
rand.nextBytes(iv);
return iv;
}
private byte[] appendArrays(byte[] firstArray, byte[] secondArray) {
final byte[] result = new byte[firstArray.length + secondArray.length];
System.arraycopy(firstArray, 0, result, 0, firstArray.length);
System.arraycopy(secondArray, 0, result, firstArray.length,
secondArray.length);
return result;
}
public byte[] encrypt(String algorithm, int keySize, final byte[] message)
throws Exception {
Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);
// The salt size for the chosen algorithm is set to be equal
// to the algorithm's block size (if it is a block algorithm).
int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
int algorithmBlockSize = cipher.getBlockSize();
if (algorithmBlockSize > 0) {
saltSizeBytes = algorithmBlockSize;
}
// Create salt
final byte[] salt = generateSalt(saltSizeBytes);
SecretKey key = generateKey(algorithm, keySize, salt);
// create a new IV for each encryption
final IvParameterSpec ivParamSpec = new IvParameterSpec(
generateIV(cipher));
// Perform encryption using the Cipher
cipher.init(Cipher.ENCRYPT_MODE, key, ivParamSpec);
byte[] encryptedMessage = cipher.doFinal(message);
// append the IV and salt
encryptedMessage = appendArrays(ivParamSpec.getIV(), encryptedMessage);
encryptedMessage = appendArrays(salt, encryptedMessage);
return encryptedMessage;
}
public byte[] decrypt(String algorithm, int keySize,
final byte[] encryptedMessage) throws Exception {
Cipher cipher = Cipher.getInstance(algorithm + MODE_PADDING);
// determine the salt size for the first layer of encryption
int saltSizeBytes = DEFAULT_SALT_SIZE_BYTES;
int algorithmBlockSize = cipher.getBlockSize();
if (algorithmBlockSize > 0) {
saltSizeBytes = algorithmBlockSize;
}
System.out.println("saltSizeBytes:" + saltSizeBytes);
byte[] decryptedMessage = new byte[encryptedMessage.length];
System.arraycopy(encryptedMessage, 0, decryptedMessage, 0,
encryptedMessage.length);
// extract the salt and IV from the incoming message
byte[] salt = null;
byte[] iv = null;
byte[] encryptedMessageKernel = null;
final int saltStart = 0;
final int saltSize = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes
: decryptedMessage.length);
// final int saltSize = 32;
// System.out.println("saltSize:"+saltSize);
final int ivStart = (saltSizeBytes < decryptedMessage.length ? saltSizeBytes
: decryptedMessage.length);
final int ivSize = cipher.getBlockSize();
final int encMesKernelStart = (saltSizeBytes + ivSize < decryptedMessage.length ? saltSizeBytes
+ ivSize
: decryptedMessage.length);
final int encMesKernelSize = (saltSizeBytes + ivSize < decryptedMessage.length ? (decryptedMessage.length
- saltSizeBytes - ivSize)
: 0);
salt = new byte[saltSize];
iv = new byte[ivSize];
System.out.println("saltSize:" + saltSize);
System.out.println("ivSize:" + ivSize);
encryptedMessageKernel = new byte[encMesKernelSize];
System.out.println("encryptedMessageKernel");
System.arraycopy(decryptedMessage, saltStart, salt, 0, saltSize);
System.arraycopy(decryptedMessage, ivStart, iv, 0, ivSize);
System.arraycopy(decryptedMessage, encMesKernelStart,
encryptedMessageKernel, 0, encMesKernelSize);
SecretKey key = generateKey(algorithm, keySize, salt);
System.out.println("ekey");
IvParameterSpec ivParamSpec = new IvParameterSpec(iv);
// Perform decryption using the Cipher
cipher.init(Cipher.DECRYPT_MODE, key, ivParamSpec);
decryptedMessage = cipher.doFinal(encryptedMessageKernel);
// Return the results
return decryptedMessage;
}
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
AESCrypt aesCrypt = new AESCrypt();
String originalText = "1234567";
String toDecrypt = new String(Base64.encode(aesCrypt.encrypt("AES", 256, originalText.getBytes())));
System.out.println(toDecrypt);
byte[] criptata = Base64.decode(toDecrypt);
byte[] decriptata = aesCrypt.decrypt("AES", 256, criptata);
String msgdecriptato = new String(decriptata);
System.out.println(msgdecriptato);
if (!originalText.equals(msgdecriptato)) {
throw new IllegalStateException("Strings do not match!");
}
}
}