AES秘密键在应用程序开始时丢失

发布于 2025-01-24 02:49:34 字数 2165 浏览 2 评论 0原文

我正在使用AES加密,并已加密了一条消息,并使用键源生成器生成的键进行了加密。加密和解密正常工作。 但是,当应用程序重新启动并且我试图再次解密相同的消息时,它会出现错误。

无法调用javax.crypto.cipher.getiv(),因为AES.EncryptionCipher为null。

我不想将秘密密钥存储在数据库中。我可以将SecretKey存储并将其写入文件中,并将该文件放在SRC/MAIN/RESOSDER文件夹中。这是一种很好的方法吗?

是否还有其他地方可以存储秘密钥匙,在解密Meesages时,我可以从该位置和解密消息加载钥匙。

这是我到目前为止所做的。

private static SecretKey key;
private static int KEY_SIZE = 128;
private static int T_LEN = 128;
private static Cipher encryptionCipher;


public static String encrypt(String message) {
    byte[] messageInBytes = message.getBytes();
    byte[] encryptedBytes = null;
    try {
        KeyGenerator generator = KeyGenerator.getInstance("AES");       
        generator.init(KEY_SIZE);
        key = generator.generateKey();
        encryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
        encryptionCipher.init(Cipher.ENCRYPT_MODE, key);
        encryptedBytes = encryptionCipher.doFinal(messageInBytes);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        e.printStackTrace();
    }
    catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
        e.printStackTrace();
    }
    return encode(encryptedBytes);

}

public static String decrypt(String encryptedMessage) {
    byte[] messageInBytes = decode(encryptedMessage);
    byte[] decryptedBytes = null;
    try {
        Cipher decryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(T_LEN, encryptionCipher.getIV());
        decryptionCipher.init(Cipher.DECRYPT_MODE, key, spec);
        decryptedBytes = decryptionCipher.doFinal(messageInBytes);
    } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
        e.printStackTrace();
    }
    return new String(decryptedBytes);

}

private static String encode(byte[] data) {
    return Base64.getEncoder().encodeToString(data);
}


private static byte[] decode(String data) {
    return Base64.getDecoder().decode(data);
}

I am using AES encryption and have encrypted a message with a key generated from key generator. Encryption and Decryption is working as expected.
But when the application is restarted and I am trying to decrypt the same message again, it is giving error as the secret key is not stored anywhere which was used to encrypt the message and on restart of application we don't have that secret key anymore.

Cannot invoke javax.crypto.Cipher.getIV() because AES.encryptionCipher is null.

I don't want to store the secret key in database. Can I store the secretKey and write it in a file and place that file in src/main/resources folder.Will it be a good approach?

Is there any other place where I could store the secret key and at the time of decrypting the meesages I could load the key from that place and decrypt messages.

This is what I have done so far.

private static SecretKey key;
private static int KEY_SIZE = 128;
private static int T_LEN = 128;
private static Cipher encryptionCipher;


public static String encrypt(String message) {
    byte[] messageInBytes = message.getBytes();
    byte[] encryptedBytes = null;
    try {
        KeyGenerator generator = KeyGenerator.getInstance("AES");       
        generator.init(KEY_SIZE);
        key = generator.generateKey();
        encryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
        encryptionCipher.init(Cipher.ENCRYPT_MODE, key);
        encryptedBytes = encryptionCipher.doFinal(messageInBytes);
    } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
        e.printStackTrace();
    }
    catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
        e.printStackTrace();
    }
    return encode(encryptedBytes);

}

public static String decrypt(String encryptedMessage) {
    byte[] messageInBytes = decode(encryptedMessage);
    byte[] decryptedBytes = null;
    try {
        Cipher decryptionCipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec spec = new GCMParameterSpec(T_LEN, encryptionCipher.getIV());
        decryptionCipher.init(Cipher.DECRYPT_MODE, key, spec);
        decryptedBytes = decryptionCipher.doFinal(messageInBytes);
    } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeyException e) {
        e.printStackTrace();
    }
    return new String(decryptedBytes);

}

private static String encode(byte[] data) {
    return Base64.getEncoder().encodeToString(data);
}


private static byte[] decode(String data) {
    return Base64.getDecoder().decode(data);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无人问我粥可暖 2025-01-31 02:49:34

我有类似的情况,仍然有一些开放的部分。建议的解决方案解决了一些问题,但仍然存在一些空旷的问题,希望我们可以与专家投入一起使用共同的方法。

要生成秘密密钥的键盘

keytool -genseckey  -alias aeskey -keyalg AES -keysize 128  -keypass password -keystore project.keystore -storetype pkcs12
  

请参阅oracle 文档

  • Java提供标准Java密钥店(JKS),秘密密钥可以在启动应用程序之前存储在JKS文件中,并且可以在RESTART上再次读取此文件。

  • jks还需要密码来访问,在这种方法中,挑战是如何安全地保持java键盘密码

  • 我的建议是密钥库密码可以安全地保存在kubernetes(例如其他建议)中的新平台上(任何其他建议?)

参考源代码之类的新平台中,以从Java KeyStore检索秘密密钥:

    KeyStore ks = KeyStore.getInstance("pkcs12");
    String keyStorePassword = appSecurityConfig.getJksPass(); //get keystore password from external configuration, like kubernetes secret
       //appSecurityConfig is configuration class
    char [] password = keyStorePassword.toCharArray();

    ks.load(new FileInputStream(appSecurityConfig.getKeystoreFile()), password);    //keystoreFile -> JKS file name
    
    SecretKey secretKey = (SecretKey) ks.getKey("kskey", password); //kskey -> is secreykey alias

I had similar situation, still have some open part. Suggested solution solve some, but still there are some open question, hopefully we can have common approach with expert inputs.

Keytool to generate Secret Key

keytool -genseckey  -alias aeskey -keyalg AES -keysize 128  -keypass password -keystore project.keystore -storetype pkcs12
  

refer the Oracle documentation for details.

  • Java provide standard Java keystore(JKS), Secret key can be stored in jks file before starting application and this file can be read again on restart.

  • JKS also need password to access, in this approach, challenge is how to keep java keystore password securely

  • my suggestion is keystore password can be saved securely in new platform like kubernetes ( any other suggestion?)

Reference source code to retrieve Secret Key from Java Keystore:

    KeyStore ks = KeyStore.getInstance("pkcs12");
    String keyStorePassword = appSecurityConfig.getJksPass(); //get keystore password from external configuration, like kubernetes secret
       //appSecurityConfig is configuration class
    char [] password = keyStorePassword.toCharArray();

    ks.load(new FileInputStream(appSecurityConfig.getKeystoreFile()), password);    //keystoreFile -> JKS file name
    
    SecretKey secretKey = (SecretKey) ks.getKey("kskey", password); //kskey -> is secreykey alias
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文