1.PGP加密
1.1 简介
PGP:Pretty Good Policy,良好隐私密码法,是一套用于消息加密、验证的应用程序。
加密发送一个文件:
- 获取pgp公钥进行加密文件内容,发送给指定用户。
- 用户获取文件之后,用对应密钥对文件内容进行解密,获取数据。
1.2 生成pgp公钥密钥
下载软件的地址:https://files.gpg4win.org/gpg4win-3.1.11.exe
软件名:kleopatra
- 新建密钥对
输入自定义的名称和邮件地址:
点击下一步:
箭头处输入用于保护密钥的密码,用于在使用密钥进行解密文件时的验证处理。
输入密码,点击ok。密码如果不合乎规定,可能会需要再次确定输入密码,如果符合要求,则不会弹出下面的弹框。
创建成功如下图:
生成密钥对副本:会导出对应的密钥文件:
-----BEGIN PGP PRIVATE KEY BLOCK-----
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
=r3oi
-----END PGP PRIVATE KEY BLOCK-----
点击完成。
点击对应表用户名。
点击导出,可以得到pgp的公钥文件。
复制内容,创建文件,以pgp结尾保存即可。
1.3 对公钥加密的文件进行解密
打开软件kelopatra:点击“解密/校验”
选择需要解密的文件:
输入之前设置的密钥保护密码:
选择导出位置:
可以在指定位置得到解密的文件。
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;
}
}
}