Java Cipher 解密中的奇怪字符

Posted

技术标签:

【中文标题】Java Cipher 解密中的奇怪字符【英文标题】:Java Cipher Strange chars in decryption 【发布时间】:2016-06-23 10:15:20 【问题描述】:

我的程序有一个奇怪的问题,我想加密一些字符串然后解密它们;我做了一个试用类来测试加密和解密的功能。加密工作正常,但是当我尝试解密时,只有有时,我在字符串中间有奇怪的字符。 这是我的代码:

public class Prova 

public static void main(String[] args)
    String s = "with the lights out is less dangerous here we are now entertain us";
    s = cripta(s);
    System.out.println(s);
    s = decripta(s);
    System.out.println(s);


public static String cripta(String s)
    System.out.println("lunghezza stringa:"+s.length());
    byte[] input = s.getBytes();
    byte[] output;
    byte[] keyBytes = hexStringToByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
    byte[] ivBytes = hexStringToByteArray("AAAAAAAAAAAAAAAA");
    String out = "";


    SecretKeySpec key = new SecretKeySpec(keyBytes, "DESede" );
    IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    try 
        Cipher cp = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cp.init(Cipher.ENCRYPT_MODE, key);
        byte[] criptati = new byte[cp.getOutputSize(input.length)];
        int enc_len = cp.update(input, 0, input.length, criptati, 0);
        enc_len += cp.doFinal(criptati, enc_len);
        out = new String(criptati);
     catch (NoSuchAlgorithmException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (NoSuchPaddingException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (InvalidKeyException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (ShortBufferException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (IllegalBlockSizeException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (BadPaddingException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

    return out;


public static String decripta(String s)

    byte[] input = s.getBytes();
    byte[] output;
    byte[] keyBytes = hexStringToByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
    byte[] ivBytes = hexStringToByteArray("AAAAAAAAAAAAAAAA");
    String out = "";

    try 
        SecretKeySpec key = new SecretKeySpec(keyBytes, "DESede");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        Cipher cp = Cipher.getInstance("DESede/ECB/NoPadding");
        cp.init(Cipher.DECRYPT_MODE,  key);
        byte[] decrypt = new byte[cp.getOutputSize(input.length)];

        int dec_len = cp.update(input, 0, input.length, decrypt, 0);
        System.out.println(dec_len);
        dec_len += cp.doFinal(decrypt, dec_len );
        System.out.println(dec_len);
        out = new String(decrypt);
     catch (NoSuchAlgorithmException | NoSuchPaddingException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (InvalidKeyException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (ShortBufferException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (IllegalBlockSizeException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (BadPaddingException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    
    return out;


private static byte[] hexStringToByteArray(String s) 
    // TODO Auto-generated method stub
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) 
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    
    return data;


我收到的输出是“熄灯后的 dangÝâ¥8,–xÖÆZŽÏö=æe 现在招待我们”

【问题讨论】:

String 不是二进制数据的容器。 【参考方案1】:

问题是加密字节可能包含一些值,这些值在简单地转换为字符串时会导致奇怪的行为。所以你应该像这样使用base64编码:

在密码中:

out = new String(Base64.getEncoder().encode(criptati));

简述:

byte[] input = Base64.getDecoder().decode(s.getBytes());

顺便问一下:你为什么用cp.update()?为什么不只是 cp.doFinal() 那样:

Cipher cp = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cp.init(Cipher.ENCRYPT_MODE, key);
byte[] criptati = cp.doFinal(input);
out = new String(Base64.getEncoder().encode(criptati));

decript 也一样?

编辑

删除所有杂乱(TODO-cmets、未使用的代码等)的工作示例:

public static void main(String[] args) 
        String s = "with the lights out is less dangerous here we are now entertain us";
        s = cripta(s);
        System.out.println(s);
        s = decripta(s);
        System.out.println(s);
    

    public static String cripta(String s) 
        System.out.println("lunghezza stringa:" + s.length());
        byte[] input = s.getBytes();
        byte[] keyBytes = hexStringToByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
        String out = "";

        SecretKeySpec key = new SecretKeySpec(keyBytes, "DESede");
        try 
            Cipher cp = Cipher.getInstance("DESede/ECB/PKCS5Padding");
            cp.init(Cipher.ENCRYPT_MODE, key);
            byte[] criptati = cp.doFinal(input);
            out = new String(Base64.getEncoder().encode(criptati));
         catch (NoSuchAlgorithmException e) 
            e.printStackTrace();
         catch (NoSuchPaddingException e) 
            e.printStackTrace();
         catch (InvalidKeyException e) 
            e.printStackTrace();
         catch (IllegalBlockSizeException e) 
            e.printStackTrace();
         catch (BadPaddingException e) 
            e.printStackTrace();
        

        return out;
    

    public static String decripta(String s) 

        byte[] input = Base64.getDecoder().decode(s.getBytes());
        byte[] keyBytes = hexStringToByteArray("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
        String out = "";

        try 
            SecretKeySpec key = new SecretKeySpec(keyBytes, "DESede");
            Cipher cp = Cipher.getInstance("DESede/ECB/NoPadding");
            cp.init(Cipher.DECRYPT_MODE, key);
            byte[] decrypt = cp.doFinal(input);
            out = new String(decrypt);
         catch (NoSuchAlgorithmException | NoSuchPaddingException e) 
            e.printStackTrace();
         catch (InvalidKeyException e) 
            e.printStackTrace();
         catch (IllegalBlockSizeException e) 
            e.printStackTrace();
         catch (BadPaddingException e) 
            e.printStackTrace();
        
        return out;
    

【讨论】:

现在我收到此错误:线程“main”java.lang.IllegalArgumentException 中的异常:非法 base64 字符 20 它工作,我使用你的解决方案出错了,现在它似乎工作了,非常感谢你的帮助!

以上是关于Java Cipher 解密中的奇怪字符的主要内容,如果未能解决你的问题,请参考以下文章

java 中的Cipher类RSA方式能不能用私钥加密公钥解密,完整解释下

ruby 实现java中的aes 加密解密

从Java中的node.js解密字符串?

Java Cipher类解密|笔记

Java Cipher类解密|笔记

Java Cipher类解密|笔记