在Java中使用AES 256加密RSA私钥

在Java中使用AES 256加密RSA私钥,java,encryption,aes,rsa,private-key,Java,Encryption,Aes,Rsa,Private Key,我正在用Java编写一个安全的文件共享应用程序。总体架构如下所示: 用户希望加密文件以在多个用户之间安全共享 应用程序在客户端上生成一个随机UUID,并将其用作AES 256密码,然后使用UUID对数据进行加密 然后使用每个人的公钥对UUID进行RSA加密。每个共享用户一次 每个加密的UUID数据包作为文件的一部分存储在自定义文件头中 然后将文件上载到其他人可以访问的服务器 用户可以使用各自的私钥读取AES加密密钥并解密文件 这是陷阱。用户的私钥必须加密并存储在数据库中的服务器上,以便可以从多个

我正在用Java编写一个安全的文件共享应用程序。总体架构如下所示:

  • 用户希望加密文件以在多个用户之间安全共享
  • 应用程序在客户端上生成一个随机UUID,并将其用作AES 256密码,然后使用UUID对数据进行加密
  • 然后使用每个人的公钥对UUID进行RSA加密。每个共享用户一次
  • 每个加密的UUID数据包作为文件的一部分存储在自定义文件头中
  • 然后将文件上载到其他人可以访问的服务器
  • 用户可以使用各自的私钥读取AES加密密钥并解密文件
  • 这是陷阱。用户的私钥必须加密并存储在数据库中的服务器上,以便可以从多个位置访问文件。在将私钥上载到服务器之前,将在客户端上使用用户选择的密码对其进行加密

    我想使用AES 256位加密来实现这一点。我希望在不依赖BouncyCastle库或任何第三方库的情况下完成整个工作。它需要使用标准的Java5库,这就是为什么我选择使用AES256加密和RSA,而不是PGP之类的东西

    任何人都能发现这种方法有什么内在的不安全之处,或者想出一种更有效的方法来做到这一点吗

    编辑:


    好的,我正在更新这个问题,因为我得到的所有答案都表明我没有将私钥传输到服务器。我之所以需要服务器上的私钥,是因为用户需要能够从多个客户端和多个位置(即:他们的iphone、ipad、工作笔记本电脑和家用电脑)访问他们的数据。他们不希望必须在设备之间管理和复制他们的密钥,这比将密钥存储在我们的服务器上更不安全,因为他们最终会通过电子邮件将密钥发送给自己。

    这方面的最大问题是使用UUID。虽然UUID(某种程度上)保证是唯一的,但它们包含的很多内容都是可预测的;在一台机器上生成的所有UUID中,大量的UUID保持不变。因此,如果一个人能够访问(例如)自己的钥匙,他们可能很容易猜到其他人的钥匙

    另一个问题是在服务器上存储用户的私钥。这使得整个方案的其余部分相对脆弱,因为访问这些密钥显然会访问所有其余的数据。它还(显然)意味着您通常会在服务器上解密数据,因此当用户通过网络访问该数据时,它要么需要重新加密以便传输,要么需要在用户的机器上解密,否则您将以明文形式传输数据(从而使大多数加密无效)

    编辑:至于我认为我应该怎么做:

    我在服务器上有一个公钥列表。当客户机希望与其他客户机共享文件时,它会从服务器获取这些客户机的公钥。然后它生成一个安全的随机密钥,并用该密钥加密数据。然后,它用所有其他客户端的公钥加密随机密钥,这些客户端应该能够访问数据。将它们放在一个流中,并将它们传输到服务器。然后,其他客户端可以下载流,用它们的私钥解密密钥,并使用该密钥解密数据本身

    这意味着每个客户机的私钥都是真正私有的——它永远不必以任何形式离开他们的机器。他们必须与世界其他地方共享的只是他们的公钥(根据定义,公钥不应该引起安全问题)

    因此,两条明显的攻击线分别针对随机数生成器和RSA本身。对于随机数生成器,我会使用Java的SecureRandom——这正是它想要达到的目的,如果内存可用,那么它已经被非常仔细地检查过了,与之发生重大冲突的可能性似乎非常小

    我不会试图评论RSA本身的安全性。现在,我认为您主要关心的是协议,而不是加密算法本身。只需说一句,如果RSA被严重破坏,您显然需要更改代码,但您会有很多公司

    这样,客户机就可以安全地存储他们的私钥。我喜欢用智能卡做那份工作,但有很多选择。从服务器和协议的角度来看,它不再是一个真正的因素

    编辑2:对于处理多个设备,我认为我应该简单地将每个设备视为一个单独的用户,拥有自己的公钥/私钥对。然后,我(可能)根据实际用户将它们分组,这样我就可以很容易地选择“Joe Blow”让他访问所有设备——但通过分层显示,我也可以很容易地限制对其中一个子集的访问,因此如果我想在Joe的办公机器上与他共享,但它足够敏感,我不想让它去有人可能会回头看,而他看着它,我也可以很容易地做到这一点

    这使用户的生活变得简单,但保留了相同的基本安全模型(即私钥保持私密)。

    这取决于您希望加密的“安全性”。显然,RSA是PKI的良好文档/公认标准。这就是说,无论何时提供明文和加密文本,黑客都可以更容易地解密明文中已知部分的密文。在这里,你正是这样做的。尽管您仅传输加密的UUID,但通过使用多个密钥加密相同的明文,攻击者可以深入了解有效负载。此外,如果
    Iterable<Certificate> recipients = null;
    KeyGenerator gen = KeyGenerator.getInstance("AES");
    gen.init(256);
    SecretKey contentEncryptionKey = gen.generateKey();
    
    Cipher contentCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    contentCipher.init(Cipher.ENCRYPT_MODE, contentEncryptionKey);
    AlgorithmParameters params = contentCipher.getParameters();
    byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
    
    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... */