Java AES不解密阿拉伯语

时间:2014-03-20 10:35:49

标签: java eclipse encryption aes

我正在使用Eclipse来加密和解密字符串。我正在使用以下功能:

private final static String ALGORITHM = "AES";


    public static String cipher(String secretKey, String data) throws Exception {



        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), secretKey.getBytes(), 128, 256);

        SecretKey tmp = factory.generateSecret(spec);

        SecretKey key = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);



        Cipher cipher = Cipher.getInstance(ALGORITHM);

        cipher.init(Cipher.ENCRYPT_MODE, key);



        return toHex(cipher.doFinal(data.getBytes()));

    }


    public static String decipher(String secretKey, String data) throws Exception {



        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

        KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), secretKey.getBytes(), 128, 256);

        SecretKey tmp = factory.generateSecret(spec);

        SecretKey key = new SecretKeySpec(tmp.getEncoded(), ALGORITHM);



        Cipher cipher = Cipher.getInstance(ALGORITHM);



        cipher.init(Cipher.DECRYPT_MODE, key);



        return new String(cipher.doFinal(toByte(data)));

    }


    private static byte[] toByte(String hexString) {

        int len = hexString.length()/2;



        byte[] result = new byte[len];



        for (int i = 0; i < len; i++)

            result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();

        return result;

    }


    public static String toHex(byte[] stringBytes) {

        StringBuffer result = new StringBuffer(2*stringBytes.length);



        for (int i = 0; i < stringBytes.length; i++) {

            result.append(HEX.charAt((stringBytes[i]>>4)&0x0f)).append(HEX.charAt(stringBytes[i]&0x0f));

        }



        return result.toString();

    }
    private final static String HEX = "0123456789ABCDEF";

我正在处理的字符串包含英文和阿拉伯字符。当我正在解密字符串时,阿拉伯字符被问号(?)

替换

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:4)

问题是您使用data.getBytes()(和secretKey.getBytes())。此方法使用操作系统上的默认编码。例如,在Windows上的西欧,此默认值为Cp1252,其中不包含阿拉伯语,因此将不受支持的字符转换为?

创建字符串时,您需要使用data.getBytes("UTF-8)和相同的内容。

底线:始终用你的角色集明确!

答案 1 :(得分:2)

这里有三个单独的转换:

  • 未加密的文本到未加密的字节
  • 加密字节的未加密字节
  • 加密字节为十六进制

......反之,当然。

怀疑问题出在第一步。目前您正在使用new String(byte[])String.getBytes(),两者都使用平台默认编码。这几乎总是一个坏主意。使用UTF-8(例如使用StandardCharsets.UTF_8)进行所有编码和解码通常是个好主意,除非您有充分的理由使用其他内容。

这是一个起点 - 但另一个是分别查看这些转换的每个,并确定数据被破坏的位置。很多诊断都会有所帮助。

我有一个blog post about precisely this sort of problem,它会详细介绍。

答案 2 :(得分:0)

我做了两次调整并且有效:

  • 在我写的密码函数中:return toHex(cipher.doFinal(data.getBytes(&#34; UTF-8&#34;)));

  • 在解密函数中我写了这个:return new String(cipher.doFinal(toByte(data)),&#34; UTF-8&#34;);