我有下面的代碼幾乎工作:AES與鹽和靜態密碼
AES.java
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
private static final int KEY_LENGTH = 128;
private static final int ITERATIONS = 100;
private static final String ALGORITHM = "AES";
private static final String SECRET_KEY_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private final Cipher m_enc_cipher;
private final Cipher m_dec_cipher;
private final byte[] m_iv;
public AES(final char[] password, final byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException,
NoSuchPaddingException, InvalidKeyException,
InvalidParameterSpecException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException,
InvalidAlgorithmParameterException {
// Derive the key, given password and salt
final SecretKeyFactory factory = SecretKeyFactory
.getInstance(SECRET_KEY_ALGORITHM);
final KeySpec spec = new PBEKeySpec(password, salt, ITERATIONS,
KEY_LENGTH);
final SecretKey tmp = factory.generateSecret(spec);
final SecretKey secret = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);
// Build encryptor and get IV
final Cipher enc_cipher = Cipher.getInstance(TRANSFORMATION);
enc_cipher.init(Cipher.ENCRYPT_MODE, secret);
final AlgorithmParameters params = enc_cipher.getParameters();
final byte[] iv = params.getParameterSpec(IvParameterSpec.class)
.getIV();
// Build decryptor
final Cipher dec_cipher = Cipher.getInstance(TRANSFORMATION);
dec_cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
this.m_enc_cipher = enc_cipher;
this.m_dec_cipher = dec_cipher;
this.m_iv = iv;
}
public AES(final byte[] iv) throws NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException,
InvalidKeyException, InvalidParameterSpecException,
IllegalBlockSizeException, BadPaddingException,
UnsupportedEncodingException, InvalidAlgorithmParameterException {
final AlgorithmParameterSpec aps = new IvParameterSpec(iv);
final KeyGenerator keygen = KeyGenerator.getInstance(ALGORITHM);
keygen.init(KEY_LENGTH);
final SecretKey secret = keygen.generateKey();
// Build encryptor
final Cipher enc_cipher = Cipher.getInstance(TRANSFORMATION);
enc_cipher.init(Cipher.ENCRYPT_MODE, secret, aps);
// Build decryptor
final Cipher dec_cipher = Cipher.getInstance(TRANSFORMATION);
dec_cipher.init(Cipher.DECRYPT_MODE, secret, aps);
this.m_enc_cipher = enc_cipher;
this.m_dec_cipher = dec_cipher;
this.m_iv = iv;
}
public byte[] get_iv() {
return this.m_iv;
}
public byte[] encrypt(final byte[] data) throws NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException,
InvalidKeyException, InvalidParameterSpecException,
IllegalBlockSizeException, BadPaddingException,
UnsupportedEncodingException {
return this.m_enc_cipher.doFinal(data);
}
public byte[] decrypt(final byte[] data) throws IllegalBlockSizeException,
BadPaddingException {
return this.m_dec_cipher.doFinal(data);
}
}
AESTest.java
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.junit.Test;
import static org.junit.Assert.*;
public class AESTest {
@Test
public void test() throws InvalidKeyException, NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException,
InvalidParameterSpecException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException,
InvalidAlgorithmParameterException {
final char[] password = "my_password".toCharArray();
final byte[] salt = new byte[] { 22, 11 };
final byte[] original_data = "Hello, World!".getBytes("UTF-8");
final AES aesA = new AES(password, salt);
final byte[] encrypted_data = aesA.encrypt(original_data);
System.out.println("Encrypted:");
System.out.println(javax.xml.bind.DatatypeConverter
.printBase64Binary(encrypted_data));
final AES aesB = new AES(aesA.get_iv());
final byte[] decrypted_data_B = aesB.decrypt(encrypted_data);
System.out.println("Decrypted B:");
System.out.println(javax.xml.bind.DatatypeConverter
.printBase64Binary(decrypted_data_B));
assertTrue(Arrays.equals(original_data, decrypted_data_B));
}
}
在測試(AESTest.java),它給了我這個錯誤:
javax.crypto.BadPaddingException: Given final block not properly padded
我的最終目的是能夠發送加密的數據塊,並在以後拿回來。
術語「稍後」可以指一天/一週/年。
然後,使用相同的密碼我想解密它。
因爲「稍後」可能是一個月,我需要創建一個新的AES
對象。
現在,這個新的AES
對象必須能夠使用相同的固定密碼/鹽來解密數據。
就是這樣。
我試過使用相同的IV,但它不起作用。
我在這裏做錯了什麼?
編輯#1: 請注意ITERATIONS
以及。
第二個ctor應該看起來像http://pastebin.com/741SuBtv?它實際上工作,但我想知道,如果它仍然是靜態的,那麼這兩個'SecretKey'對象('tmp'&'secret')是做什麼的?不知道我明白這一點。無論如何,你對發佈的代碼有什麼看法? – Poni 2012-04-08 19:56:12
謝謝! ............. – Poni 2012-04-19 17:58:44