Bouncycastle pgp 解密大小正确但全部空白
当我调用它时,它成功加密了我的字符串,但解密文本的输出为空。我没有收到任何错误,并且输出字符串的 byteArray 的长度正确 (102),但它只是 102 个零。这是改编自 KeyBasedFileProcessor 示例,但尝试基于流/字符串而不是基于文件。
package com.common.security.pgp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Date;
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.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.PGPLiteralDataGenerator;
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.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
/**
* A simple utility class that encrypts/decrypts public key based encryption
* files.
* <p>
* To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.<br>
* If -a is specified the output file will be "ascii-armored". If -i is
* specified the output file will be have integrity checking added.
* <p>
* To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.
* <p>
* Note 1: this example will silently overwrite files, nor does it pay any
* attention to the specification of "_CONSOLE" in the filename. It also expects
* that a single pass phrase will have been used.
* <p>
* Note 2: if an empty file name has been specified in the literal data object
* contained in the encrypted packet a file with the name filename.out will be
* generated in the current working directory.
*/
public class PgpEncryption3 {
/**
* A simple routine that opens a key ring file and loads the first available
* key suitable for encryption.
*
* @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);
//
// 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.
//
//
// iterate through the key rings.
//
Iterator rIt = pgpPub.getKeyRings();
while (rIt.hasNext()) {
PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next();
Iterator kIt = kRing.getPublicKeys();
while (kIt.hasNext()) {
PGPPublicKey k = (PGPPublicKey) kIt.next();
if (k.isEncryptionKey()) {
return k;
}
}
}
throw new IllegalArgumentException(
"Can't find encryption key in key ring.");
}
/**
* Search a secret key ring collection for a secret key corresponding to
* keyID if it exists.
*
* @param pgpSec
* a secret key ring collection.
* @param keyID
* keyID we want.
* @param pass
* passphrase to decrypt secret key with.
* @return
* @throws PGPException
* @throws NoSuchProviderException
*/
private static PGPPrivateKey findSecretKey(
PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass)
throws PGPException, NoSuchProviderException {
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null) {
return null;
}
return pgpSecKey.extractPrivateKey(pass, "BC");
}
/**
* decrypt the passed in message stream
*/
private static void decryptFile(InputStream in, InputStream keyIn,
char[] passwd, String defaultFileName, OutputStream out) throws Exception {
in = PGPUtil.getDecoderStream(in);
try {
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 it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(keyIn));
while (sKey == null && it.hasNext()) {
pbe = (PGPPublicKeyEncryptedData) it.next();
sKey = findSecretKey(pgpSec, pbe.getKeyID(), passwd);
}
if (sKey == null) {
throw new IllegalArgumentException(
"secret key for message not found.");
}
InputStream clear = pbe.getDataStream(sKey, "BC");
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) {
System.out.println(message);
PGPLiteralData ld = (PGPLiteralData) message;
System.out.println(ld.getFileName());
System.out.println(ld.getDataStream());
InputStream unc = ld.getInputStream();
int ch;
while ((ch = unc.read()) >= 0) {
System.out.println(ch);
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()) {
System.err.println("message failed integrity check");
} else {
System.err.println("message integrity check passed");
}
} else {
System.err.println("no message integrity check");
}
} catch (PGPException e) {
System.err.println(e);
if (e.getUnderlyingException() != null) {
e.getUnderlyingException().printStackTrace();
}
}
}
public static void writeStreamToLiteralData(OutputStream out,
char fileType, byte[] data, String fileName, Date modDate) throws IOException {
PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
OutputStream pOut = lData.open(out, fileType, fileName, data.length, modDate);
byte[] buf = new byte[4096];
ByteArrayInputStream in = new ByteArrayInputStream(buf);
int len;
while ((len = in.read(buf)) > 0) {
pOut.write(buf, 0, len);
}
lData.close();
in.close();
}
private static void encryptFile(OutputStream out, byte[] data,String fileName,
PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck, Date modDate)
throws IOException, NoSuchProviderException {
if (armor) {
out = new ArmoredOutputStream(out);
}
try {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
writeStreamToLiteralData(bOut,PGPLiteralData.TEXT, data, fileName,modDate);
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(
PGPEncryptedData.CAST5, withIntegrityCheck,
new SecureRandom(), "BC");
cPk.addMethod(encKey);
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes);
cOut.close();
out.close();
} catch (PGPException e) {
System.err.println(e);
if (e.getUnderlyingException() != null) {
e.getUnderlyingException().printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
Date modDate = new Date();
String dataToEncrypt = "THIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXT";
System.out.println(dataToEncrypt.length());
byte[] data = dataToEncrypt.getBytes();
String fileName = "blah.txt";
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream pKeyIn = new FileInputStream("/Users/me/blah.pub.key");
encryptFile(out, data, fileName,readPublicKey(pKeyIn), true, false,modDate);
System.out.println(new String(out.toByteArray()));
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
System.out.println(in);
FileInputStream sKeyIn = new FileInputStream("/Users/me/blah.sec.key");
ByteArrayOutputStream decOut = new ByteArrayOutputStream();
decryptFile(in, sKeyIn, "mypass".toCharArray(), "blah.txt", decOut);
System.out.println(decOut.toByteArray().length);
System.out.println(new String(decOut.toByteArray()));
}
}
When I call this, it successfully encrypts my string but the output of the decrypted text is blank. I get no errors and the byteArray of the output string is of the correct lenth (102), however it's just 102 zeros. This is adapted from the KeyBasedFileProcessor example but is attempting to be stream/string based instead of file based.
package com.common.security.pgp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Date;
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.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.PGPLiteralDataGenerator;
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.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
/**
* A simple utility class that encrypts/decrypts public key based encryption
* files.
* <p>
* To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.<br>
* If -a is specified the output file will be "ascii-armored". If -i is
* specified the output file will be have integrity checking added.
* <p>
* To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.
* <p>
* Note 1: this example will silently overwrite files, nor does it pay any
* attention to the specification of "_CONSOLE" in the filename. It also expects
* that a single pass phrase will have been used.
* <p>
* Note 2: if an empty file name has been specified in the literal data object
* contained in the encrypted packet a file with the name filename.out will be
* generated in the current working directory.
*/
public class PgpEncryption3 {
/**
* A simple routine that opens a key ring file and loads the first available
* key suitable for encryption.
*
* @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);
//
// 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.
//
//
// iterate through the key rings.
//
Iterator rIt = pgpPub.getKeyRings();
while (rIt.hasNext()) {
PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next();
Iterator kIt = kRing.getPublicKeys();
while (kIt.hasNext()) {
PGPPublicKey k = (PGPPublicKey) kIt.next();
if (k.isEncryptionKey()) {
return k;
}
}
}
throw new IllegalArgumentException(
"Can't find encryption key in key ring.");
}
/**
* Search a secret key ring collection for a secret key corresponding to
* keyID if it exists.
*
* @param pgpSec
* a secret key ring collection.
* @param keyID
* keyID we want.
* @param pass
* passphrase to decrypt secret key with.
* @return
* @throws PGPException
* @throws NoSuchProviderException
*/
private static PGPPrivateKey findSecretKey(
PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass)
throws PGPException, NoSuchProviderException {
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null) {
return null;
}
return pgpSecKey.extractPrivateKey(pass, "BC");
}
/**
* decrypt the passed in message stream
*/
private static void decryptFile(InputStream in, InputStream keyIn,
char[] passwd, String defaultFileName, OutputStream out) throws Exception {
in = PGPUtil.getDecoderStream(in);
try {
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 it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(keyIn));
while (sKey == null && it.hasNext()) {
pbe = (PGPPublicKeyEncryptedData) it.next();
sKey = findSecretKey(pgpSec, pbe.getKeyID(), passwd);
}
if (sKey == null) {
throw new IllegalArgumentException(
"secret key for message not found.");
}
InputStream clear = pbe.getDataStream(sKey, "BC");
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) {
System.out.println(message);
PGPLiteralData ld = (PGPLiteralData) message;
System.out.println(ld.getFileName());
System.out.println(ld.getDataStream());
InputStream unc = ld.getInputStream();
int ch;
while ((ch = unc.read()) >= 0) {
System.out.println(ch);
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()) {
System.err.println("message failed integrity check");
} else {
System.err.println("message integrity check passed");
}
} else {
System.err.println("no message integrity check");
}
} catch (PGPException e) {
System.err.println(e);
if (e.getUnderlyingException() != null) {
e.getUnderlyingException().printStackTrace();
}
}
}
public static void writeStreamToLiteralData(OutputStream out,
char fileType, byte[] data, String fileName, Date modDate) throws IOException {
PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
OutputStream pOut = lData.open(out, fileType, fileName, data.length, modDate);
byte[] buf = new byte[4096];
ByteArrayInputStream in = new ByteArrayInputStream(buf);
int len;
while ((len = in.read(buf)) > 0) {
pOut.write(buf, 0, len);
}
lData.close();
in.close();
}
private static void encryptFile(OutputStream out, byte[] data,String fileName,
PGPPublicKey encKey, boolean armor, boolean withIntegrityCheck, Date modDate)
throws IOException, NoSuchProviderException {
if (armor) {
out = new ArmoredOutputStream(out);
}
try {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
writeStreamToLiteralData(bOut,PGPLiteralData.TEXT, data, fileName,modDate);
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(
PGPEncryptedData.CAST5, withIntegrityCheck,
new SecureRandom(), "BC");
cPk.addMethod(encKey);
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes);
cOut.close();
out.close();
} catch (PGPException e) {
System.err.println(e);
if (e.getUnderlyingException() != null) {
e.getUnderlyingException().printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
Date modDate = new Date();
String dataToEncrypt = "THIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXTTHIS IS SOME TEXT";
System.out.println(dataToEncrypt.length());
byte[] data = dataToEncrypt.getBytes();
String fileName = "blah.txt";
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream pKeyIn = new FileInputStream("/Users/me/blah.pub.key");
encryptFile(out, data, fileName,readPublicKey(pKeyIn), true, false,modDate);
System.out.println(new String(out.toByteArray()));
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
System.out.println(in);
FileInputStream sKeyIn = new FileInputStream("/Users/me/blah.sec.key");
ByteArrayOutputStream decOut = new ByteArrayOutputStream();
decryptFile(in, sKeyIn, "mypass".toCharArray(), "blah.txt", decOut);
System.out.println(decOut.toByteArray().length);
System.out.println(new String(decOut.toByteArray()));
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
完整的工作示例
The full working example