如何在Java中生成一次密钥并将该密钥用于两个不同的程序?

5
我的目标是编写一个Java程序,使用AES算法加密文本文件(密文)。然后,编写另一个程序来解密该加密文件(密文)以获取明文。我想在加密和解密过程中使用相同的密钥(同一密钥,生成一次,保存在某个地方,并在加密和解密程序中使用)。如果我在同一个程序中生成密钥并逐行进行加密和解密,则它可以完美地工作。以下是该功能的代码片段:
        String strDataToEncrypt = new String();
        String strCipherText = new String();
        String strDecryptedText = new String();

        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(128);
        SecretKey secretKey = keyGen.generateKey();

        Cipher aesCipher = Cipher.getInstance("AES");
        aesCipher.init(Cipher.ENCRYPT_MODE,secretKey);

        strDataToEncrypt = "any text input";
        byte[] byteDataToEncrypt = strDataToEncrypt.getBytes();
        byte[] byteCipherText = aesCipher.doFinal(byteDataToEncrypt); 
        strCipherText = new BASE64Encoder().encode(byteCipherText);
        System.out.println("cipher text: " +strCipherText);
        aesCipher.init(Cipher.DECRYPT_MODE,secretKey,aesCipher.getParameters());
        byte[] byteDecryptedText = aesCipher.doFinal(new BASE64Decoder().decodeBuffer(strCipherText));
        strDecryptedText = new String(byteDecryptedText);
        System.out.println("plain text again: " +strDecryptedText);

但是,我需要有两个不同的程序(Java文件)用于加密和解密。因此,我必须以某种方式生成一个密钥并将其保存在某个地方。然后在加密和解密程序中使用相同的密钥。我该怎么做?

编辑_1

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
byte[] encoded = secretKey.getEncoded(); 
System.out.println("key: "+encoded);// key: [B@52b2a2d8

我可以使用上述程序获取编码的密钥值。但我的问题是如何在我的解密程序中使用此值生成SecretKey?

1
你已经生成了一个密钥,为什么不将其写入文件,然后在第二个程序中读取呢? - Jim Garrison
@JimGarrison请查看我的编辑。 - K M Rakibul Islam
关键是一个 byte[] ,系统使用 Object#toString(),它只写出内部标识。你需要将各个 byte 值写入文件中,也可以先将其转换为十六进制。 - Jim Garrison
2个回答

18

如果我误解了您的问题,请原谅,但我认为您希望从现有的字节数组编码的密钥重构一个SecretKey对象。

这可以通过使用javax.crypto.spec.SecretKeySpec的构造函数来简单地执行,如下所示:

byte[] encoded = //Key data

SecretKey secretKey = new SecretKeySpec(encoded, "AES");

由于SecretKeySpecSecretKey的子类,不需要强制转换。 如果您的加密/解密算法更改,请确保将构造函数AES中使用的字符串文字更改为您决定在未来使用的任何算法。


1
谢谢,我使用Base64Coder将密钥转换为十六进制字符串并保存到首选项中,然后检索密钥并使用Base64Coder对其进行解码,它完美地运行。 - Diljeet

1
这里有一种打印十六进制值的 byte[] 数组的方法:

只需按照以下格式:

byte[] a = {-120, 17, 42,121};
for (byte b : a)
{
    System.out.printf("%2X",b);
}
System.out.println();

我也可以使用Arrays.toString(byte[])来获取字节数组的内容。但是,我不确定如何使用这个值来初始化SecretKey。还在深入研究中。 - K M Rakibul Islam
如果您使用 Arrays.toString(byte[]),则会进行字节到字符的编码转换,这可能是不可逆的。 - Jim Garrison
Arrays.toString(byte[]) 的定义是生成一个标准的数组表示形式,这个表示形式很不可能改变。然而,我同意它绝对不是为此目的而设计的最佳选择。@KeenLearner 如果您需要将密钥表示为ASCII码,请考虑使用十六进制或Base64编码,并记住文件可能包含二进制数据。 - ntoskrnl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接