我应该使用Cipher.WRAP_MODE或Cipher.ENCRYPT_MODE来加密会话密钥吗?

时间:2013-05-16 11:50:15

标签: java encryption jce

如何使用从服务器端传输的公钥加密客户端的会话密钥?

我应该使用Cipher.WRAP_MODE还是Cipher.ENCRYPT_MODE

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, publicKey);
byte[] wrappedSessionKey = cipher.wrap(sessionKey);

我不确定如何使用encrypt_mode加密sessionKey。有人可以帮我吗?

1 个答案:

答案 0 :(得分:18)

包装和加密非常相似,但包装更精确地表达了您打算做的事情。通用“加密”对原始数据进行操作而没有语义含义,而已知包装与密钥相关。因此Cipher.unwrap()方法返回Key而不是字节数组。

如果使用wrap进行密钥包装,则代码将更具可移植性(特别是硬件安全模块)。在某些情况下,密钥权限将允许包装操作,但不允许密钥字节的原始加密。

当然,由于整个JCE体系结构基于提供程序概念,因此您需要准确检查为所选提供程序指定的算法,以获取所需的输出格式。如果您将包装的密钥数据发送给第三方,这一点尤其重要。


在您的特定情况下,WRAPENCRYPT都会展示相同的行为,如下所示,我在其中交换结果:

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "SunJSSE");
generator.initialize(2048);
KeyPair keyPair = generator.generateKeyPair();

SecretKey sessionKey = new SecretKeySpec(new byte[16], "AES");

Cipher c = Cipher.getInstance("RSA", "SunJCE");
c.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] result1 = c.doFinal(sessionKey.getEncoded());

c.init(Cipher.WRAP_MODE, keyPair.getPublic());
byte[] result2 = c.wrap(sessionKey);

c.init(Cipher.UNWRAP_MODE, keyPair.getPrivate());
SecretKey sessionKey1 = (SecretKey) c.unwrap(result1, "AES",
    Cipher.SECRET_KEY);

c.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
SecretKey sessionKey2 = new SecretKeySpec(c.doFinal(result2), "AES");

System.out.println(Arrays.equals(sessionKey1.getEncoded(),
    sessionKey2.getEncoded()));

打印:true