最近业务上遇到一个很棘手的问题,客户要求在调用他们的时候要对报文进行加密解密,然后方式就是用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 public key found.* @throws IOException* @throws PGPException*/static PGPPublicKey readPublicKey(InputStream input)throws IOException, PGPException {PGPPublicKeyRingCollection pgpPub =new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());//// we just loop through the collection till we find a key suitable for encryption, in the real// world you would probably want to be a bit smarter about this.//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.");}static PGPSecretKey readSecretKey(String fileName)throws IOException, PGPException {InputStream keyIn =new BufferedInputStream(new FileInputStream(fileName));PGPSecretKey secKey =readSecretKey(keyIn);keyIn.close();return secKey;}/*** A simple routine that opens a key ring file and loads the first available key* suitable for signature generation.** @param input stream to read the secret key ring collection from.* @return a secret key.* @throws IOException  on a problem with using the input stream.* @throws PGPException if there is an issue parsing the input stream.*/static PGPSecretKey readSecretKey(InputStream input)throws IOException, PGPException {PGPSecretKeyRingCollection pgpSec =new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(input), new JcaKeyFingerprintCalculator());//// we just loop through the collection till we find a key suitable for encryption, in the real// world you would probably want to be a bit smarter about this.//Iterator keyRingIter = pgpSec.getKeyRings();while (keyRingIter.hasNext()) {PGPSecretKeyRing keyRing = (PGPSecretKeyRing) keyRingIter.next();Iterator keyIter = keyRing.getSecretKeys();while (keyIter.hasNext()) {PGPSecretKey key = (PGPSecretKey) keyIter.next();if (key.isSigningKey()) {return key;}}}throw new IllegalArgumentException("Can't find signing key in key ring.");}}

2.KeyBasedFileProcessor

import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator;
import org.bouncycastle.util.io.Streams;import java.io.*;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class KeyBasedFileProcessor {private static void decryptFile(String inputFileName,String keyFileName,char[] passwd,String defaultFileName)throws IOException, NoSuchProviderException {InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName));decryptFile(in, keyIn, passwd, defaultFileName);keyIn.close();in.close();}/*** decrypt the passed in message stream*/private static void decryptFile(InputStream in,InputStream keyIn,char[] passwd,String defaultFileName)throws IOException, NoSuchProviderException {in = PGPUtil.getDecoderStream(in);try {JcaPGPObjectFactory pgpF = new JcaPGPObjectFactory(in);PGPEncryptedDataList enc;Object o = pgpF.nextObject();//// the first object might be a PGP marker packet.//if (o instanceof PGPEncryptedDataList) {enc = (PGPEncryptedDataList) o;} else {enc = (PGPEncryptedDataList) pgpF.nextObject();}//// find the secret key//Iterator it = enc.getEncryptedDataObjects();PGPPrivateKey sKey = null;PGPPublicKeyEncryptedData pbe = null;PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn), new JcaKeyFingerprintCalculator());while (sKey == null && it.hasNext()) {pbe = (PGPPublicKeyEncryptedData) it.next();sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), passwd);}if (sKey == null) {throw new IllegalArgumentException("secret key for message not found.");}InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));JcaPGPObjectFactory plainFact = new JcaPGPObjectFactory(clear);Object message = plainFact.nextObject();if (message instanceof PGPCompressedData) {PGPCompressedData cData = (PGPCompressedData) message;JcaPGPObjectFactory pgpFact = new JcaPGPObjectFactory(cData.getDataStream());message = pgpFact.nextObject();}if (message instanceof PGPLiteralData) {PGPLiteralData ld = (PGPLiteralData) message;String outFileName = ld.getFileName();if (outFileName.length() == 0) {outFileName = defaultFileName;} else {outFileName = defaultFileName;}InputStream unc = ld.getInputStream();OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));Streams.pipeAll(unc, fOut);fOut.close();} 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 (pbe.isIntegrityProtected()) {if (!pbe.verify()) {System.err.println("message failed integrity check");} else {System.err.println("message integrity check passed");}} else {System.err.println("no message integrity check");}} catch (PGPException e) {System.err.println(e);if (e.getUnderlyingException() != null) {e.getUnderlyingException().printStackTrace();}}}private static void encryptFile(String outputFileName,String inputFileName,String encKeyFileName,boolean armor,boolean withIntegrityCheck)throws IOException, NoSuchProviderException, PGPException {OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));PGPPublicKey encKey = PGPExampleUtil.readPublicKey(encKeyFileName);encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck);out.close();}private static void encryptFile(OutputStream out,String fileName,PGPPublicKey encKey,boolean armor,boolean withIntegrityCheck)throws IOException, NoSuchProviderException {if (armor) {out = new ArmoredOutputStream(out);}try {byte[] bytes = PGPExampleUtil.compressFile(fileName, CompressionAlgorithmTags.ZIP);PGPEncryptedDataGenerator encGen = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));encGen.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));OutputStream cOut = encGen.open(out, bytes.length);cOut.write(bytes);cOut.close();if (armor) {out.close();}} catch (PGPException e) {System.err.println(e);if (e.getUnderlyingException() != null) {e.getUnderlyingException().printStackTrace();}}}//遍历读取文件名public static List ReadFileName() throws Exception {File f = null;//        DateUtil.getCurrentDate("yyyy-MM-dd");//        String timerandom = DateUtil.getCurrentDate("yyyy-MM-dd").replace("-", "");String path = "";//        path = "D:" + "/" + timerandom + "/encrypt";path = "D:/20190628/decrypt/";f = new File(path); //新建文件实例File[] list = f.listFiles(); /* 此处获取文件夹下的所有文件 */List fileNameList = new ArrayList();if (null != list && list.length > 0) {for (int i = 0; i < list.length; i++) {fileNameList.add(list[i].getName());System.out.println("遍历后的文件名:" + fileNameList.get(i));}} else {System.out.println("文件夹没有相应的文件");}return fileNameList;}/*** @param: 参数* @return: 返回值* @description: 得到加密的字符串* @author: lxh* @date: 2022/7/11 17:59*/public String getEncryptString(String content, String publicKeys) throws Exception {String result = "";String inputPath = "linshifile";String filename = "linshi.asc";String pathname = inputPath + '/' + filename;String outPath = inputPath + '/' + "linshi.txt";//        publicKeys = "D:\\public-gpg";  //公钥地址//校验临时文件是否存在,不存在就创建它File tFile = new File(inputPath);if (!tFile.exists()) {tFile.mkdirs();System.out.println("*** 文件路径不存在,已创建 ***");}FileReadWriteutil fileReadWriteutil = new FileReadWriteutil();fileReadWriteutil.getContentFile(content, pathname);encryptFile(outPath, pathname, publicKeys, true, true);//读取解密文件的内容String filecontent = fileReadWriteutil.getFilecontent(outPath);result = filecontent;return result;}/*** @param: 参数* @return: 返回值* @description: 得到解密的字符串* @author: lxh* @date: 2022/7/11 18:18*/public String getDecryptString(String content, String privateKeys, String password) throws Exception {String result = "";String inputPath = "linshifile";String filename = "jiami.asc";String pathname = inputPath + '/' + filename;String outPath = inputPath + '/' + "jiami.txt";//校验临时文件是否存在,不存在就创建它File tFile = new File(inputPath);if (!tFile.exists()) {tFile.mkdirs();System.out.println("*** 文件路径不存在,已创建 ***");}FileReadWriteutil fileReadWriteutil = new FileReadWriteutil();fileReadWriteutil.getContentFile(content, pathname);decryptFile(pathname, privateKeys, password.toCharArray(), outPath);//读取加密文件的内容String filecontent = fileReadWriteutil.getFilecontent(outPath);result = filecontent;return result;}//主方法public static void main(String[] s) throws Exception {Security.addProvider(new BouncyCastleProvider());}}

3.FileReadWriteutil

import org.bouncycastle.jce.provider.BouncyCastleProvider;import java.io.*;
import java.security.Security;/*** @projectName: Test* @package: com.demo.util* @className: FileReadWriteutil* @description: 对gpg生成的文件方便处理* @author: lxh* @date: 2022/7/11 13:52*/
public class FileReadWriteutil {public String getFilecontent(String path) {//首先校验文件是否存在File tFile = new File(path);if (!tFile.exists()) {return "";}BufferedReader br = null;String s = "";String sum = "";try {br = new BufferedReader(new FileReader(tFile));int i = 0;while ((s = br.readLine()) != null) {i++;//记录行数if (i == 1) {sum = s;} else {sum = sum + "\n" + s;}}System.out.println("*** 一共读取" + i + "行数据 ***");System.out.println("******************最终的读取数据为:\n" +sum);} catch (Exception e) {e.printStackTrace();} finally {try {if (br != null) {br.close();//用完之後要對流關閉}} catch (IOException e) {e.printStackTrace();}}return sum;}public void getContentFile(String content, String path) throws Exception {String result = path;File file = new File(result);FileOutputStream fout = new FileOutputStream(file);OutputStreamWriter write = new OutputStreamWriter(fout, "UTF-8");BufferedWriter bw = new BufferedWriter(write);bw.write(content);bw.close();write.close();fout.close();}public static void main(String[] args) throws Exception {Security.addProvider(new BouncyCastleProvider());//必须有否则会报错KeyBasedFileProcessor keybase = new KeyBasedFileProcessor();//加密String encryptstring = keybase.getEncryptString("hello world", "D:/public-gpg");System.out.println(encryptstring);//解密String decryptString = keybase.getDecryptString(encryptstring, "D:\\secret-key", "12345678");System.out.println("***********************************************************");System.out.println(decryptString);}
}

以上就是所有的代码了,大家在自测的时候,进入FileReadWriteutil的main方法去试,我把东西都封装好了,在运行的时候会产生一些临时文件,如果大家不想要,可以在代码中写对应的逻辑去删除,我这里考虑到的是因为这个文件需要频繁使用,所以就没有删除,然后说一下遇到的坑吧,首先是这一行代码

必须要有,不然会报错,大家可以试一下

然后是参数,就是上边的那个password,我之前一直以为是cmd里产生的那个私钥,结果怎么试都不对,最后试了一下cmd输入的时候输入的那个邮箱密码,结果就对了,很坑,这里大家需要注意一下,我这里的原理其实就是,加密的时候,加密内容我会去将其生成一个txt文件,然后java对这个文件加密,然后对加密后的文件读取内容,将内容输出来,没办法,gpg的方式就是这样的,加密解密的其实是文件。
好啦!以上就是所有对gpg加密解密的分享,欢迎有问题的小伙伴私信我呦,不喜勿喷呀,祝大家都能顺利!

基于JAVA实现GPG加密解密(Windows+java两种方式)相关推荐

  1. Java实现MD5加密及验证(两种方式,加盐md5与未加盐md5)

    一.加盐MD5加密工具 package com.dimpt.base.util;import java.io.UnsupportedEncodingException; import java.sec ...

  2. 使用IntelliJ IDEA 集成阿里提供的 Alibaba Cloud Toolkit插件,实现自动化远程部署Java项目(jar包,war包两种方式)

    打开IntelliJ IDEA编译器,点击文件==>点击设置(setting) 在设置页面点击插件(英文应该是 Plugins ,对IntelliJ IDEA汉化感兴趣的同学可以在这个页面搜索 ...

  3. java 不重启部署_编译Java类后不重启Tomcat有两种方式:热部署、热加载

    不重启Tomcat有两种方式:热部署.热加载 热部署:容器状况在运行时重新部署整个项目.这类环境下一般整个内存会清空,重新加载,这类方式 有可能会造成sessin丢失等环境.tomcat 6确实可以热 ...

  4. java 将word转为pdf文件的两种方式【spire.doc.free】【documents4j】

    场景 如资产证明等场景下,一般要求同时生成word与pdf两种格式的证明文件,且两者格式需保持一致,可以各自单独生成,但那样可能需要维护两个模板文件,所以也可以仅定义一份word的模板文件,使用模板生 ...

  5. Java 生成随机码工具类 线程安全 两种方式

    提供两种方法产生随机码,默认长度为8 方案1:基于 Collections.shuffle() 有线程安全问题,需要加锁 速度快,但并发场景下可能比UUID方式慢 实现简单,可直接修改随机码位数 /* ...

  6. Java在控制台输出带颜色字符的两种方式

    通过\033特殊转义符实现 这种方法主要适用于Linux系统的控制台,也能在Windows系统中的IDEA中实现,但在Windows系统的控制台中却是乱码. public class ColourTe ...

  7. java web oracle 分页_Oracle分页的两种方式

    第一种: select b.* from (select rownum as rid, a.* from om_cm_book_hotword a) b where b.rid <= 10 an ...

  8. Java计算两点间经纬度距离(两种方式)

    反余弦计算方式: private static final double EARTH_RADIUS = 6371000; // 平均半径,单位:m:不是赤道半径.赤道为6378左右 public st ...

  9. Java——获取当前线程的对象(currentThread())(两种方式)

    package com.yy.threadmethod;public class Demo2_CurrentThread {/*** public static Thread currentThrea ...

最新文章

  1. k8s控制器:DaemonSet
  2. 【Ubuntu】ubuntu更新设置
  3. Java高级面试题!java编程思想怎么学
  4. OpenWrt 之 MT7628 移植第三方SPI驱动
  5. linux自动读取麦克风,检测用户向麦克吹气
  6. Python 加密解密
  7. unity3d Aniso Level 摄像机近地面清楚,远地面模糊
  8. greenplum mysql jdbc_Kylin设置JDBC配置greenplum数据源
  9. python open 追加_Python创建文件和追加文件内容实例
  10. 点餐系统ip地址_spring boot实战——微信点餐系统03:微信授权(用户授权),免费内网穿透(固定ip)...
  11. Like rlike在hive中的区别
  12. v5服务器装系统,小白必学:宏基V5-591G内存、固态、装系统教程!
  13. java电驴_转:java写的电驴下载完成关机小程序
  14. java中sof是什么意思_SOF是什么意思
  15. 恒虚警率(Constant False Alarm Rate)检测
  16. DNS这位“翻译官”是如何转换域名和IP地址的?
  17. 获取单选框复选框被选中的值
  18. 【Linux vim 入门及渐进过程2 - vim 常用插件配置】
  19. 基于SSM社区网格化小区管理系统设计
  20. Contacts管理系统通讯录

热门文章

  1. MxNet系列——how_to——multi_devices
  2. Java 利用感知哈希算法简单实现用户头像搜索(搜图)
  3. Springboot AOP注解方式获取请求参数及返回值并发送至rabbitMQ
  4. 终于等到你,最强 IDE Visual Studio 2017 正式版发布(附详细介绍与下载地址)
  5. verilog 学习笔记1
  6. 亥姆霍兹线圈分类简介
  7. 360安全浏览器极速模式对rem失效
  8. 知乎上40个有趣回复,很精辟!
  9. Spring框架基础入门
  10. #内存泄露# linux常用内存相关命令