加密和解密字符串

时间:2014-10-16 19:10:44

标签: java android string encryption cryptography

我尝试按照SO上的一个示例来加密和解密字符串。

这是我到目前为止所拥有的:

public static String encrypt(String value) {
        byte[] encrypted = null;
        String encrypted_string = null;
        try {

            byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
            Key skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] iv = new byte[cipher.getBlockSize()];

            IvParameterSpec ivParams = new IvParameterSpec(iv);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ivParams);
            encrypted  = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string:" + encrypted.length);

            //Encrypted byte array
            System.out.println("encrypted byte array:" + encrypted);

            //Encrypted string
            encrypted_string = new String(encrypted);
            System.out.println("encrypted string: " + encrypted_string);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return encrypted_string;
    }

    public static String decrypt(String encrypted_string) {
        byte[] original = null;
        Cipher cipher = null;
        String decrypted_string = null;
        try {
            byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
            Key key = new SecretKeySpec(raw, "AES");
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //the block size (in bytes), or 0 if the underlying algorithm is not a block cipher
            byte[] ivByte = new byte[cipher.getBlockSize()];
            //This class specifies an initialization vector (IV). Examples which use
            //IVs are ciphers in feedback mode, e.g., DES in CBC mode and RSA ciphers with OAEP encoding operation.
            IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
            cipher.init(Cipher.DECRYPT_MODE, key, ivParamsSpec);
            original= cipher.doFinal(encrypted_string.getBytes());

            //Converts byte array to String
            decrypted_string = new String(original);
            System.out.println("Text Decrypted : " + decrypted_string);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return decrypted_string;
    }

我希望能够加密字符串然后返回加密字符串。然后取出该加密字符串并将其传递给我的decrypt方法,该方法也返回原始解密字符串。

我使用了Byte []数组的示例,但我不想使用Byte数组,我只想使用字符串。

以上问题是我在这一行上收到错误:

original= cipher.doFinal(encrypted_string.getBytes());

表示“错误的最终块长度:IllegalBlockSizeException”。这让我觉得我不能简单地将我的字符串转换为字节数组并将其传递给doFinal()方法。但是我能以上面想要的格式解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

将随机字节数组(典型的签名转换为字符串)转换为 所有不可打印的字符都将替换为替换字符。 替换字符取决于使用的编码。对于ASCII,这是? (3F十六进制) 对于UTF-8,这是 (EFBFBD十六进制)。

public String(byte[] bytes)使用默认编码进行转换,对于您的应用程序可能是UTF-8。然后String.getBytes()将字符串数据转换回默认编码,您会得到很多 EFBFBD用于原始数据的每个不可打印字符,使其更长。 AES又是分组密码,它以16字节块运行。因此,所有密码 文本的长度与16成比例。这就是为什么你得到无效的块大小, 当将数据损坏到AES解密时。

将二进制数据转换为字符串表示形式的一种可能性是Base64编码。 在Android上,可以使用Base64类完成:

String encryptedString = Base64.encodeToString(encrypted, Base64.DEFAULT);
byte[] encrypted2 = Base64.decode(encryptedString, Base64.DEFAULT);