java 加密字符串,将其保存到数据库,加载并解密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12803298/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 10:17:42  来源:igfitidea点击:

Encrypt a String, save it to DB, load it and decrypt it

javadatabaseencryption

提问by diminuta

I have to store in a DB table the connection details to another databases, I must encrypt the passwords to those DBs and one must be able to "manually" insert data into that table via SQL scripts...

我必须将与另一个数据库的连接详细信息存储在数据库表中,我必须加密这些数据库的密码,并且必须能够通过 SQL 脚本“手动”将数据插入该表中...

I need to encrypt and decrypt it because my app must be able to use those data and connect to other databases, so MD5 and similar are not useful..

我需要加密和解密它,因为我的应用程序必须能够使用这些数据并连接到其他数据库,所以 MD5 和类似的没有用..

I thought of Blowfish, AES, etc... but if I store the password as VARCHAR in the DB the decrypt part doesn't work... so I stored it as BYTE, but if I do so no one can write a script to pre-load data on the table..

我想到了 Blowfish、AES 等......但是如果我将密码存储为 VARCHAR 在数据库中解密部分不起作用......所以我将它存储为 BYTE,但如果我这样做没有人可以编写脚本在表上预加载数据..

Maybe I'm missing something here...

也许我在这里遗漏了一些东西......

Here's the code I used when the registry in the table was defined as VARCHAR:

这是我在表中的注册表定义为 VARCHAR 时使用的代码:

package main;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class Prueba {

    private static final String keyValue = "fd<[;.7e/OC0W!d|";
    private static final String ALG = "Blowfish";

    public static void main(String[] args) {
        String text = "some random text";

        try {
            SecretKeySpec key = new SecretKeySpec(keyValue.getBytes(), ALG);
            Cipher cipher = Cipher.getInstance(ALG);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptedBytes = cipher.doFinal(text.getBytes());
            String encrypted = new String(encryptedBytes);

            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] recoveredBytes = cipher.doFinal(encrypted.getBytes());
            String recovered = new String(recoveredBytes);

        } catch (NoSuchAlgorithmException nsa) {
            nsa.printStackTrace();
        } catch (NoSuchPaddingException nspe) {
            nspe.printStackTrace();
        } catch (InvalidKeyException ike) {
            ike.printStackTrace();
        } catch (BadPaddingException bpe) {
            bpe.printStackTrace();
        } catch (IllegalBlockSizeException ibse) {
            ibse.printStackTrace();
        } 
    }


}

And I get the exception:

我得到了例外:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
    at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA12275)
    at javax.crypto.Cipher.doFinal(DashoA12275)
    at main.Prueba.main(Prueba.java:30)

If instead of:

如果不是:

byte[] recoveredBytes = cipher.doFinal(encrypted.getBytes());

I do

我做

byte[] recoveredBytes = cipher.doFinal(encryptedBytes);

I get no exception, but then I must store the password as byte[] soooo no script posible...

我也不例外,但是我必须将密码存储为 byte[] 所以没有可能的脚本......

Any ideas?

有任何想法吗?

采纳答案by diminuta

In the end, as maerics suggested, I solved it this way:

最后,正如 maerics 建议的那样,我是这样解决的:

import org.apache.commons.net.util.Base64;

public class MyCrypto {

    /**
     * Codifica un texto usando Base64.
     * @param texto <code>String</code> texto a codificar.
     * @return <code>String</code> texto codificado.
     */
    public static String encrypt(String texto) {
        return new String(Base64.encodeBase64(texto.getBytes()));
    }

    /**
     * Decodifica un texto usando Base64.
     * @param texto <code>String</code> texto a decodificar.
     * @return <code>String</code> texto decodificado.
     */
    public static String decrypt(String texto) {
        return new String(Base64.decodeBase64(texto.getBytes()));
    }
}

回答by Qwerky

It seems like when you store the key as bytes something somewhere is interpreting it incorrectly. It could be a character encoding problem.

当您将密钥存储为字节时,似乎某处会错误地解释它。可能是字符编码问题。

If you want to store the key as text you might want to base64 encode it first. You can then base64 decode the text back to the key.

如果要将密钥存储为文本,则可能需要先对其进行 base64 编码。然后,您可以通过 base64 将文本解码回密钥。

回答by drvijayy2k2

String encrypted = new BASE64Encoder ().encodeBuffer ( encryptedBytes );            
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] recoveredBytes = cipher.doFinal( new BASE64Decoder ().decodeBuffer (  encrypted ) );