赞
踩
PGP是一种用于数据加密和数字签名的程序,它使得一般人也可以很容易地对数据文件、邮件进行加密;PGP拥有“信任网络(Web of Trust)”的美称。PGP主要的特点是它可以在一个非线程安全的网络环境下,使得从未谋面的人取得信任。这个软件非常好用,迅速流传开来,成了许多程序员的必备工具。但是,它是商业软件,不能自由使用。所以,自由软件基金会决定,开发一个PGP的替代品,取名为GnuPG。这就是GPG的由来。
# 安装gnupg yum install -y gnupg # 验证是否安装成功 gpg --help # 生成密钥 [root@43-c58487531-0048-1226258 ~]# gpg --gen-key gpg (GnuPG) 2.0.22; Copyright (C) 2013 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 1 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 0 Key does not expire at all Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: gpg.test Email address: gpg@test.com Comment: You selected this USER-ID: "gpg.test <gpg@test.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O You need a Passphrase to protect your secret key. We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: key 98B95556 marked as ultimately trusted public and secret key created and signed. gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u pub 2048R/98B95556 2021-04-28 Key fingerprint = C0A1 5063 8F48 FEF4 AE5C 066E F775 9672 98B9 5556 uid gpg.test <gpg@test.com> sub 2048R/8EDF4C6F 2021-04-28 # 查看密钥 [root@43-c58487531-0048-1226258 ~]# gpg --list-keys /root/.gnupg/pubring.gpg ------------------------ pub 4096R/CF8E292A 2014-11-23 uid Pritunl <contact@pritunl.com> sub 4096R/4E47D23D 2014-11-23 pub 2048R/98B95556 2021-04-28 uid gpg.test <gpg@test.com> sub 2048R/8EDF4C6F 2021-04-28 # 导出公钥 gpg --export -a --output 公钥的名称 邮箱地址 [root@43-c58487531-0048-1226258 ~]# gpg --export -a --output gpg.test.asc gpg@test.com # 查看公钥 [root@43-c58487531-0048-1226258 ~]# cat gpg.test.asc -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v2.0.22 (GNU/Linux) mQENBGCJKBIBCAC+M2wf9yXIfyRkFVvAV8CopCjCkL3oUFvyrS9rFD5plmk0vTk2 EN5Lwy3gf+0CYZ5HSKZfh1kbgKx45njX58ojUx+fffDs9aeOaAqnJ4h048Ffcpkq jzVA9clTeN0YB5GBlIYl365lv6S/pIVldMiRUxXt6h2NseI+fXyKsKDbzTBDJUZ5 57bbtCxY8vSqxoqbM6GPthQFRp9nvo52dLfQFJhcBDCPQd4xSG2ciBPvPiHVJUCZ d4qzfoSaHHTPRWAUdiKeFwVMpfYrKtl4ILSnqqxdhSIZhqMZLejH7iOOonUBtxXe 5JlNeFkcqMkYJd6Rw0eRuf0Yh9UnJw2zJjV5ABEBAAG0F2dwZy50ZXN0IDxncGdA dGVzdC5jb20+iQE5BBMBAgAjBQJgiSgSAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwEC HgECF4AACgkQ93WWcpi5VVao5Af+Jb39nhqgBdJneDsh3XU4R7rah4S+Rz6uz/yW Vc1Pfg+ROBXnGU16XYZeQo6CbpOtJ4qE80lqFB1SizVGyoV5gEW0B+VlsvNr9zDQ jLnxx2g7JjL31suiKuXzp+JkMfbxMGtlgQ1nrVl47dvOUEIdSwq7kFWU7em3hK3C 3oNtBKQ1Bjuj+q0LRsTy9rGlb//lqnSGVw/p0dV8+Cq7yYRwjy+9NJkJ+bUPVic2 OSxqQmYSYv3C96k4P333a28C2pS8rrS64qevkdxlcDC9LCfzdDrMv4ABRL8Obk+R rXDjXp81tp0/6Tx/+p5KQOFvxC8nFUMpEgg7yPna/7fJcqpknLkBDQRgiSgSAQgA rGavDyykZ55QN3av0PADboRPEnpbRsGrw1tI5pb3x3fiSAOrkN4MPpXZ65qSbZ7a lIlh8KMOb2TbDvlpYDa+wttJY32tnWnNeFjaeWdPkgf687D78fNw8ofdKbXrwu8r 3tfT82pus+lFA1vZ3CPbN1S/UIIOkajMjQArX/KHmhmYgXuI+f8e0tc1kgWEpJR2 7G0CUHOib5TQShhP+yIiHWxH0+yPALUihNOmQIJhMUGIyRX7wDTvcGRN9rtwFGJ6 gaQUCFVc7FtoOMm1X1oINY6JVIJC+9YO0wANp2lHBSe0M1cb66W2wZWw4MW7ZVMs HmwrcLYCENpu+qBIi+zCbQARAQABiQEfBBgBAgAJBQJgiSgSAhsMAAoJEPd1lnKY uVVWeT8H/2/qfoO6pI0t5An+HIhGVqQ4lxcl9wfkkbztChGY8Zvr2FX9n+wHtRk1 kdRZwbm3EoHZzjkQgNBnCK6qyVszZR3hJV2JnSCqkD5Au9dYj5A2MPqfTe1MlQdM VJV/yIO/3YYUhTDZBu0/YCnWxUNSJwPkH6Xsn/lFeo1vrc/il5i3Nsktk6sDi3n4 /c+Tq5gAn/oa27AuREg1NZQ1nXDQe6hc1iKt/lUi27gvkoHbB0gnkqIT4UiH2R7i A7JRFIcqMKbjWaRm1D5sSa9Zc2mvtvF2MV8/3TMSX+EL94V1UugMkPNyomMXiiOK ym2jZ6RwcWUqlTaTRsMae5mSVLPzBB4= =Jw99 -----END PGP PUBLIC KEY BLOCK-----
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<version>1.50</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
package com.example.util; import java.io.*; import java.security.SecureRandom; import java.security.Security; import java.util.Iterator; import org.apache.commons.io.IOUtils; import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.*; import org.bouncycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; import org.bouncycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; /** * GPG 加密工具类 * * @author jinliang 2021/04/28 */ public class GpgCoderUtil { private static final Logger logger = LoggerFactory.getLogger(GpgCoderUtil.class); /** * GPG 加密 * * @param inputFileName 待加密的文件名 * @param publicKeyFileName 加密的公钥 * @param armor 是否按文本输出 * @return outputFileName 加密后的文件名 */ public static String encryptFile(String inputFileName, String publicKeyFileName, boolean armor) { logger.info("开始进行GPG加密,文件名:{}", inputFileName); Assert.notNull(inputFileName, "待加密的文件名不能为空"); Assert.notNull(publicKeyFileName, "公钥不能为空"); String outputFileName = inputFileName + ".gpg"; //添加BC Security Provider Security.addProvider(new BouncyCastleProvider()); OutputStream outputStream = null; InputStream publicKeyInputStream = null; OutputStream pgpOutputSteam = null; try { outputStream = new BufferedOutputStream(new FileOutputStream(outputFileName)); publicKeyInputStream = new BufferedInputStream(new FileInputStream(publicKeyFileName)); //生成加密的公钥 PGPPublicKey pgpPublicKey = readPublicKey(publicKeyInputStream); //是否按文本输出 if (armor) { outputStream = new ArmoredOutputStream(outputStream); } //将文件压缩,转换为字节流 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); PGPCompressedDataGenerator pgpCompressedDataGenerator = new PGPCompressedDataGenerator(PGPCompressedData.ZIP); PGPUtil.writeFileToLiteralData(pgpCompressedDataGenerator.open(byteArrayOutputStream), PGPLiteralData.BINARY, new File(inputFileName)); pgpCompressedDataGenerator.close(); //构造PGP加密器 JcePGPDataEncryptorBuilder pgpDataEncryptorBuilder = new JcePGPDataEncryptorBuilder(PGPEncryptedData.CAST5) .setWithIntegrityPacket(true).setSecureRandom(new SecureRandom()).setProvider("BC"); PGPEncryptedDataGenerator pgpEncryptedDataGenerator = new PGPEncryptedDataGenerator(pgpDataEncryptorBuilder); JcePublicKeyKeyEncryptionMethodGenerator jcePublicKeyKeyEncryptionMethodGenerator = new JcePublicKeyKeyEncryptionMethodGenerator(pgpPublicKey) .setProvider(new BouncyCastleProvider()).setSecureRandom(new SecureRandom()); pgpEncryptedDataGenerator.addMethod(jcePublicKeyKeyEncryptionMethodGenerator); byte[] bytes = byteArrayOutputStream.toByteArray(); //文件加密,并将结果写入输出流 pgpOutputSteam = pgpEncryptedDataGenerator.open(outputStream, bytes.length); pgpOutputSteam.write(bytes); } catch (Exception e) { logger.error("GPG加密失败,失败原因:{}", e.getMessage()); } finally { //关闭流 IOUtils.closeQuietly(publicKeyInputStream); IOUtils.closeQuietly(outputStream); IOUtils.closeQuietly(pgpOutputSteam); } logger.info("PGP加密成功,加密后的文件名:{}", outputFileName); return outputFileName; } /** * @param in 密钥文件流 * @return 公钥 * @throws IOException * @throws PGPException */ private static PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException { in = 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("在密钥环中找不到加密密钥."); } return key; } }
@Test
public void testGpg() {
// 第一个参数为需要加密的文件,第二个参数为导出的公钥,第三个参数为是否需要文本化输出,true为文本输出,false为二进制输出
GpgCoderUtil.encryptFile("D:\\data\\output\\output.txt","D:\\data\\public\\gpg.test.asc",false);
}
2021-04-28 17:26:30.868 INFO 19884 --- [ main] com.example.util.GpgCoderUtil : 开始进行GPG加密,文件名:D:\data\output\output.txt
2021-04-28 17:26:32.007 INFO 19884 --- [ main] com.example.util.GpgCoderUtil : PGP加密成功,加密后的文件名:D:\data\output\output.txt.gpg
[root@43-c58487531-0048-1226258 ~]# ls -lh total 68K -rw-r--r-- 1 root root 643 Apr 28 17:28 output.txt.gpg #解密 解密时需要输入密码(生成密钥匙时设置的) [root@43-c58487531-0048-1226258 ~]# gpg output.txt.gpg You need a passphrase to unlock the secret key for user: "gpg.test <gpg@test.com>" 2048-bit RSA key, ID 98B95556, created 2021-04-28 gpg: encrypted with 2048-bit RSA key, ID 98B95556, created 2021-04-28 "gpg.test <gpg@test.com>" gpg: [don't know]: invalid packet (ctb=0d) gpg: [don't know]: invalid packet (ctb=0a) gpg: mdc_packet with invalid encoding gpg: decryption failed: Invalid packet gpg: [don't know]: invalid packet (ctb=54) #查看解密后的文件 [root@43-c58487531-0048-1226258 ~]# ls -lh -rw-r--r-- 1 root root 28K Apr 28 17:29 output.txt -rw-r--r-- 1 root root 643 Apr 28 17:28 output.txt.gpg
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。