基于JAVA代碼進行GPG解密

? ? 銀行對接保險公司要對文件進行g(shù)pg加密炊汤,那保險公司要進行解密了正驻。

? ? 原來想的方案是用java代碼編寫cmd命令然后執(zhí)行bat文件,生成指定的文件夾下抢腐。這樣的話有幾個弊端:第一次運行bat文件的時候總是會提示要輸入密碼姑曙,發(fā)布到服務(wù)器上是不可控的。另一個是服務(wù)器是windows系統(tǒng)的話還要安裝gpg的軟件迈倍。

? ? 后來發(fā)現(xiàn)java封裝有g(shù)pg解密的伤靠,于是就拿來用了。我的業(yè)務(wù)邏輯是取指定文件下的以.DAT結(jié)尾的gpg加密后的文件啼染,然后遍歷生成到制定的文件夾下宴合。

? ? 在這其中遇到了兩個坑。

? ? 1迹鹅、業(yè)務(wù)邏輯中的方法中一定不要忘記加Security.addProvider(new BouncyCastleProvider());這一句卦洽,不然報錯,人往往容易一葉障目斜棚,這不該發(fā)生的問題讓我找了好久逐样。

? ? 2、報這個錯誤java.security.InvalidKeyException: Illegal key size or default parameters。問題原因是解密的私鑰位數(shù)太長脂新,跟jdk版本有關(guān)系挪捕。密鑰長度是受限制的, java運行時環(huán)境讀到的是受限的policy文件. 文件位于${java_home}/jre/lib/security, 這種限制是因為美國對軟件出口的控制。在jdk的版本中在jdk1.8的151版本之后就解除了這種限制争便。當時在本地測試的一切順利级零,一發(fā)布到測試環(huán)境就有問題,后來了解測試環(huán)境的jdk版本是jdk1.8的121版本滞乙,還是有秘鑰長度的限制奏纪。相關(guān)介紹:https://my.oschina.net/u/1037605/blog/3026103。

? ? 首先是maven要引用的jar包斩启。

<dependency>

<groupId>org.bouncycastle</groupId>

<artifactId>bcpg-jdk15on</artifactId>

<version>1.56</version>

</dependency>

下面就是代碼了(復(fù)制粘貼就可以用了序调,前提你要有相應(yīng)的秘鑰信息)。


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("文件夾沒有相應(yīng)的文件");

? ? ? ? }

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.");

? ? }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市垄琐,隨后出現(xiàn)的幾起案子边酒,更是在濱河造成了極大的恐慌,老刑警劉巖狸窘,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墩朦,死亡現(xiàn)場離奇詭異,居然都是意外死亡翻擒,警方通過查閱死者的電腦和手機氓涣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陋气,“玉大人春哨,你說我怎么就攤上這事《魉牛” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵椰拒,是天一觀的道長晶渠。 經(jīng)常有香客問我,道長燃观,這世上最難降的妖魔是什么褒脯? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮缆毁,結(jié)果婚禮上番川,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好颁督,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布践啄。 她就那樣靜靜地躺著,像睡著了一般沉御。 火紅的嫁衣襯著肌膚如雪屿讽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天吠裆,我揣著相機與錄音伐谈,去河邊找鬼。 笑死试疙,一個胖子當著我的面吹牛诵棵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祝旷,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼履澳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缓屠?” 一聲冷哼從身側(cè)響起奇昙,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敌完,沒想到半個月后储耐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡滨溉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年什湘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晦攒。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡闽撤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脯颜,到底是詐尸還是另有隱情哟旗,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布栋操,位于F島的核電站闸餐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏矾芙。R本人自食惡果不足惜舍沙,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剔宪。 院中可真熱鬧拂铡,春花似錦壹无、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至留瞳,卻和暖如春拒迅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背她倘。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工璧微, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硬梁。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓前硫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荧止。 傳聞我的和親對象是個殘疾皇子屹电,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容