2016-05-05 96 views
2

我正在为将发送电子邮件的服务器编写模块。在客户端应用程序中,用户可以添加多个收件人,每个收件人都有自己的公钥。我想要使​​用多个密钥来加密附件。例如,如果我添加3个收件人,则应使用3个不同的公钥对附件进行加密。我使用弹性城堡来做到这一点,但它仅适用于加密过程中的第一个公钥。我的意思是,只有第一个人可以使用自己的私钥进行解密,其余部分不起作用。 我的添加方法为每个键看起来像代码:使用多个RSA公共密钥进行加密

PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(dataEncryptor); 

for (PGPPublicKey publicKey : publicKeys) { 
     encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey)); 
} 

整体方法是这样的:

public File encryptFile(String fileName, 
     boolean armor, 
     boolean withIntegrityCheck) throws IOException, 
     NoSuchProviderException, 
     PGPException { 
    Security.addProvider(new BouncyCastleProvider()); 

    ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 

    PGPCompressedDataGenerator comData 
      = new PGPCompressedDataGenerator(PGPCompressedData.UNCOMPRESSED); 

    PGPUtil.writeFileToLiteralData(comData.open(bOut), 
      PGPLiteralData.BINARY, 
      new File(fileName)); 

    comData.close(); 

    BcPGPDataEncryptorBuilder dataEncryptor 
      = new BcPGPDataEncryptorBuilder(PGPEncryptedData.AES_256); 

    dataEncryptor.setWithIntegrityPacket(withIntegrityCheck); 

    dataEncryptor.setSecureRandom(new SecureRandom()); 

    PGPEncryptedDataGenerator encryptedDataGenerator 
      = new PGPEncryptedDataGenerator(dataEncryptor); 

    for (PGPPublicKey publicKey : publicKeys) { 
     encryptedDataGenerator.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey)); 
    } 

    byte[] bytes = bOut.toByteArray(); 

    FileOutputStream localByteArrayOutputStream = new FileOutputStream(fileName); 

    Object localObject = localByteArrayOutputStream; 

    if (armor) { 

     localObject = new ArmoredOutputStream((OutputStream) localObject); 

    } 

    OutputStream localOutputStream = encryptedDataGenerator.open((OutputStream) localObject, 
      bytes.length); 

    localOutputStream.write(bytes); 

    localOutputStream.close(); 

    return new File(fileName); 
} 

有人可以帮助我,告诉我什么,我做错了吗?

谢谢你的帮助。

[编辑] 此代码工作,我有加载多个键的方法的问题。

+0

请参阅http://stackoverflow.com/questions/38846/how-to-encrypt-one-message-for-multiple-recipients更标准的方法 – jonrsharpe

+0

据我所知,我需要生成对称密钥,用它来加密文件nd然后使用每个公钥加密此密钥,但我不知道如何使用bouncycastle执行此操作。我需要使用任何使用OpenPGP标准的程序来解密。 –

回答

1

那么,一年后我有同样的问题。我希望你已经解决了你的问题。我在这里写我的解决方案,以防别人有类似的问题。

您的加密代码没有问题。问题可能在于解密。对于加密数据对象,应使用与对象一起存储的密钥ID找到正确的密钥。我的解密过程如下所示:

private byte[] decryptWithKey(byte[] bytes, PGPSecretKey secKey, String pass) 
     throws PGPException, IOException { 
    PBESecretKeyDecryptor keyDec = new JcePBESecretKeyDecryptorBuilder(
      new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()) 
      .setProvider("BC").build(pass.toCharArray()); 
    ByteArrayOutputStream bout = new ByteArrayOutputStream(); 

    PGPPrivateKey privateKey = secKey.extractPrivateKey(keyDec); 
    PublicKeyDataDecryptorFactory dec1 = 
      new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(privateKey); 
    JcaPGPObjectFactory objFact = new JcaPGPObjectFactory(bytes); 
    PGPEncryptedDataList encList = (PGPEncryptedDataList) objFact.nextObject(); 

    PGPPublicKeyEncryptedData encD = null; 
    for(Iterator<PGPPublicKeyEncryptedData> it = encList.iterator(); it.hasNext();) { 
     PGPPublicKeyEncryptedData end = it.next(); 
     if (secKey.getKeyID() == end.getKeyID()) { 
      encD = end; 
      break; 
     } 
    } 
    assert encD != null: "Cannot find encrypted data with key: " 
      + Long.toHexString(secKey.getKeyID()); 
    InputStream in = encD.getDataStream(dec1); 
    byte[] buf = new byte[BufferSize]; 
    for (int len; (len = in.read(buf)) >= 0;) { 
     bout.write(buf, 0, len); 
    } 
    bout.close(); 
    return bout.toByteArray(); 
} 

密钥是找到加密对象的匹配密钥的for循环。