0
當我調用它時,它成功地加密了我的字符串,但解密文本的輸出爲空。我沒有得到任何錯誤,輸出字符串的byteArray是正確的長度(102),但它只有102個零。這是根據KeyBasedFileProcessor示例進行調整的,但是嘗試基於流/字符串而不是基於文件。Bouncycastle pgp解密正確大小但全爲空
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()));
}
}