简体   繁体   English

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

[英]Encrypt a String, save it to DB, load it and decrypt it

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 [] soooo没有脚本可用...

Any ideas? 有任何想法吗?

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. 如果要将密钥存储为文本,则可能需要先对其进行base64编码。 You can then base64 decode the text back to the key. 然后,您可以将文本base64解码回密钥。

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()));
    }
}
String encrypted = new BASE64Encoder ().encodeBuffer ( encryptedBytes );            
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] recoveredBytes = cipher.doFinal( new BASE64Decoder ().decodeBuffer (  encrypted ) );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM