2

在我基于 Java 的网络应用程序中,我想在将某些数据写入数据库之前对其进行加密,并在加载回内存后对其进行解密。为此,我使用了bouncycastle API 并创建了一个如下所示的类:

public class BlowfishEnrypter implements IEncrypter {

    /*--- Members ---*/

    private BufferedBlockCipher cipher;
    private KeyParameter key;

    /*--- Constructors ---*/

    /**
     * Initialize the cryptographic engine. The key array should be at least 8
     * bytes long.
     * 
     * @param key
     */
    public BlowfishEnrypter(byte[] key) {
    cipher = new BufferedBlockCipher(new CBCBlockCipher(new BlowfishEngine()));
    this.key = new KeyParameter(key);
    }

    /**
     * Initialize the cryptographic engine. The key array should be at least 8
     * bytes long.
     * 
     * @param key
     */
    public BlowfishEnrypter(String key) {
    this(key.getBytes());
    }

    /*--- Public ---*/

    /**
     * {@inheritDoc}
     */
    public String encrypt(String input) throws EncryptionException {
    if (StringUtils.hasText(input)) {
        byte[] bytes = Hex.decode(input);
        try {
        return new String(encrypt(bytes));
        } catch (CryptoException e) {
        throw new EncryptionException("Error occured while trying to encrypt", e);
        }
    } else {
        throw new EncryptionException("Illegal argument for encryption: " + input);
    }
    }

    /**
     * {@inheritDoc}
     */
    public String decrypt(String input) throws EncryptionException {
    if (StringUtils.hasText(input)) {
        byte[] bytes = Hex.decode(input);
        try {
        return new String(decrypt(bytes));
        } catch (CryptoException e) {
        throw new EncryptionException("Error occured while trying to decrypt", e);
        }
    } else {
        throw new EncryptionException("Illegal argument for decryption: " + input);
    }
    }

    /*--- Private ---*/

    /**
     * Encrypt arbitrary byte array, returning the encrypted data in a different
     * byte array.
     * 
     * @param data
     * @return Encrypted byte array
     * @throws CryptoException
     */
    private synchronized byte[] encrypt(byte[] data) throws CryptoException {
    if (data == null || data.length == 0) {
        return new byte[0];
    }

    cipher.init(true, key);
    return callCipher(data);
    }

    /**
     * Decrypts arbitrary data
     * 
     * @param data
     *            To decrypts
     * @return Decrypted byte array
     * @throws CryptoException
     */
    private synchronized byte[] decrypt(byte[] data) throws CryptoException {
    if (data == null || data.length == 0) {
        return new byte[0];
    }

    cipher.init(false, key);
    return callCipher(data);
    }

    /**
     * Private routine that does the gritty work.
     * 
     * @param data
     *            Data to operate on
     * @return Processed byte array
     * @throws CryptoException
     */
    private byte[] callCipher(byte[] data) throws CryptoException {
    int size = cipher.getOutputSize(data.length);
    byte[] result = new byte[size];
    int olen = cipher.processBytes(data, 0, data.length, result, 0);
    olen += cipher.doFinal(result, olen);

    if (olen < size) {
        byte[] tmp = new byte[olen];
        System.arraycopy(result, 0, tmp, 0, olen);
        result = tmp;
    }

    return result;
    }
}

到目前为止一切都很好(我想是的,如果你对这门课有任何意见,请继续)。要初始化这个类,我应该提供一个密钥。我的问题是 - 我应该如何管理这个密钥?

更具体:

  • 我应该使用特定技术创建它吗?
  • 我应该把它存放在哪里?在属性文件中?在数据库中?在我的代码中的某个地方?
  • 这个密钥(我们在这里谈论的是一个字符串,对吗?)是否应该加密,然后在加载或使用后解密?如果是这样,我该怎么做?
4

2 回答 2

1

取决于很多事情:

  1. 您的代码是否存储在其他人无法查看/访问的安全位置?如果是这样,我会把它放在代码中。
  2. 您是否设想不时更改密钥(这种方式更安全)?如果是这样并且第 1 点仍然成立,则将其粘贴到属性文件中。
  3. 否则将其放入数据库并保持数据库的用户名/密码保密!

不确定为什么要加密实际密钥,因为您将密钥放在哪里来保护原始密钥?

不过,更好的做法是查看Java SE 安全性,看看 Java Keystore 等可以为您做什么。此外,您还可以阅读bouncy castle网站上的资源,这可能会有所帮助。

于 2012-09-18T08:28:15.443 回答
1

我们为许多网络应用程序使用了类似的加密。通常,密钥作为字符串保存在源代码的属性文件中。密钥未加密,它是一个带有特殊字符和其他字符串组合的字符串,只是为了使其更强大(数字、大写字母等)。一旦上线,业务用户通常每 6 个月更改一次密钥。

于 2012-09-18T08:48:14.807 回答