【发布时间】:2018-03-09 21:44:04
【问题描述】:
我正在编写一个用于传输文件的小型应用程序,或多或少是作为了解更多编程加密基础的一种方式。这个想法是生成一个 RSA 密钥对,交换公钥,然后发送 AES iv 和密钥以进行进一步解密。我想用接收者 RSA 公钥加密 AES 密钥,如下所示:
// encode the SecretKeySpec
private byte[] EncryptSecretKey ()
{
Cipher cipher = null;
byte[] key = null;
try
{
cipher = Cipher.getInstance("RSA/ECB/NOPADDING");
// contact.getPublicKey returns a public key of type Key
cipher.init(Cipher.ENCRYPT_MODE, contact.getPublicKey() );
// skey is the SecretKey used to encrypt the AES data
key = cipher.doFinal(skey.getEncoded());
}
catch(Exception e )
{
System.out.println ( "exception encoding key: " + e.getMessage() );
e.printStackTrace();
}
return key;
}
然后我将密钥值写给接收者,并像这样解密:
private SecretKey decryptAESKey(byte[] data )
{
SecretKey key = null;
PrivateKey privKey = null;
Cipher cipher = null;
System.out.println ( "Data as hex: " + utility.asHex(data) );
System.out.println ( "data length: " + data.length );
try
{
// assume this loads our private key
privKey = (PrivateKey)utility.loadLocalKey("private.key", false);
cipher = Cipher.getInstance("RSA/ECB/NOPADDING");
cipher.init(Cipher.DECRYPT_MODE, privKey );
key = new SecretKeySpec(cipher.doFinal(data), "AES");
System.out.println ( "Key decrypted, length is " + key.getEncoded().length );
System.out.println ( "data: " + utility.asHex(key.getEncoded()));
}
catch(Exception e)
{
System.out.println ( "exception decrypting the aes key: " + e.getMessage() );
e.printStackTrace();
return null;
}
return key;
}
在控制台的另一边,我得到这个作为输出:
read_bytes for key: 16
data length: 16
Data as hex: <hex string>
Key decrypted, length is 256
java.security.InvalidKeyException: Invalid AES key length: 256 bytes
此外,如果我创建一个大小为 16 的字节数组并将 cipher.doFinal(data) 输出放入其中,则该数组似乎已调整为 256 字节(至少 .length 是这样说的)。为什么会这样,更进一步,我做错了什么?
编辑
我解决了这个问题,并认为我会发布这个问题,以防有人遇到这个问题。事实证明,问题在于 RSA/ECB/NOPADDING。出于某种奇怪的原因,当我将 SecretKey 转移到客户端时,它搞砸了我的创建。 可能与我如何生成密钥对有关(我为此使用 getInstance("RSA")),但我并不完全确定。
【问题讨论】:
-
您好,请将您的完整答案作为答案发布,而不是在您的问题中进行编辑(您告诉我们问题出在哪里,而不是答案)。然后你可以在一段时间后接受你自己的答案。或者接受我的,这就解释了为什么你应该使用
"RSA/ECB/PKCS1Padding"而不是"RSA/ECB/NoPadding"... -
请注意,当您创建执行加密的在线协议时,您应该使用完整性保护(例如签名)。甚至 RSA 加密也可能适用于例如填充预言机攻击。没有完整性保护是一个常见错误,尽管如果您使用 PKCS#1 v1.5(由
"RSA/ECB/PKCS1Padding"暗示),此问题会受到限制。 -
作为旁注,ECB 很少是块密码的好模式。
-
据我了解,核心 javax.crypto 库不支持任何其他形式的分组密码,因此我有点坚持。
-
至少可以从 ECB 构建 CTR。你只需要小心创建一个好的随机数。但如果图书馆至少不支持 CBC 模式,我会感到惊讶。
标签: java security encryption