1.PGP加密

1.1 简介

PGP:Pretty Good Policy,良好隐私密码法,是一套用于消息加密、验证的应用程序。

加密发送一个文件:

  • 获取pgp公钥进行加密文件内容,发送给指定用户。
  • 用户获取文件之后,用对应密钥对文件内容进行解密,获取数据。
1.2 生成pgp公钥密钥

下载软件的地址:https://files.gpg4win.org/gpg4win-3.1.11.exe

软件名:kleopatra

  • 新建密钥对

pgcrypto加密 java pgp加密工具_sed

输入自定义的名称和邮件地址:

pgcrypto加密 java pgp加密工具_ide_02


点击下一步:

pgcrypto加密 java pgp加密工具_java_03

箭头处输入用于保护密钥的密码,用于在使用密钥进行解密文件时的验证处理。

输入密码,点击ok。密码如果不合乎规定,可能会需要再次确定输入密码,如果符合要求,则不会弹出下面的弹框。

创建成功如下图:

pgcrypto加密 java pgp加密工具_java_04

生成密钥对副本:会导出对应的密钥文件:

-----BEGIN PGP PRIVATE KEY BLOCK-----

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
=r3oi
-----END PGP PRIVATE KEY BLOCK-----

点击完成。

pgcrypto加密 java pgp加密工具_sed_05

点击对应表用户名。

pgcrypto加密 java pgp加密工具_java_06

点击导出,可以得到pgp的公钥文件。

pgcrypto加密 java pgp加密工具_ide_07

复制内容,创建文件,以pgp结尾保存即可。

1.3 对公钥加密的文件进行解密

打开软件kelopatra:点击“解密/校验”

pgcrypto加密 java pgp加密工具_pgcrypto加密 java_08

选择需要解密的文件:

pgcrypto加密 java pgp加密工具_java_09

输入之前设置的密钥保护密码:

pgcrypto加密 java pgp加密工具_pgcrypto加密 java_10

选择导出位置:

pgcrypto加密 java pgp加密工具_pgcrypto加密 java_11

可以在指定位置得到解密的文件。

pgcrypto加密 java pgp加密工具_加密解密_12

1.4 pgp加密的运用

BouncyCastle是一个提供哈希算法和加密算法的第三方库,提供java标准库中没有的算法。

BouncyCastle中的第三方库提供了pgp加密的算法,可以设置参数直接进行调用。

BouncyCastle是一个提供哈希算法和加密算法的第三方库,提供java标准库中没有的算法。

java标准库提供一种标准机制:java.security,允许第三方提供商无缝接入。

//获取pgp公钥对象
    // in指的是公钥对应的输入文件流
    private PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException {
        //对输入文件六进行解码解析
        in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
        //创建公钥环集合对象
        PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in);
        PGPPublicKey key = null;
        //获取公钥环集合中的公钥环,公钥环对象有两个:主密钥和子密钥,需要使用的是子密钥。
        Iterator<PGPPublicKeyRing> rIt = pgpPub.getKeyRings();
        while (key == null && rIt.hasNext()) {
            PGPPublicKeyRing kRing = rIt.next();
            //从公钥环中获取公钥
            Iterator<PGPPublicKey> kIt = kRing.getPublicKeys();
            while (key == null && kIt.hasNext()) {
                PGPPublicKey k = kIt.next();
                //判断密钥是否适合于用于加密
                if (k.isEncryptionKey()) {
                    key = k;
                }
            }
        }
 
        if (key == null) {
            throw new IllegalArgumentException("Can't find encryption key in key ring.");
        }
 
        return key;
    }


    //加密文件
    /*
    * out指的时输出文件流
    * 
    */
    private void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) throws IOException, NoSuchProviderException, PGPException {
        //注册地三方库:BouncyCastle
        Security.addProvider(new BouncyCastleProvider());
 
        if (armor) {
            out = new ArmoredOutputStream(out);
        }
 
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
 		//构造数据发生器
        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
 		//以文字数据包的形式写出所提供的文件
        org.bouncycastle.openpgp.PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
 		//关闭构造器
        comData.close();
 		
        //构造新的数据加密构建器:指定的密码类型
        JcePGPDataEncryptorBuilder c = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC");
 		//实际加密对象
        PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(c);
 		//使用提供的密钥创建加密方法
        JcePublicKeyKeyEncryptionMethodGenerator d = new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom());
 		//实际加密对象设置加密方法
        cPk.addMethod(d);
 		
        byte[] bytes = bOut.toByteArray();
 
        OutputStream cOut = cPk.open(out, bytes.length);
        cOut.write(bytes);
        cOut.close();
        out.close();
    }

关键步骤:

  • 设置使用的第三方库
  • 构造数据发生器,定义文件的导出形式,例如文字数据包的形式。
  • 构造新的数据加密构造器:包括指定的密码类型
  • 使用构造发生器创建实际的加密对象
  • 创建加密方法:指定加密密钥,指定的三方库等
  • 加密对象指定加密方法
  • 使用加密对象进行加密

完整的代码示例:

package com.xx.util.encrypt;
 
import java.io.*;
import java.security.GeneralSecurityException;
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.BCPGOutputStream;
import org.bouncycastle.bcpg.HashAlgorithmTags;
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.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureGenerator;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.PGPUtil;
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
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;
 
 
public class PgpUtils {
    private static PgpUtils INSTANCE = null;
    public static PgpUtils getInstance() {
 
        if (INSTANCE == null) INSTANCE = new PgpUtils();
        return INSTANCE;
    }
 
    private PgpUtils() {
    }
 
 	//获取pgp公钥对象
    // in指的是公钥对应的输入文件流
    private PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException {
        //对输入文件六进行解码解析
        in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
        //创建公钥环集合对象
        PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in);
        PGPPublicKey key = null;
        //获取公钥环集合中的公钥环,公钥环对象有两个:主密钥和子密钥,需要使用的是子密钥。
        Iterator<PGPPublicKeyRing> rIt = pgpPub.getKeyRings();
        while (key == null && rIt.hasNext()) {
            PGPPublicKeyRing kRing = rIt.next();
            //从公钥环中获取公钥
            Iterator<PGPPublicKey> kIt = kRing.getPublicKeys();
            while (key == null && kIt.hasNext()) {
                PGPPublicKey k = kIt.next();
                //判断密钥是否适合于用于加密
                if (k.isEncryptionKey()) {
                    key = k;
                }
            }
        }
 
        if (key == null) {
            throw new IllegalArgumentException("Can't find encryption key in key ring.");
        }
 
        return key;
    }
 
	//获取私钥对象
    private PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) throws IOException, PGPException, NoSuchProviderException {
        //1.输入流文件中获取私钥环集合
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(org.bouncycastle.openpgp.PGPUtil.getDecoderStream(keyIn));
 		//2.通过id获取私钥
        PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
 
        if (pgpSecKey == null) {
            return null;
        }
 		//设置解码器
        PBESecretKeyDecryptor a = new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(pass);
 		//从pgpSeckey对象中通过定义的解码器进行提取pgp私钥
        return pgpSecKey.extractPrivateKey(a);
    }
 
    /**
     * 文件解码
     * decrypt the passed in message stream
     */
    private void decryptFile(InputStream in, OutputStream out, InputStream keyIn, char[] passwd) throws Exception {
        //加载第三方库
        Security.addProvider(new BouncyCastleProvider());
        //获取
        in = org.bouncycastle.openpgp.PGPUtil.getDecoderStream(in);
        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<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;
 
        while (sKey == null && it.hasNext()) {
            pbe = it.next();
            sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd);
        }
 
        if (sKey == null) {
            throw new IllegalArgumentException("Secret key for message not found.");
        }
 
        PublicKeyDataDecryptorFactory b = new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").setContentProvider("BC").build(sKey);
 
        InputStream clear = pbe.getDataStream(b);
 
        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;
            InputStream unc = ld.getInputStream();
            int ch;
            while ((ch = unc.read()) >= 0) {
                out.write(ch);
            }
        } 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()) {
                throw new PGPException("Message failed integrity check");
            }
        }
    }
 
    //加密文件
    /*
    * out指的时输出文件流
    * 
    */
    private void encryptFile(OutputStream out, String fileName, PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck) throws IOException, NoSuchProviderException, PGPException {
        //注册地三方库:BouncyCastle
        Security.addProvider(new BouncyCastleProvider());
 
        if (armor) {
            out = new ArmoredOutputStream(out);
        }
 		//输出文件流
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
 		//构造数据发生器
        PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
 		//设置以文件数据包的形式写出数据
        org.bouncycastle.openpgp.PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
 
        comData.close();
 
        JcePGPDataEncryptorBuilder c = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC");
 		//实际及逆行加密对象
        PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(c);
 		//设置加密的公钥,使用的第三方库的加密方法
        JcePublicKeyKeyEncryptionMethodGenerator d = new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom());
 		//加密对象与加密方法关联
        cPk.addMethod(d);
        byte[] bytes = bOut.toByteArray();
        OutputStream cOut = cPk.open(out, bytes.length);
        cOut.write(bytes);
        cOut.close();
        out.close();
    }
 
 
    private byte[] inputStreamToByteArray(InputStream is) throws IOException {
 
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 
        int nRead;
        byte[] data = new byte[1024];
 
        while ((nRead = is.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
 
        buffer.flush();
 
        return buffer.toByteArray();
    }
 
 
    /**
     * verify the signature in in against the file fileName.
     */
    private boolean verifySignature(String fileName, byte[] b, InputStream keyIn) throws GeneralSecurityException, IOException, PGPException {
        //in = PGPUtil.getDecoderStream(in);
 
        PGPObjectFactory pgpFact = new PGPObjectFactory(b);
        PGPSignatureList p3 = null;
 
        Object o = pgpFact.nextObject();
        if (o instanceof PGPCompressedData) {
            PGPCompressedData c1 = (PGPCompressedData) o;
 
            pgpFact = new PGPObjectFactory(c1.getDataStream());
 
            p3 = (PGPSignatureList) pgpFact.nextObject();
        } else {
            p3 = (PGPSignatureList) o;
        }
 
        PGPPublicKeyRingCollection pgpPubRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
 
 
        InputStream dIn = new BufferedInputStream(new FileInputStream(fileName));
 
        PGPSignature sig = p3.get(0);
        PGPPublicKey key = pgpPubRingCollection.getPublicKey(sig.getKeyID());
 
 
        sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider(new BouncyCastleProvider()), key);
 
        int ch;
        while ((ch = dIn.read()) >= 0) {
            sig.update((byte) ch);
        }
 
        dIn.close();
 
        if (sig.verify()) {
            return true;
        } else {
            return false;
        }
    }
 
    private PGPSecretKey readSecretKey(InputStream input) throws IOException, PGPException {
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(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 = 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.");
    }
 
    private byte[] createSignature(String fileName, InputStream keyIn, char[] pass, boolean armor) throws GeneralSecurityException, IOException, PGPException {
 
 
        PGPSecretKey pgpSecKey = readSecretKey(keyIn);
        PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(new BouncyCastleProvider()).build(pass));
        PGPSignatureGenerator sGen = new PGPSignatureGenerator(new JcaPGPContentSignerBuilder(pgpSecKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1).setProvider(new BouncyCastleProvider()));
 
 
        sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
 
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ArmoredOutputStream aOut = new ArmoredOutputStream(byteOut);
 
 
        BCPGOutputStream bOut = new BCPGOutputStream(byteOut);
 
        InputStream fIn = new BufferedInputStream(new FileInputStream(fileName));
 
        int ch;
        while ((ch = fIn.read()) >= 0) {
            sGen.update((byte) ch);
 
        }
 
        aOut.endClearText();
 
        fIn.close();
 
        sGen.generate().encode(bOut);
 
        if (armor) {
            aOut.close();
        }
 
        return byteOut.toByteArray();
    }
    /**
     * 生成签名文件
     *
     * @param filePath         签名文件路径
     * @param privateKeyPath   私钥路径
     * @param outFilePath      输出证书路径
     *                         证书名称必须与签名文件名称一样 多后缀: .asc
     *                         比如: 签名文件为:di.ova   那么生成的证书必须为: di.ova.asc
     * @param passWord         证书密码
     * @return 证书字节数组
     */
    public static byte[] signatureCreate(String filePath, String privateKeyPath, String outFilePath, String passWord) {
 
        try {
            FileInputStream privKeyIn = new FileInputStream(privateKeyPath);
            FileOutputStream signatureOut = new FileOutputStream(outFilePath);
            byte[] sig = PgpUtils.getInstance().createSignature(filePath, privKeyIn, passWord.toCharArray(), true);
            signatureOut.write(sig);
            signatureOut.flush();
            signatureOut.close();
            privKeyIn.close();
            return sig;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * 签名验证
     *
     * @param filePath        被签名的文件路径
     * @param publicKeyPath   公钥路径
     * @param signFilePath    签名文件路径
     * @return 是否通过
     */
    public static boolean verifySignature(String filePath, String publicKeyPath, String signFilePath) {
        try {
            FileInputStream pubKeyIs = new FileInputStream(publicKeyPath);
            FileInputStream signFile = new FileInputStream(signFilePath);
            byte[] signFileBytes = new byte[signFile.available()];
            signFile.read(signFileBytes);
            final boolean verifyResult = PgpUtils.getInstance().verifySignature(filePath, signFileBytes, pubKeyIs);
            signFile.close();
            pubKeyIs.close();
            return verifyResult;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
 
}