Android:我的加密/解密不起作用,我的输出很奇怪

时间:2014-11-29 13:54:56

标签: java android encryption cryptography

我想加密和解密一个字符串,但我得到一个奇怪的输出。我不知道为什么它不起作用。

我的加密类,使用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次迭代?和密码结合盐?

1 个答案:

答案 0 :(得分:1)

如果您未在init方法中自行指定,则Java / Android会提供随机IV。

您可以使用new SecureRandomIvParameterSpec生成一个,然后您可以通过将其添加到密文并在解密期间使用它来传达IV。