java通过PGP加解密文件(详细)


前言

根据上一节生成的pgp公钥、密钥给文件加解密,传送门 Java生成PGP的公钥和密钥


一、使用步骤

1.加解密工具类

代码如下(示例):


private static final String PROVIDER_BC = "BC";

/**
* Encrypt data to io stream.
*
* @param data      - The data to be encrypted.
* @param out       - The io stream to store the encrypted data.
* @param fileName  - The output file name.
* @param publicKey - The stream of public key.
* @throws IOException
* @throws PGPException
*/
public static void encryptToStream(byte[] data, OutputStream out, String fileName, InputStream publicKey) throws IOException, PGPException {

   byte[] compressedData = compressData(data, fileName);

   PGPPublicKey pgpPublicKey = readPublicKey(publicKey);

   PGPEncryptedDataGenerator pgpEncryptedDataGenerator = new PGPEncryptedDataGenerator(
           new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5)
                   .setWithIntegrityPacket(true)
                   .setSecureRandom(new SecureRandom())
                   .setProvider(PROVIDER_BC));
   pgpEncryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(pgpPublicKey).setProvider(PROVIDER_BC));

   OutputStream encryptOutputStream = pgpEncryptedDataGenerator.open(out, compressedData.length);

   encryptOutputStream.write(compressedData);
   encryptOutputStream.close();
}

/**
* Decrypt the encrypted data to io stream.
*
* @param encryptedData        - The data to be decrypted.
* @param secretKeyInputStream - The secret key.
* @param out                  - The io stream to store decrypted data.
* @throws IOException
*/
public static void decryptDataToStream(InputStream encryptedData, InputStream secretKeyInputStream, OutputStream out, String passphrase) throws IOException {

   try (InputStream pgpEncryptedData = PGPUtil.getDecoderStream(encryptedData)) {
       JcaPGPObjectFactory jcaPGPObjectFactory = new JcaPGPObjectFactory(pgpEncryptedData);
       Object object = jcaPGPObjectFactory.nextObject();

       // the first object might be a PGP marker packet.
       PGPEncryptedDataList pgpEncryptedDataList;
       if (object instanceof PGPEncryptedDataList) {
           pgpEncryptedDataList = (PGPEncryptedDataList) object;
       } else {
           pgpEncryptedDataList = (PGPEncryptedDataList) jcaPGPObjectFactory.nextObject();
       }

       // find the secret key
       Iterator iterator = pgpEncryptedDataList.getEncryptedDataObjects();
       PGPPrivateKey pgpPrivateKey = null;
       PGPPublicKeyEncryptedData pgpPublicKeyEncryptedData = null;
       PGPSecretKeyRingCollection pgpSecretKeyRingCollection = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(secretKeyInputStream), new JcaKeyFingerprintCalculator());

       while (pgpPrivateKey == null && iterator.hasNext()) {
           pgpPublicKeyEncryptedData = (PGPPublicKeyEncryptedData) iterator.next();
           pgpPrivateKey = findSecretKey(pgpSecretKeyRingCollection, pgpPublicKeyEncryptedData.getKeyID(), passphrase.toCharArray());
       }

       if (pgpPrivateKey == null) {
           throw new IllegalArgumentException("secret key for message not found.");
       }

       InputStream pgpPrivateKeyInputStream = pgpPublicKeyEncryptedData.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider(PROVIDER_BC).build(pgpPrivateKey));
       JcaPGPObjectFactory pgpPrivateKey_jcaPGPObjectFactory = new JcaPGPObjectFactory(pgpPrivateKeyInputStream);
       Object message = pgpPrivateKey_jcaPGPObjectFactory.nextObject();

       if (message instanceof PGPCompressedData) {
           PGPCompressedData pgpCompressedData = (PGPCompressedData) message;
           JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(pgpCompressedData.getDataStream());

           message = pgpFact.nextObject();
       }

       if (message instanceof PGPLiteralData) {
           PGPLiteralData pgpLiteralData = (PGPLiteralData) message;
           InputStream unc = pgpLiteralData.getInputStream();
           Streams.pipeAll(unc, out);

       } else if (message instanceof PGPOnePassSignatureList) {
           throw new PGPException("encrypted message contains a signed message - not literal data.");
       } else {
           throw new PGPException("message is not a simple encrypted file - type unknown.");
       }

       if (pgpPublicKeyEncryptedData.isIntegrityProtected()) {
           if (!pgpPublicKeyEncryptedData.verify()) {
               log.error("message failed integrity check");
           } else {
               log.info("message integrity check passed");
           }
       } else {
           log.error("no message integrity check");
       }
   } catch (PGPException e) {
       log.error(e.getMessage(), e);
       if (e.getUnderlyingException() != null) {
           log.error(e.getUnderlyingException().getMessage(), e.getUnderlyingException());
       }
   }
}

public static byte[] compressData(byte[] data, String fileName) throws IOException {

   ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
   PGPCompressedDataGenerator pgpCompressedDataGenerator = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZIP);
   OutputStream compressStream = pgpCompressedDataGenerator.open(byteArrayOutputStream);

   PGPLiteralDataGenerator pgpLiteralDataGenerator = new PGPLiteralDataGenerator();
   // we want to generate compressed data. This might be a user option later,
   OutputStream pgpOutputStream = pgpLiteralDataGenerator.open(compressStream,
           PGPLiteralData.BINARY,
           fileName,
           data.length,
           new Date()
   );

   // in which case we would pass in bOut.
   pgpOutputStream.write(data);
   pgpOutputStream.close();
   compressStream.close();

   return byteArrayOutputStream.toByteArray();
}

public static PGPPublicKey readPublicKey(InputStream keyInputStream) throws IOException, PGPException {
   PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(
           PGPUtil.getDecoderStream(keyInputStream), new JcaKeyFingerprintCalculator());

   Iterator keyRingIter = pgpPub.getKeyRings();
   while (keyRingIter.hasNext()) {
       PGPPublicKeyRing keyRing = (PGPPublicKeyRing) keyRingIter.next();

       Iterator keyIter = keyRing.getPublicKeys();
       while (keyIter.hasNext()) {
           PGPPublicKey key = (PGPPublicKey) keyIter.next();

           if (key.isEncryptionKey()) {
               return key;
           }
       }
   }
   throw new IllegalArgumentException("Can't find encryption key in key ring.");
}

public static PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection pgpSecretKeyRingCollection, long keyID, char[] pass) throws PGPException {

   PGPSecretKey pgpSecretKey = pgpSecretKeyRingCollection.getSecretKey(keyID);
   if (pgpSecretKey == null) return null;

   PBESecretKeyDecryptor pbeSecretKeyDecryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass);
   return pgpSecretKey.extractPrivateKey(pbeSecretKeyDecryptor);

}

2.测试

代码如下(示例):

private static void encrypt() throws Exception {
    //要加密的文件名
    String dataPath = "template.csv";
    InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(dataPath);
    // 读取classes下pgp文件夹的public key
    InputStream pubKey = new ClassPathResource("pgp/PUBLIC_KEY_2048.asc").getInputStream();
    byte[] encData = toByteArray(inputStream);
    //加密后的文件名
    FileOutputStream fileOutputStream = new FileOutputStream("template-encrypt.csv");
    //加密
    encryptToStream(encData, fileOutputStream, "template-encrypt.csv", pubKey);
}

private static void decrypt() throws Exception{
    InputStream encryptedData = Thread.currentThread().getContextClassLoader().getResourceAsStream("template-encrypt.csv");
    // 读取classes下pgp文件夹的private key
    InputStream secretKey = new ClassPathResource("pgp/PRIVATE_KEY_2048.asc").getInputStream();
    // 解密后的 文件
    FileOutputStream fileOutputStream = new FileOutputStream("template-decrypt.csv");
    decryptDataToStream(encryptedData, secretKey, fileOutputStream, "");
}

public static void main(String[] args) throws Exception {
	encrypt();
	decrypt();
}

总结

通过公钥给文件加密,私钥给文件解密,RSA非对称加密算法。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PGP(Pretty Good Privacy)是一种用于加密和签名电子邮件、文档和文件的加密协议。它使用对称加密和非对称加密结合的方式,能够保证通信的安全性。 Java中可以使用Bouncy Castle库来实现PGP加解密,具体步骤如下: 1. 首先,需要导入Bouncy Castle库: ```java import org.bouncycastle.openpgp.*; import org.bouncycastle.openpgp.operator.jcajce.*; ``` 2. 加载公钥和私钥 ```java PGPPublicKeyRing publicKeyRing = new PGPPublicKeyRing(pubKeyRingCollection); PGPPublicKey publicKey = publicKeyRing.getPublicKey(publicKeyId); PGPSecretKeyRing secretKeyRing = new PGPSecretKeyRing(secretKeyRingCollection); PGPSecretKey secretKey = secretKeyRing.getSecretKey(secretKeyId); ``` 3. 加密数据 ```java byte[] data = "hello, world!".getBytes("UTF-8"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator(); OutputStream encryptedOutputStream = literalDataGenerator.open(outputStream, PGPLiteralData.BINARY, "", data.length, new Date()); encryptedOutputStream.write(data); encryptedOutputStream.close(); PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.AES_256).setWithIntegrityPacket(true).setSecureRandom(new SecureRandom()).setProvider("BC")); encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(publicKey).setProvider("BC")); byte[] encryptedData = outputStream.toByteArray(); ``` 4. 解密数据 ```java ByteArrayInputStream inputStream = new ByteArrayInputStream(encryptedData); PGPObjectFactory objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(inputStream), new JcaKeyFingerprintCalculator()); PGPCompressedData compressedData = (PGPCompressedData) objectFactory.nextObject(); objectFactory = new PGPObjectFactory(compressedData.getDataStream(), new JcaKeyFingerprintCalculator()); PGPLiteralData literalData = (PGPLiteralData) objectFactory.nextObject(); InputStream literalDataStream = literalData.getInputStream(); byte[] decryptedData = new byte[literalData.getLength()]; IOUtils.readFully(literalDataStream, decryptedData); literalDataStream.close(); ``` 以上就是使用Java实现PGP加解密的基本步骤。需要注意的是,Bouncy Castle库的使用需要引入相应的jar包,并且还需要导入Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files,否则会出现加密强度不足的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值