最近业务上遇到一个很棘手的问题,客户要求在调用他们的时候要对报文进行加密解密,然后方式就是用pgp的方式进行加密解密,相信有很多小伙伴和我一样刚开始看到这个pgp(或者gpg)加密都是一脸懵,啥玩意儿?这东西是个啥,于是乎就上百度搜索了一下,原来是一种很传统的加密解密方式,没办法,客户要求怎么做我们就得如何去实现,话不多说,开搞!!!
一,(重要!!)首先我们需要了解的是,gpg的加密解密有两种方式,第一种就是在我们的windows系统中敲cmd命令进行加密解密,我建议大家在这里先尝试一下这种方式,了解一下,因为在java代码中去实现的话,需要用到其中的公钥私钥和对应的密码,这些不能是我们随便创建的,是要有专门的去生成的,否则代码就会报错!!!这是我当时所遇见的坑之一,所以这里也是希望各位小伙伴少走弯路。
首先下载gpg.exe,Gpg4win - Get Gpg4win,打不开大家可以找一下别的,可视化界面工具大家下载完其实没必要打开,直接cmd敲命令就行(因为有时候有小伙伴的可视化页面打不开,但不影响cmd命令)
然后cmd生成密钥等,由于我主要是给大家说java方式实现,所以这里不详细介绍,大家可以参考这个博主写的,非常详细,亲测可用!
(3条消息) gpg在xp系统使用,用java调用指令对文件加密解密_pinkpqs的博客-CSDN博客
二,java方式实现,上面介绍了在windows中实现的之后,要把生成的公钥,私钥,以及对应的key要存在我们电脑中,以便我们代码中去使用,在这里要强调一点我们自测的时候第一行代码必须是
Security.addProvider(new BouncyCastleProvider());否则会报错,大家切记!这个是个坑!!!
首先是jar包,我这里是1.60
<!-- gpg加密解密需要用到的包 start --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpg-jdk15on</artifactId> <version>1.60</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.60</version> </dependency> <!-- gpg加密解密需要用到的包 End -->
然后有三个类是我封装的,由于最后是的到加密解密的字符串,但其实是加密解密的文件,因为发送的是报文所以将文件进行了生成和读取
1.PGPExampleUtil
import org.bouncycastle.openpgp.*; import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import java.io.*; import java.security.NoSuchProviderException; import java.util.Iterator; public class PGPExampleUtil { static byte[]compressFile(String fileName, int algorithm)throws IOException { ByteArrayOutputStream bOut =new ByteArrayOutputStream(); PGPCompressedDataGenerator comData =new PGPCompressedDataGenerator(algorithm); PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName)); comData.close(); return bOut.toByteArray(); } /** * Search a secret key ring collection for a secret key corresponding to keyID if it * exists. * * @param pgpSec a secret key ring collection. * @param keyID keyID we want. * @param pass passphrase to decrypt secret key with. * @return the private key. * @throws PGPException * @throws NoSuchProviderException */ static PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass) throws PGPException, NoSuchProviderException { PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID); if (pgpSecKey ==null) { return null; } return pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(pass)); } static PGPPublicKey readPublicKey(String fileName)throws IOException, PGPException { InputStream keyIn =new BufferedInputStream(new FileInputStream(fileName)); PGPPublicKey pubKey =readPublicKey(keyIn); keyIn.close(); return pubKey; } /** * A simple routine that opens a key ring file and loads the first available key * suitable for encryption. * * @param input data stream containing the public key data * @return the first pub