基于Java Bouncy Castle的PGP加密解密示例1

GPG文件加解密 百科及教程:

http://www.ruanyifeng.com/blog/2013/07/gpg.html

http://www.alexgao.com/2009/01/24/gpg/

 

pom:

 

<dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpg-jdk15on</artifactId>
        </dependency>

 

 

 

 

 

UTIL 工具类:

 

package util;


import org.apache.commons.io.FileUtils;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
import org.bouncycastle.openpgp.operator.bc.BcPublicKeyDataDecryptorFactory;

import java.io.*;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Iterator;

public class PGPUtils {

    private static final int BUFFER_SIZE = 1 << 16; // should always be power of 2
    private static final int KEY_FLAGS = 27;
    private static final int[] MASTER_KEY_CERTIFICATION_TYPES = new int[]{
            PGPSignature.POSITIVE_CERTIFICATION,
            PGPSignature.CASUAL_CERTIFICATION,
            PGPSignature.NO_CERTIFICATION,
            PGPSignature.DEFAULT_CERTIFICATION
    };

    @SuppressWarnings("unchecked")
    public static PGPPublicKey readPublicKey(InputStream in)
            throws IOException, PGPException {
        PGPPublicKeyRingCollection keyRingCollection = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(in));
        //
        // 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.
        //
        PGPPublicKey publicKey = null;

        // iterate through the key rings.
        Iterator<PGPPublicKeyRing> rIt = keyRingCollection.getKeyRings();

        while (publicKey == null && rIt.hasNext()) {
            PGPPublicKeyRing kRing = rIt.next();
            Iterator<PGPPublicKey> kIt = kRing.getPublicKeys();
            while (publicKey == null && kIt.hasNext()) {
                PGPPublicKey key = kIt.next();
                if (key.isEncryptionKey()) {
                    publicKey = key;
                }
            }
        }
        if (publicKey == null) {
            throw new IllegalArgumentException("Can't find public key in the key ring.");
        }
        if (!isForEncryption(publicKey)) {
            throw new IllegalArgumentException("KeyID " + publicKey.getKeyID() + " not flagged for encryption.");
        }

        return publicKey;
    }

    @SuppressWarnings("unchecked")
    public static PGPSecretKey readSecretKey(InputStream in)
            throws IOException, PGPException {

        PGPSecretKeyRingCollection keyRingCollection = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(in));
        PGPSecretKey secretKey = null;
        Iterator<PGPSecretKeyRing> rIt = keyRingCollection.getKeyRings();
        while (secretKey == null && rIt.hasNext()) {
            PGPSecretKeyRing keyRing = rIt.next();
            Iterator<PGPSecretKey> kIt = keyRing.getSecretKeys();
            while (secretKey == null && kIt.hasNext()) {
                PGPSecretKey key = kIt.next();
                if (key.isSigningKey()) {
                    secretKey = key;
                }
            }
        }
        // Validate secret key
        if (secretKey == null) {
            throw new IllegalArgumentException("Can't find private key in the key ring.");
        }
        if (!secretKey.isSigningKey()) {
            throw new IllegalArgumentException("Private key does not allow signing.");
        }

        if (secretKey.getPublicKey().isRevoked()) {
            throw new IllegalArgumentException("Private key has been revoked.");
        }

        if (!hasKeyFlags(secretKey.getPublicKey(), KeyFlags.SIGN_DATA)) {
            throw new IllegalArgumentException("Key cannot be used for signing.");
        }
        return secretKey;

    }

    /**
     * Load a secret key ring collection from keyIn and find the private key corresponding to
     * keyID if it exists.
     * <p/>
     *
     * @param keyIn input stream representing a key ring collection.
     * @param keyID keyID we want.
     * @param pass  passphrase to decrypt secret key with.
     * @return 156
     * @throws IOException             157
     * @throws PGPException            158
     * @throws NoSuchProviderException 159
     */

    public static PGPPrivateKey findPrivateKey(InputStream keyIn, long keyID, char[] pass)
            throws IOException, PGPException, NoSuchProviderException
    {
        PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
        return findPrivateKey(pgpSec.getSecretKey(keyID), pass);

    }

    /**
     * 169
     * Load a secret key and find the private key in it
     * 170
     *
     * @param pgpSecKey The secret key
     * @param pass      passphrase to decrypt secret key with
     * @throws PGPException
     */
    public static PGPPrivateKey findPrivateKey(PGPSecretKey pgpSecKey, char[] pass)
            throws PGPException {
        if (pgpSecKey == null) return null;
        PBESecretKeyDecryptor decryptor = new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass);
        return pgpSecKey.extractPrivateKey(decryptor);
    }

    @SuppressWarnings("unchecked")
    public static 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();
        }
        Iterator<PGPPublicKeyEncryptedData> it = enc.getEncryptedDataObjects();
        PGPPrivateKey sKey = null;
        PGPPublicKeyEncryptedData pbe = null;

        while (sKey == null && it.hasNext()) {
            pbe = it.next();
            sKey = findPrivateKey(keyIn, pbe.getKeyID(), passwd);
        }

        if (sKey == null) {
            throw new IllegalArgumentException("Secret key for message not found.");
        }

        InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(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;
            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");
            }
        }
    }

    /**
     * From LockBox Lobs PGP Encryption tools.
     * http://www.lockboxlabs.org/content/downloads
     * <p/>
     * I didn't think it was worth having to import a 4meg lib for three methods
     */

    public static boolean isForEncryption(PGPPublicKey key) {
        if (key.getAlgorithm() == PublicKeyAlgorithmTags.RSA_SIGN
                || key.getAlgorithm() == PublicKeyAlgorithmTags.DSA
                || key.getAlgorithm() == PublicKeyAlgorithmTags.EC
                || key.getAlgorithm() == PublicKeyAlgorithmTags.ECDSA) {
            return false;
        }
        return hasKeyFlags(key, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
    }


    /**
     * From LockBox Lobs PGP Encryption tools.
     * http://www.lockboxlabs.org/content/downloads
     * <p/>
     * I didn't think it was worth having to import a 4meg lib for three methods
     */
    @SuppressWarnings("unchecked")
    private static boolean hasKeyFlags(PGPPublicKey encKey, int keyUsage) {
        if (encKey.isMasterKey()) {
            for (int i = 0; i != PGPUtils.MASTER_KEY_CERTIFICATION_TYPES.length; i++) {
                for (Iterator<PGPSignature> eIt = encKey.getSignaturesOfType(PGPUtils.MASTER_KEY_CERTIFICATION_TYPES[i]); eIt.hasNext(); ) {
                    PGPSignature sig = eIt.next();
                    if (!isMatchingUsage(sig, keyUsage)) {
                        return false;
                    }
                }
            }
        } else {
            for (Iterator<PGPSignature> eIt = encKey.getSignaturesOfType(PGPSignature.SUBKEY_BINDING); eIt.hasNext(); ) {
                PGPSignature sig = eIt.next();
                if (!isMatchingUsage(sig, keyUsage)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * From LockBox Lobs PGP Encryption tools.
     * http://www.lockboxlabs.org/content/downloads
     * <p/>
     * I didn't think it was worth having to import a 4meg lib for three methods
     */
    private static boolean isMatchingUsage(PGPSignature sig, int keyUsage) {
        if (sig.hasSubpackets()) {
            PGPSignatureSubpacketVector sv = sig.getHashedSubPackets();
            if (sv.hasSubpacket(PGPUtils.KEY_FLAGS)) {
                // code fix suggested by kzt (see comments)
                if ((sv.getKeyFlags() == 0 && keyUsage == 0)) {
                    return false;
                }
            }
        }
        return true;
    }

    public static void main(String[] args) throws Exception {
        FileInputStream in = new FileInputStream("/Users/fusheng/Desktop/DPXK_EBC17030001_14_20170306_26_1.csv.gpg");
        File keyInFile = new File("/Users/fusheng/Desktop/xieyuanshun.asc");
        FileInputStream keyIn = new FileInputStream(keyInFile);
        File outputFile = File.createTempFile("CITIC_DECRYPTED", ".csv");
        FileOutputStream out = new FileOutputStream(outputFile);
        PGPUtils.decryptFile(in, out, keyIn, "1qaz2wsx".toCharArray());
        System.out.println(FileUtils.readFileToString(outputFile));
    }
}

 

 

 

 

 

使用密钥解密文件并读取数据:

 

if (!"gpg".equalsIgnoreCase(FilenameUtils.getExtension(file.getName()))) {
                continue;
            }

            FileInputStream in = new FileInputStream(file);
            File keyInFile = new File("/Users/fusheng/Desktop/xieyuanshun.asc");
            FileInputStream keyIn = new FileInputStream(keyInFile);
            File outputFile = File.createTempFile("CITIC_DECRYPTED", ".csv");
            FileOutputStream out = new FileOutputStream(outputFile);
            PGPUtils.decryptFile(in, out, keyIn, "1qaz2wsx".toCharArray());

            List<File> fileLST = new ArrayList<>();
            fileLST.add(file);
            List<String> referenceIds = FileUtils.readLines(outputFile);

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PGP(Pretty Good Privacy)是一种加密和签名数据的标准,它使用了非对称加密算法和对称加密算法。下面是 PGP 加密解密Java 代码示例PGP 加密过程: ```java import java.io.*; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Date; import org.bouncycastle.bcpg.*; import org.bouncycastle.openpgp.*; import org.bouncycastle.openpgp.bc.*; import org.bouncycastle.openpgp.jcajce.*; import org.bouncycastle.openpgp.operator.bc.*; import org.bouncycastle.util.io.*; public class PgpEncrypt { public static void encrypt(String inputFile, String publicKeyFile, String outputFile) { try { Security.addProvider(new BouncyCastleProvider()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZIP); OutputStream compressedDataStream = compressedDataGenerator.open(baos); PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator(); OutputStream literalDataStream = literalDataGenerator.open(compressedDataStream, PGPLiteralData.BINARY, inputFile, new Date(), new byte[4096]); FileInputStream publicKeyInputStream = new FileInputStream(publicKeyFile); byte[] publicKeyBytes = new byte[publicKeyInputStream.available()]; publicKeyInputStream.read(publicKeyBytes); publicKeyInputStream.close(); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5).setWithIntegrityPacket(true).setSecureRandom(new SecureRandom()).setProvider("BC")); encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(publicKey).setProvider("BC")); OutputStream encryptedDataStream = encryptedDataGenerator.open(literalDataStream, new byte[4096]); FileInputStream inputStream = new FileInputStream(inputFile); IOUtils.copy(inputStream, encryptedDataStream); inputStream.close(); encryptedDataStream.close(); literalDataStream.close(); literalDataGenerator.close(); compressedDataStream.close(); compressedDataGenerator.close(); FileOutputStream encryptedOutputStream = new FileOutputStream(outputFile); encryptedOutputStream.write(baos.toByteArray()); encryptedOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` PGP 解密过程: ```java import java.io.*; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.bouncycastle.bcpg.*; import org.bouncycastle.openpgp.*; import org.bouncycastle.openpgp.bc.*; import org.bouncycastle.openpgp.jcajce.*; import org.bouncycastle.util.io.*; public class PgpDecrypt { public static void decrypt(String inputFile, String privateKeyFile, String privateKeyPassword, String outputFile) { try { Security.addProvider(new BouncyCastleProvider()); FileInputStream inputStream = new FileInputStream(inputFile); PGPObjectFactory objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(inputStream), new BcKeyFingerprintCalculator()); Object object = objectFactory.nextObject(); PGPEncryptedDataList encryptedDataList = null; if (object instanceof PGPEncryptedDataList) { encryptedDataList = (PGPEncryptedDataList) object; } else { encryptedDataList = (PGPEncryptedDataList) objectFactory.nextObject(); } Iterator<PGPPublicKeyEncryptedData> iterator = encryptedDataList.getEncryptedDataObjects(); PGPPrivateKey privateKey = null; PGPPublicKeyEncryptedData encryptedData = null; while (privateKey == null && iterator.hasNext()) { encryptedData = iterator.next(); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(IOUtils.toByteArray(new FileInputStream(privateKeyFile))); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKeyObj = keyFactory.generatePrivate(pkcs8EncodedKeySpec); if (encryptedData.getKeyID() == privateKeyObj.getEncoded()) { privateKey = new JcePGPKeyConverter().getPGPPrivateKey(encryptedData.getKeyAlgorithm(), privateKeyObj); } } if (privateKey == null) { throw new IllegalArgumentException("Can't find private key with ID " + encryptedData.getKeyID()); } InputStream decryptedDataStream = encryptedData.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(privateKey)); PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(decryptedDataStream, new BcKeyFingerprintCalculator()); Object message = pgpObjectFactory.nextObject(); if (message instanceof PGPCompressedData) { PGPCompressedData compressedData = (PGPCompressedData) message; pgpObjectFactory = new PGPObjectFactory(compressedData.getDataStream(), new BcKeyFingerprintCalculator()); message = pgpObjectFactory.nextObject(); } PGPLiteralData literalData = (PGPLiteralData) message; InputStream literalDataStream = literalData.getInputStream(); FileOutputStream outputStream = new FileOutputStream(outputFile); IOUtils.copy(literalDataStream, outputStream); outputStream.close(); literalDataStream.close(); decryptedDataStream.close(); inputStream.close(); } catch (Exception e) { e.printStackTrace(); } } } ``` 上面的代码使用了 Bouncy Castle 库来实现 PGP 加密解密。需要注意的是,加密和解密时需要用到公钥和私钥,这里的公钥和私钥是以文件形式存储的,需要读取文件并转换成相应的对象使用。另外,解密时还需要输入私钥的密码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值