【问题标题】:java - get key from byte arrayjava - 从字节数组中获取密钥
【发布时间】:2012-12-15 20:40:26
【问题描述】:

我有一个使用随机生成的密钥加密文件内容的 java 程序。 该密钥使用 RSA 加密并保存到文本文件中。

现在,我有一个 java 程序,它给出了文件和存储 RSA 密钥的密钥库,需要先解密加密的密钥,然后用密钥解密文件。

这是我目前所拥有的:

// Fetch the other public key and decrypt the file encryption key
java.security.cert.Certificate cert2 = keystore.getCertificate("keyForSeckeyDecrypt");
Key secKeyPublicKey = cert2.getPublicKey();
Cipher cipher = Cipher.getInstance(secKeyPublicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, secKeyPublicKey);
keyFileFis = new FileInputStream(keyFile);
byte[] encryptedKey = new byte[128];
keyFileFis.read(encryptedKey);
byte[] realFileKey = cipher.doFinal(encryptedKey, 0, encryptedKey.length);
Key realKey = //  THE PROBLEM!!!;
keyFileFis.close();

简而言之,我从密钥文本文件中获取加密密钥并对其进行解密,现在我将解密后的密钥作为一个字节数组,我该如何再次将其设为 Key 变量?

我是这样生成密钥的:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
Key secKey = keyGen.generateKey();
cipher.init(Cipher.ENCRYPT_MODE, secKey);

并以这种方式加密:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
PrivateKey privateKey = kp.getPrivate();
Cipher keyCipher = Cipher.getInstance("RSA");
keyCipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] encryptedKey = keyCipher.doFinal(secKey.getEncoded());
FileOutputStream keyStream = new FileOutputStream("key.txt");
keyStream.write(encryptedKey);
keyStream.close();

【问题讨论】:

  • 您能分享一下您是如何生成存储在文件中的密钥的吗?算法?长度?
  • 只是为了确定!您使用“新生成的”RSA 私钥加密您的aes 密钥并将其保存到文件中。但是您希望使用密钥库中的公钥对其进行解密!这对我来说没有意义。您应该使用密钥库中的私钥来使其工作。
  • @Akdeniz,除了从密钥库解密之外,我的密钥是 RSA 公钥,所以我可以拥有 RSA 私钥,所以我可以解密我的 AES 密钥。使用 RSA 加密 AES 密钥是练习的要求之一,如果您有更好的设计方案,我很乐意听到 :)

标签: java public-key cryptoapi


【解决方案1】:

我还没有尝试过,但点击 API SecretKeySpec 可能就是您要找的。​​p>

SecretKeySpec(byte[] key, String algorithm)

它可用于从字节数组构造 SecretKey,而无需通过(基于提供者的)SecretKeyFactory。

此类仅对可以表示为字节数组且没有与其关联的密钥参数的原始密钥有用,例如 DES 或三重 DES 密钥。

【讨论】:

  • 我已经尝试过了,但是当我这样做并尝试使用此 SecretKeySpec 初始化密码时,我收到异常“没有安装的提供程序支持此密钥:javax.crypto.spec.SecretKeySpec "
  • @MichBoy 这是重新创建密钥的正确方法。问题可能是您的密钥大小错误。 AES 密钥将是 16、24 或 32 字节,而不是 128 字节。要使用超过 128 字节的密钥,您需要正确安装无限强度管辖策略文件。
【解决方案2】:

如果我做对了,这应该可以工作..

Key privateKey = keyStore.getKey("youralias", "password".toCharArray());
PublicKey publicKey = keyStore.getCertificate("youralias").getPublicKey();

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
Key secKey = keyGen.generateKey();

Cipher keyCipher = Cipher.getInstance("RSA");
keyCipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] encryptedKey = keyCipher.doFinal(secKey.getEncoded());

// Write & Read to/from file!

Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] decryptedKey = decryptCipher.doFinal(encryptedKey);

boolean equals = Arrays.equals(secKey.getEncoded(), new SecretKeySpec(decryptedKey, "AES").getEncoded());
System.out.println(equals?"Successfull!":"Failed!");

【讨论】:

  • 感谢您的努力,以下几点: a) 加密和解密属于两个不同的类别(即不同的程序),因此 secKey 在加密程序中,但在解密程序中没有。 b) 我的问题仍然没有解决,因为我需要一个密钥变量来解密原始文件。
  • 顺便说一句,由于某种原因,在尝试执行 decryptCipher.doFinal(encryptedKey) 部分时,我得到“Data mush start with a zero”异常,为什么?
  • 确保您可以准确读取写入该文件的内容。顺便说一句,这段代码只是一个概念证明,您可以使用SecretKeySpec 重新创建您的AES 密钥。如果您对上下文有疑问,请提出另一个问题,明确指出您的问题。
猜你喜欢
  • 2011-03-20
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
  • 2018-07-04
  • 2010-10-15
  • 2014-12-18
  • 2019-06-10
  • 2021-04-10
相关资源
最近更新 更多