【问题标题】:Problem with java Cipher when i want to decipher it当我想破译它时出现java Cipher的问题
【发布时间】:2018-08-31 17:21:02
【问题描述】:

我用 javafx 制作了一个应用程序,我可以写一些东西并将其保存到数据库中。我的数据库是 sqlite。这是一个非常简单的应用程序。虽然我已经在我的写作应用程序中添加了登录应用程序,但仍然可以通过任何软件打开 sqlite。 而不是加密sqlite db(我不知道,我发现这样做真的很混乱:))我决定在java中加密文本,然后当我想阅读它时,我会将它恢复正常并显示它。

我从this link 学到了如何做到这一点,我将其更改为打印字符串而不是写入文件 所以我的最终代码如下所示:

public static void main(String[] args) throws Exception {

    String textA = "";
    String textB="";

    byte[] thisismykey = "Hello How manyBytes are in@hts A".getBytes();
    SecretKey secKey = new SecretKeySpec(thisismykey, "AES");


    Cipher aesCipher = Cipher.getInstance("AES");

    //turn your original text to byte
    byte[] myoriginaltexttobyte = "Your Plain Text Here".getBytes();
    //activate the encrypt method
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    //encrypt the text and assign the encrypted text to a byte array
    byte[] bytecipheredoforgtext = aesCipher.doFinal(myoriginaltexttobyte);
    //change it to string with new string
    textA = new String(bytecipheredoforgtext);
    System.out.println(textA);

    //get the bytes of encrypted text and assign it to a byte array
    byte[] byteofencryptedtext = textA.getBytes();
    //activate the decrypt mode of the cipher
    aesCipher.init(Cipher.DECRYPT_MODE, secKey);
    //decrypt the encrypted text and assign it to a byte array
    byte[] byteofencryptedbacktonormaltext = aesCipher.doFinal(byteofencryptedtext);
    //change it to string with new string
    textB = new String(byteofencryptedbacktonormaltext);
    System.out.println(textB);
}

现在加密和解密使用相同的方法,它可以完美地工作,但我想将它更改为具有不同方法的类,这样我就可以用一种方法加密文本并用另一种方法解密。但是当我将事物分开时,解密效果不佳。加密工作良好。这是现在的代码:

public class CipherFinalB {

//from https://stackoverflow.com/questions/20796042/aes-encryption-and-decryption-with-java/20796446#20796446
private final byte[] thisismykey;
private final SecretKey secKey;
private final Cipher aesCipher;
public CipherFinalB() throws NoSuchPaddingException, NoSuchAlgorithmException {
    thisismykey = "HellodHowfmanyBytesgarehin@htseA".getBytes();
    secKey = new SecretKeySpec(thisismykey, "AES");

    aesCipher = Cipher.getInstance("AES");

}public String encrypt (String originaltext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] myoriginaltexttobyte =originaltext.getBytes();
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    byte[] bytecipheredoforgtext = aesCipher.doFinal(myoriginaltexttobyte);
    String textA = new String(bytecipheredoforgtext);
    System.out.println(textA);
    return new String(bytecipheredoforgtext);
}

public String decrypt (String encryptedtext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] byteofencryptedtext = encryptedtext.getBytes();
    aesCipher.init(Cipher.DECRYPT_MODE, secKey);
    byte[] byteofencryptedbacktonormaltext = aesCipher.doFinal(byteofencryptedtext);
    return new String(byteofencryptedbacktonormaltext);
}

}

当我使用加密方法时,它会返回一个字符串。当我将相同的字符串发送到解密方法时它不起作用并给我以下错误:

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
    at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
    at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2191)
    at main.CipherFinalB.decrypt(CipherFinalB.java:66)
    at main.CipherTest.main(CipherTest.java:16)

我该怎么办?

更新答案:

正如@Juan 所说,问题是“当数据被加密时,数组中可能有任何字节,而不仅仅是可打印的字符。”所以我改变了方法,为加密方法和解密方法返回字节。解密方法现在将字节作为参数而不是字符串,现在一切正常。

更新后的代码如下所示:

 public byte[] encrypt (String originaltext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] myoriginaltexttobyte =originaltext.getBytes();
    aesCipher.init(Cipher.ENCRYPT_MODE, secKey);
    byte[] bytecipheredoforgtext = aesCipher.doFinal(myoriginaltexttobyte);
    String textA = new String(bytecipheredoforgtext);
    System.out.println(textA);
    return bytecipheredoforgtext;
}

public byte[] decrypt (byte[] encryptedtext) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] byteofencryptedtext = encryptedtext;
    aesCipher.init(Cipher.DECRYPT_MODE, secKey);
    byte[] byteofencryptedbacktonormaltext = aesCipher.doFinal(byteofencryptedtext);
    return byteofencryptedbacktonormaltext;
}

【问题讨论】:

    标签: java encryption aes


    【解决方案1】:

    我不确定错误是由这个引起的,但是您正在执行的 String 和 byte[] 之间的转换可能适用于字符集范围内的字节,但是当数据被加密时,您可能在数组中有任何字节,不仅仅是可打印的字符。

    在您获得带有加密文本的 byte[] 后,将其编码为 Base64 并存储字符串表示形式。

    解密时先将Base64解码成byte[],再解密。

    See Base64 class

    【讨论】:

    • 非常感谢。我读了 Base64 但问题是它说“编码器没有添加任何换行符(行分隔符)”,因为我要从 javafx textarea 获取数据然后再次显示它,所以我需要行分隔符。但正如您所说,问题是“当数据被加密时,您可能在数组中有任何字节,而不仅仅是可打印的字符。”所以现在我没有返回字符串,而是将其更改为返回字节,然后我自己将其转换为字符串。非常感谢
    • 据您所知,我不认为它不会编码规范和换行符,它可能会说编码的文本没有空格和换行符。这不是问题,因为您将只存储编码文本。解码后,空格和换行符会回到那里。
    • 哦,我明白了。非常感谢您的解释
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2019-10-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2012-06-26
    • 2022-11-01
    • 2010-09-25
    相关资源
    最近更新 更多