解密方法返回null

时间:2014-04-04 20:01:06

标签: java encryption cryptography

我有这个加密课程。

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Crypto
{
    public Crypto(){

    }

    public static void main(String args[]){
        Crypto crypto = new Crypto();
        byte encrypted[] = crypto.encrypt("test encryption");
        System.out.println(encrypted);
        String decrypted = crypto.decrypt(encrypted);
        System.out.println(decrypted);

    }

    public byte[] encrypt(String input){
        try{
            Crypto crypto = new Crypto();
            SecretKeySpec key = crypto.hashPhrase();
            Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aes.init(Cipher.ENCRYPT_MODE, key);
            return aes.doFinal(input.getBytes());
        }
        catch(Exception e){
            return null;
        }
    }

    public SecretKeySpec hashPhrase(){
        try{
            String code = "some code";
            MessageDigest digest = MessageDigest.getInstance("SHA");
            digest.update(code.getBytes());
            return new SecretKeySpec(digest.digest(), 0, 16, "AES");
        }
        catch(Exception e){
            return null;
        }
    }

    public String decrypt(byte[] input){
        try{
            Crypto crypto = new Crypto();
            SecretKeySpec key = crypto.hashPhrase();
            Cipher aes = Cipher.getInstance("AES/ECB/PKCS5Padding");
            aes.init(Cipher.DECRYPT_MODE, key);
            return new String(aes.doFinal(input));
        }
        catch(Exception e){
            return null;
        }
    }
}

当我在这个课程中运行main时,它运行正常。我看到一个加密值,然后在调用decrypt方法后,我看到原始输入 - "测试加密。"

然而,当我尝试实际使用解密方法时,我遇到了问题。我稍微缩短了这一课程,只展示了相关部分。

public void read() throws java.io.IOException{
    Crypto crypto = new Crypto();
    byte[] input;
    BufferedReader in = new BufferedReader(new FileReader("C:\\Budget\\data.txt")); 
    while(in.ready()) {
        input = in.readLine().getBytes();
        BudgetInterface.list.add(crypto.decrypt(input)); //ArrayList of Objects
        System.out.println(crypto.decrypt(input));
        //BudgetInterface.list.add(in.readLine()); - artifact from version without cryptographic capability
    }
    in.close();
}

BudgetInterface.list是一个对象的ArrayList,如上所述,我试图将解密版本的输入添加到数组中,但是crypto.decrypt(输入)正在为文件中的每一行返回。如果我删除了加密元素,它可以从文件中读取行没有问题。如果我不尝试解密,它也会读得很好。为什么decrypt方法在这个方法中返回null,而不是在Crypto类的main方法中?

编辑:获取堆栈跟踪后我得到的错误是javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher 我理解这是在说什么,但是为什么只有当我从文件中获取加密内容时才会发生这种情况?我从文件中读取的字节数组和我在Crypto中从主方法获取的字节数组长度相同。

2 个答案:

答案 0 :(得分:1)

除了其他所有内容之外,您在此处遇到的最多基本问题是您只是使用平台默认编码将二进制数据转换为字符串,就像它&# 39; s实际上只是文字。它不是 - 它的二进制数据。

如果你想要每个加密输入一行文本,那很好 - 但是你需要将二进制数据转换为base64或类似的文本。永远不会永远处理任意二进制数据(加密数据,压缩数据,图像数据,音乐数据......基本上不是文本),就好像它只是编码文本一样。即使您执行已编码文本,也请明确指定编码。

修复此问题 - 并停止使用BufferedReader.ready(),更愿意致电readLine()并在其返回null时终止 - 并且您将处于更好的位置。当然也要修复异常处理。

有关诊断此类问题的详细信息,请参阅我的blog post about reversible transformations;有关IO错误的更多信息,请参阅Marc Gravell's post about IO

答案 1 :(得分:0)

看看你的解密方法在做什么:

    catch(Exception e){
        return null;
    }

如果你不能处理异常,你就不应该抓住它。 或者至少 ,您应该打印异常的堆栈跟踪:

    catch(Exception e){
        e.printStackTrace();
    }