如何使用从服务器端传输的公钥加密客户端的会话密钥?
我应该使用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。有人可以帮我吗?
答案 0 :(得分:18)
包装和加密非常相似,但包装更精确地表达了您打算做的事情。通用“加密”对原始数据进行操作而没有语义含义,而已知包装与密钥相关。因此Cipher.unwrap()
方法返回Key
而不是字节数组。
如果使用wrap进行密钥包装,则代码将更具可移植性(特别是硬件安全模块)。在某些情况下,密钥权限将允许包装操作,但不允许密钥字节的原始加密。
当然,由于整个JCE体系结构基于提供程序概念,因此您需要准确检查为所选提供程序指定的算法,以获取所需的输出格式。如果您将包装的密钥数据发送给第三方,这一点尤其重要。
在您的特定情况下,WRAP
和ENCRYPT
都会展示相同的行为,如下所示,我在其中交换结果:
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