PGP加解密

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

 

 


前言

PGP加解密
 


 

一、PGP是什么?

PGP全称 Pretty Good Privacy, 由Phil Zimmermann在1991年开发,开源后由各个组织开发过不同版本的PGP实现,后由IETF成立OPenPGP工作组并统一制定了一套标准,也是本文中使用的版本。

  • PGP:由Phil Zimmermann开发,最终被赛门铁克收购,被收购后是一个商业软件,需要付费。

  • OpenPGP:由开源组织规范的PGP协议,定义了加密消息、签名、私钥和用于交换公钥的证书统一标准。

  • GPG(GnuPG):符合OpenPGP标准的开源加密软件,PGP的开源实现。

二、使用步骤

1.引入库

使用maven引入库

<!--空气城堡的加解密库类-->
<dependency>
   <groupId>org.bouncycastle</groupId>
   <artifactId>bcpg-jdk15on</artifactId>
   <version>1.66</version>
</dependency>
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15on</artifactId>
	<version>1.66</version>
</dependency>
<!--工具集,非必须-->
<dependency>
   <groupId>name.neuhalfen.projects.crypto.bouncycastle.openpgp</groupId>
   <artifactId>bouncy-gpg</artifactId>
   <version>2.2.0</version>
</dependency>
<!--断言工具,非必须-->
<dependency>
   <groupId>org.assertj</groupId>
   <artifactId>assertj-core</artifactId>
   <version>3.16.1</version>
</dependency>

2.生成秘钥对

private static BouncyCastleProvider provider;
private static SecureRandom secureRandom;

static {
    provider = new BouncyCastleProvider();
    secureRandom = new SecureRandom();
    Security.addProvider(provider);
}
/**
 * <pre>
 *     to generate PGP key pairs.
 *     usage:  generatePGPKeyPair(2048, true, "tom", "my pass", "/www/pub", "/www/pri");
 *     return key pairs, str[0]=publicKey, str[1]=privateKey.
 *     if armor, return armored key string, if unarmored, return key path.
 * </pre>
 *
 * @param keyWidth   key width, 1024/2048/3072/4096, recommend 2048
 * @param armor      designate if key format with armored or not
 * @param identity   key holder's identity, recommend write as email
 * @param passPhrase password to open private key
 * @return return key pairs, str[0]=publicKey, str[1]=privateKey.
 * @throws Exception
 */
public static String[] generatePGPKeyPair(int keyWidth, boolean armor, String identity, String passPhrase,
                                          String pubKeyFile, String priKeyFile) throws Exception {
    KeyPairGenerator var1 = KeyPairGenerator.getInstance(MyPGPUtil.RSA, MyPGPUtil.PROVIDER_BC);
    var1.initialize(keyWidth);
    KeyPair var2 = var1.generateKeyPair();
    OutputStream var3;
    OutputStream var4;
    try (ByteArrayOutputStream pubKeyOut = new ByteArrayOutputStream();
         ByteArrayOutputStream priKeyOut = new ByteArrayOutputStream();
    ) {
        if (armor) {
            // key format with armored
            var3 = new ArmoredOutputStream(priKeyOut);
            var4 = new ArmoredOutputStream(pubKeyOut);
        } else {
            // key format without armored
            var3 = new FileOutputStream(priKeyFile);
            var4 = new FileOutputStream(pubKeyFile);
        }
        // the pass phrase for open private key
        char[] var11 = passPhrase.toCharArray();
        PGPDigestCalculator var6 = (new JcaPGPDigestCalculatorProviderBuilder()).build().get(2);
        JcaPGPKeyPair var7 = new JcaPGPKeyPair(1, var2, new Date());
        PGPSecretKey var8 = new PGPSecretKey(16, var7, identity, var6, (PGPSignatureSubpacketVector) null,
                (PGPSignatureSubpacketVector) null, new JcaPGPContentSignerBuilder(var7.getPublicKey().getAlgorithm(), 8),
                (new JcePBESecretKeyEncryptorBuilder(3, var6)).setProvider(MyPGPUtil.PROVIDER_BC).build(var11));
        var8.encode(var3);
        (var3).close();
        PGPPublicKey var9 = var8.getPublicKey();
        var9.encode(var4);
        (var4).close();
        // build return result
        String[] keyPair = new String[2];
        if (armor) {
            keyPair[0] = pubKeyOut.toString();
            keyPair[1] = priKeyOut.toString();
        } else {
            keyPair[0] = pubKeyFile;
            keyPair[1] = priKeyFile;
        }
        return keyPair;
    }
}

3. 加密并签名

使用接收者的公钥加密,使用发送者的私钥签名

import java.io.*;
import java.security.*;
import java.util.Date;
import java.util.Iterator;

import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import o
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
关于 JavaPGP 加解密,你可以使用 Bouncy Castle 库来实现。下面是一个简单的示例代码: ```java import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.openpgp.*; import java.io.*; public class PgpExample { public static void main(String[] args) throws Exception { // 加密 String publicKeyFile = "public.key"; String inputFile = "input.txt"; String outputFile = "encrypted.pgp"; encryptFile(publicKeyFile, inputFile, outputFile); // 解密 String privateKeyFile = "private.key"; String passphrase = "your-passphrase"; String decryptedFile = "decrypted.txt"; decryptFile(outputFile, privateKeyFile, passphrase, decryptedFile); } public static void encryptFile(String publicKeyFile, String inputFile, String outputFile) throws Exception { FileInputStream publicKeyStream = new FileInputStream(publicKeyFile); FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(outputFile); encryptStream(publicKeyStream, inputStream, outputStream); } public static void encryptStream(InputStream publicKeyStream, InputStream inputStream, OutputStream outputStream) throws Exception { Security.addProvider(new BouncyCastleProvider()); PGPPublicKey publicKey = readPublicKey(publicKeyStream); outputStream = new ArmoredOutputStream(outputStream); PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator( new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5) .setWithIntegrityPacket(true) .setSecureRandom(new SecureRandom()) .setProvider("BC")); encryptedDataGenerator.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(publicKey)); OutputStream encryptedOutputStream = encryptedDataGenerator.open(outputStream, new byte[4096]); PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator(PGPCompressedData.ZIP); PGPUtil.writeFileToLiteralData(compressedDataGenerator.open(encryptedOutputStream), PGPLiteralData.BINARY, new File(inputFile)); compressedDataGenerator.close(); encryptedOutputStream.close(); outputStream.close(); } public static void decryptFile(String inputFile, String privateKeyFile, String passphrase, String decryptedFile) throws Exception { FileInputStream privateKeyStream = new FileInputStream(privateKeyFile); FileInputStream inputStream = new FileInputStream(inputFile); FileOutputStream outputStream = new FileOutputStream(decryptedFile); decryptStream(privateKeyStream, passphrase.toCharArray(), inputStream, outputStream); } public static void decryptStream(InputStream privateKeyStream, char[] passphrase, InputStream inputStream, OutputStream outputStream) throws Exception { Security.addProvider(new BouncyCastleProvider()); PGPPrivateKey privateKey = readPrivateKey(privateKeyStream); inputStream = PGPUtil.getDecoderStream(inputStream); JcaPGPObjectFactory pgpObjectFactory = new JcaPGPObjectFactory(inputStream); PGPEncryptedDataList encryptedDataList; Object object = pgpObjectFactory.nextObject(); if (object instanceof PGPEncryptedDataList) { encryptedDataList = (PGPEncryptedDataList) object; } else { encryptedDataList = (PGPEncryptedDataList) pgpObjectFactory.nextObject(); } Iterator<?> encryptedDataObjects = encryptedDataList.getEncryptedDataObjects(); PGPPrivateKey foundPrivateKey = null; PGPPublicKeyEncryptedData encryptedData = null; while (foundPrivateKey == null && encryptedDataObjects.hasNext()) { encryptedData = (PGPPublicKeyEncryptedData) encryptedDataObjects.next(); foundPrivateKey = findPrivateKey(privateKey, encryptedData.getKeyID(), passphrase); } if (foundPrivateKey == null) { throw new IllegalArgumentException("Private key for message not found."); } InputStream decryptedInputStream = encryptedData.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(foundPrivateKey)); PGPObjectFactory pgpObjectFactory2 = new JcaPGPObjectFactory(decryptedInputStream); Object message = pgpObjectFactory2.nextObject(); if (message instanceof PGPCompressedData) { PGPCompressedData compressedData = (PGPCompressedData) message; pgpObjectFactory2 = new JcaPGPObjectFactory(compressedData.getDataStream()); message = pgpObjectFactory2.nextObject(); } if (message instanceof PGPLiteralData) { PGPLiteralData literalData = (PGPLiteralData) message; InputStream literalInputStream = literalData.getInputStream(); int ch; while ((ch = literalInputStream.read()) >= 0) { outputStream.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 (encryptedData.isIntegrityProtected()) { if (!encryptedData.verify()) { throw new PGPException("Message failed integrity check."); } } } public static PGPPublicKey readPublicKey(InputStream inputStream) throws IOException, PGPException { inputStream = PGPUtil.getDecoderStream(inputStream); JcaPGPPublicKeyRingCollection publicKeyRingCollection = new JcaPGPPublicKeyRingCollection(inputStream); Iterator<PGPPublicKeyRing> publicKeyRings = publicKeyRingCollection.getKeyRings(); while (publicKeyRings.hasNext()) { PGPPublicKeyRing publicKeyRing = publicKeyRings.next(); Iterator<PGPPublicKey> publicKeys = publicKeyRing.getPublicKeys(); while (publicKeys.hasNext()) { PGPPublicKey publicKey = publicKeys.next(); if (publicKey.isEncryptionKey()) { return publicKey; } } } throw new IllegalArgumentException("Can't find encryption key in key ring."); } public static PGPPrivateKey readPrivateKey(InputStream inputStream) throws IOException, PGPException { inputStream = PGPUtil.getDecoderStream(inputStream); JcaPGPSecretKeyRingCollection secretKeyRingCollection = new JcaPGPSecretKeyRingCollection(inputStream); Iterator<PGPSecretKeyRing> secretKeyRings = secretKeyRingCollection.getKeyRings(); while (secretKeyRings.hasNext()) { PGPSecretKeyRing secretKeyRing = secretKeyRings.next(); Iterator<PGPSecretKey> secretKeys = secretKeyRing.getSecretKeys(); while (secretKeys.hasNext()) { PGPSecretKey secretKey = secretKeys.next(); if (secretKey.isSigningKey()) { PGPPrivateKey privateKey = secretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build("your-passphrase".toCharArray())); return privateKey; } } } throw new IllegalArgumentException("Can't find signing key in key ring."); } public static PGPPrivateKey findPrivateKey(PGPSecretKey secretKey, long keyID, char[] passphrase) throws PGPException { PBESecretKeyDecryptor decryptor = new JcePBESecretKeyDecryptorBuilder().setProvider("BC").build(passphrase); return secretKey.extractPrivateKey(decryptor); } } ``` 在上面的示例代码中,你需要替换以下部分: - `publicKeyFile`:公钥文件的路径 - `privateKeyFile`:私钥文件的路径 - `inputFile`:要加密的输入文件的路径 - `outputFile`:加密后的输出文件的路径 - `decryptedFile`:解密后的输出文件的路径 - `passphrase`:私钥的密码 请确保你已经安装了 Bouncy Castle 库,并将其添加到你的项目中。你可以从 Bouncy Castle 官方网站下载库文件并将其添加到你的项目中,或者使用 Maven/Gradle 等构建工具来添加依赖。 希望这个示例能帮助到你进行 Java PGP 加解密。如果有任何问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值