基于JAVA代码进行GPG解密

    银行对接保险公司要对文件进行gpg加密,那保险公司要进行解密了。

    原来想的方案是用java代码编写cmd命令然后执行bat文件,生成指定的文件夹下。这样的话有几个弊端:第一次运行bat文件的时候总是会提示要输入密码,发布到服务器上是不可控的。另一个是服务器是windows系统的话还要安装gpg的软件。

    后来发现java封装有gpg解密的,于是就拿来用了。我的业务逻辑是取指定文件下的以.DAT结尾的gpg加密后的文件,然后遍历生成到制定的文件夹下。

    在这其中遇到了两个坑。

    1、业务逻辑中的方法中一定不要忘记加Security.addProvider(new BouncyCastleProvider());这一句,不然报错,人往往容易一叶障目,这不该发生的问题让我找了好久。

    2、报这个错误java.security.InvalidKeyException: Illegal key size or default parameters。问题原因是解密的私钥位数太长,跟jdk版本有关系。密钥长度是受限制的, java运行时环境读到的是受限的policy文件. 文件位于${java_home}/jre/lib/security, 这种限制是因为美国对软件出口的控制。在jdk的版本中在jdk1.8的151版本之后就解除了这种限制。当时在本地测试的一切顺利,一发布到测试环境就有问题,后来了解测试环境的jdk版本是jdk1.8的121版本,还是有秘钥长度的限制。相关介绍:https://my.oschina.net/u/1037605/blog/3026103。

    首先是maven要引用的jar包。

<dependency>

<groupId>org.bouncycastle</groupId>

<artifactId>bcpg-jdk15on</artifactId>

<version>1.56</version>

</dependency>

下面就是代码了(复制粘贴就可以用了,前提你要有相应的秘钥信息)。


import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.security.NoSuchProviderException;

import java.security.SecureRandom;

import java.security.Security;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import com.sinosoft.light.dataswitch.service.util.PGPExampleUtil;

import com.sinosoft.platform.common.exception.SinoSystemException;

import org.bouncycastle.bcpg.ArmoredOutputStream;

import org.bouncycastle.bcpg.CompressionAlgorithmTags;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.openpgp.PGPCompressedData;

import org.bouncycastle.openpgp.PGPEncryptedData;

import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;

import org.bouncycastle.openpgp.PGPEncryptedDataList;

import org.bouncycastle.openpgp.PGPException;

import org.bouncycastle.openpgp.PGPLiteralData;

import org.bouncycastle.openpgp.PGPOnePassSignatureList;

import org.bouncycastle.openpgp.PGPPrivateKey;

import org.bouncycastle.openpgp.PGPPublicKey;

import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;

import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;

import org.bouncycastle.openpgp.PGPUtil;

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;

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 (oinstanceof 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 (messageinstanceof PGPCompressedData) {

PGPCompressedData cData = (PGPCompressedData) message;

                JcaPGPObjectFactory pgpFact =new JcaPGPObjectFactory(cData.getDataStream());

                message = pgpFact.nextObject();

            }

if (messageinstanceof 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 (messageinstanceof 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 ListReadFileName()throws SinoSystemException {

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/encrypt/";

        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 {

throw new SinoSystemException("文件夹没有相应的文件");

        }

return fileNameList;

    }

//主方法

    public static void main(String[] s)throws Exception {

Security.addProvider(new BouncyCastleProvider());

        boolean encryp =false;  //加密:true  解密:false

        if (encryp) {

String outPath ="D:\\20190628\\decrypt\\123.DAT";

            String inputPath ="D:\\20190628\\decrypt\\123.txt";

            String publicKeys ="D:\\20190628\\public\\C3B655736E8C77F83183074049F3AB440C1B1830.asc";  //公钥地址

            encryptFile(outPath, inputPath, publicKeys, true, true);

        }else {

String inputPath;

            String outPath;

            String address ="D:/20190628/decrypt/";

            String password ="1234568987";  //私钥的Key

            String privateKeys ="D:\\20190628\\private\\C3B655736E8C77F83183074049F3AB440C1B1830.asc";//私钥地址

//批量解密文件

            List fileList =ReadFileName();

            if (null != fileList) {

for (int i =0; i < fileList.size(); i++) {

inputPath ="D:/20190628/encrypt/" + fileList.get(i);  //被加密的文件

                    if (fileList.get(i).indexOf("DAT") != -1) {

outPath = address + fileList.get(i).replace("DAT", "TXT");

                        System.out.println("解密第一个文件,要解密的文件:" + inputPath +",解密出来的文件" + outPath);

                        decryptFile(inputPath, privateKeys, password.toCharArray(), outPath);

                    }else {

continue;

                    }

}

}

}

}

}

----------------------------------------------------------------------------

import org.bouncycastle.openpgp.*;

import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;

import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;

import java.io.BufferedInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

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 PGPPrivateKeyfindSecretKey(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 PGPPublicKeyreadPublicKey(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 PGPPublicKeyreadPublicKey(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 PGPSecretKeyreadSecretKey(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 PGPSecretKeyreadSecretKey(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.");

    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容