? ? 銀行對接保險公司要對文件進行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.");
? ? }
}