您概述的方案等效于 CMS(标准底层 S/MIME)和 PGP;从根本上说,它是安全的。在 CMS 中,这种模式称为“密钥传输”。您还可以通过 DH 或 ECDH 等算法使用多方“密钥协议”。
唯一的问题是您为 AES 使用了选择不当的密钥。
我想不出任何理由使用包含非随机位的随机 UUID。只需使用 Java 密码体系结构的正常密钥生成机制。密钥、明文和密文都应表示为字节序列,除非您需要容纳一些仅容纳文本的外部存储或传输。
Iterable<Certificate> recipients = null;
KeyGenerator gen = KeyGenerator.getInstance("AES");
gen.init(256);
SecretKey contentEncryptionKey = gen.generateKey();
初始化 AES 密码并让提供者选择一个 IV。
Cipher contentCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
contentCipher.init(Cipher.ENCRYPT_MODE, contentEncryptionKey);
AlgorithmParameters params = contentCipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
对于每个收件人,初始化 RSA 密码并加密 AES 密钥。
Cipher keyEncryptionCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
for (Certificate recipient : recipients) {
keyEncryptionCipher.init(Cipher.WRAP_MODE, recipient);
byte[] encryptedKey = keyEncryptionCipher.wrap(contentEncryptionKey);
/* Store the encryptedKey with an identifier for the recipient... */
}
/* Store the IV... */
/* Encrypt the file... */
让用户选择并记住有效强度为 256 位的密码是不合理的。要获得这种强度,您必须随机选择密码,将它们编码为文本,并让用户将它们写在卡片上。如果您真的需要这么大的强度,您可以查看基于智能卡的解决方案来存储用户的 RSA 密钥。
我强烈建议您使用 CMS 库来存储您的文件。这将增加您使用的协议是安全的、您使用的代码经过更多审查以及其他工具、库和系统可以与加密消息互操作的机会。BouncyCastle 的 API 有点晦涩,但可能值得学习。
(我不记得 Java 5 是否支持“RSA/ECB/OAEPWithSHA-512AndMGF1Padding”;如果支持,您应该使用它而不是 PKCS1Padding。)