openPGP :邮件加密标准,被广泛使用

准备工作:

bouncycastle 的jar包

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15on</artifactId>
  <version>1.50</version>
</dependency>

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcpg-jdk15on</artifactId>
  <version>1.50</version>
</dependency>

https://www.oracle.com/java/technologies/

搜索下载 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files

将压缩包中的 jar包替换 %JAVA_HOME%/jre/lib/security 或者 %JRE_HOME%/lib/security  目录中的jar包 (目的是为了防止程序出现 Invalid Key size的错误)

源码如下:(可以参考 bcpg-jdk15on jar包里面的 examples目录)

Security.addProvider(new BouncyCastleProvider());这句是必须的,否则程序会报错
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
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.Iterator;

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.PGPCompressedDataGenerator;
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.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPOnePassSignatureList;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
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 OpenPgpUtil { static { try { Security.addProvider(new BouncyCastleProvider()); } catch (Exception e) { e.printStackTrace(); } } public static void encryptFile(String outputFileName, String inputFileName, String encKeyFileName, boolean armor, boolean withIntegrityCheck) throws IOException, NoSuchProviderException, PGPException { OutputStream out = null; try { out = new BufferedOutputStream(new FileOutputStream(outputFileName)); PGPPublicKey encKey = readPublicKey(encKeyFileName); encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck); } finally { if(out!=null) { out.close(); } } } public static void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) throws IOException, NoSuchProviderException, PGPException { if (armor) { out = new ArmoredOutputStream(out); } byte[] bytes = 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(); } } public 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(); } public static PGPPublicKey readPublicKey(String fileName) throws IOException, PGPException { InputStream keyIn = new BufferedInputStream(new FileInputStream(fileName)); PGPPublicKey pubKey = readPublicKey(keyIn); keyIn.close(); return pubKey; } @SuppressWarnings("rawtypes") private static PGPPublicKey readPublicKey(InputStream input) throws IOException, PGPException { PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input)); // // 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."); } public static void decryptFile(String inputFileName, String keyFileName, String password, String defaultFileName) throws Exception { InputStream in = null; InputStream keyIn = null; try { in = new BufferedInputStream(new FileInputStream(inputFileName)); keyIn = new BufferedInputStream(new FileInputStream(keyFileName)); decryptFile(in, keyIn, password.toCharArray(), defaultFileName); } finally { if(in!=null) { in.close(); } if(keyIn!=null) { keyIn.close(); } } } @SuppressWarnings("rawtypes") public static void decryptFile(InputStream in, InputStream keyIn, char[] passwd, String defaultFileName) throws Exception { in = PGPUtil.getDecoderStream(in); try { PGPObjectFactory pgpF = new PGPObjectFactory(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)); while (sKey == null && it.hasNext()) { pbe = (PGPPublicKeyEncryptedData) it.next(); sKey = 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)); PGPObjectFactory plainFact = new PGPObjectFactory(clear); Object message = plainFact.nextObject(); if (message instanceof PGPCompressedData) { PGPCompressedData cData = (PGPCompressedData) message; PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream()); message = pgpFact.nextObject(); } if (message instanceof PGPLiteralData) { PGPLiteralData ld = (PGPLiteralData) message; String outFileName = ld.getFileName(); // if (outFileName.length() == 0) { // outFileName = defaultFileName; // } 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(); } throw e; } } public 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)); } }

 

posted on 2020-08-20 17:36  >^^<  阅读(1089)  评论(0编辑  收藏  举报