我想加密和解密一个字符串,但我得到一个奇怪的输出。我不知道为什么它不起作用。
我的加密类,使用Singleton模式:
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 javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
public class CryptExample {
private static final String SECRET_KEY_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static final String UTF_8_CHARSET = "UTF-8";
private static final int BASE_64_ENCODING = Base64.DEFAULT;
private static final String STR_PASSWORD = "bM4uOGs600okBDsF";
private static final String STR_SALT = "iMYGYBFpl2ghOy1k0wMb";
private static final int ITERATION_COUNT = 4;
private static final int KEY_SIZE = 128;
private static CryptExample mCrypt;
private char[] mPasswordArray;
private byte[] mSalt;
private SecretKeySpec mSecretKeySpec;
private Cipher mCipher;
public static CryptExample getInstance() {
if (mCrypt == null) {
mCrypt = new CryptExample();
}
return mCrypt;
}
private CryptExample() {
try {
mPasswordArray = STR_PASSWORD.toCharArray();
mSalt = STR_SALT.getBytes(UTF_8_CHARSET);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try {
init();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
}
}
private void init() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidParameterSpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance(SECRET_KEY_ALGORITHM);
PBEKeySpec spec = new PBEKeySpec(mPasswordArray, mSalt, ITERATION_COUNT, KEY_SIZE);
SecretKey secretKey = factory.generateSecret(spec);
mSecretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
mCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
}
public String encrypt(String szContent) throws NoSuchAlgorithmException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
mCipher.init(Cipher.ENCRYPT_MODE, mSecretKeySpec);
byte[] encryptedContentBytes = mCipher.doFinal(szContent.getBytes(UTF_8_CHARSET));
return Base64.encodeToString(encryptedContentBytes, BASE_64_ENCODING);
}
public String decrypt(String szEncryptedContent) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidParameterSpecException {
byte[] encryptedContentBytes = Base64.decode(szEncryptedContent, BASE_64_ENCODING);
mCipher.init(Cipher.DECRYPT_MODE, mSecretKeySpec);
byte[] decryptedContentBytes = mCipher.doFinal(encryptedContentBytes);
return new String(decryptedContentBytes, UTF_8_CHARSET);
}
}
Ecryption / decription测试:
@Override
protected void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
// Other code
String text = "This is an awesome text that should be encrypted ! This is me, John and Elvira! Welcome home!";
CryptExample crypto = CryptExample.getInstance();
try {
String szEncryptedText = crypto.encrypt(text);
Log.D(TAG, "Text before: " + text);
Log.D(TAG, "Text encrypted: " + szEncryptedText);
String szDecryptedText = crypto.decrypt(szEncryptedText);
Log.D(TAG, "Text decrypted: " + szDecryptedText);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}
输出:
Text before: This is an awesome text that should be encrypted ! This is me, John and Elvira! Welcome home!
Text encrypted: iYtkSbJXeZERPrdqLO40BHo8RMsmVKt7+6jNK9yTW8bPWBIB6IpnBcEk9eZp37p8fcHCOz7uJhcchrY0rgVATqwZHd8F1Xb8IWtdmZxpkB1jsANtrkA4zwJh6/IMLeDz
Text decrypted: ;?)?{eM??%t???me text that should be encrypted ! This is me, John and Elvira! Welcome home!
P.S:您对我的加密类有什么看法?它够好吗?密钥大小或迭代次数怎么样?是否可以使用128 len和4次迭代?和密码结合盐?
答案 0 :(得分:1)
如果您未在init
方法中自行指定,则Java / Android会提供随机IV。
您可以使用new SecureRandom
和IvParameterSpec
生成一个,然后您可以通过将其添加到密文并在解密期间使用它来传达IV。