gpt4 book ai didi

java - BouncycaSTLe pgp 解密大小正确但全部空白

转载 作者:行者123 更新时间:2023-12-01 16:00:53 26 4
gpt4 key购买 nike

当我调用它时,它成功加密了我的字符串,但解密文本的输出为空。我没有收到任何错误,并且输出字符串的 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()));

}
}

最佳答案

完整的工作示例

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.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.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;

/**
* Simple routine to encrypt and decrypt using a Public and Private key with passphrase. This service
* routine provides the basic PGP services between byte arrays.
*
*/
public class PgpEncryption {


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
*
* @param encrypted
* The message to be decrypted.
* @param passPhrase
* Pass phrase (key)
*
* @return Clear text as a byte array. I18N considerations are not handled
* by this routine
* @exception IOException
* @exception PGPException
* @exception NoSuchProviderException
*/
public static byte[] decrypt(byte[] encrypted, InputStream keyIn, char[] password)
throws IOException, PGPException, NoSuchProviderException {
InputStream in = new ByteArrayInputStream(encrypted);

in = PGPUtil.getDecoderStream(in);

PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc = null;
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(), password);
}

if (sKey == null) {
throw new IllegalArgumentException(
"secret key for message not found.");
}

InputStream clear = pbe.getDataStream(sKey, "BC");



PGPObjectFactory pgpFact = new PGPObjectFactory(clear);

PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject();

pgpFact = new PGPObjectFactory(cData.getDataStream());

PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();

InputStream unc = ld.getInputStream();

ByteArrayOutputStream out = new ByteArrayOutputStream();
int ch;

while ((ch = unc.read()) >= 0) {
out.write(ch);

}

byte[] returnBytes = out.toByteArray();
out.close();
return returnBytes;
}

/**
* Simple PGP encryptor between byte[].
*
* @param clearData
* The test to be encrypted
* @param passPhrase
* The pass phrase (key). This method assumes that the key is a
* simple pass phrase, and does not yet support RSA or more
* sophisiticated keying.
* @param fileName
* File name. This is used in the Literal Data Packet (tag 11)
* which is really inly important if the data is to be related to
* a file to be recovered later. Because this routine does not
* know the source of the information, the caller can set
* something here for file name use that will be carried. If this
* routine is being used to encrypt SOAP MIME bodies, for
* example, use the file name from the MIME type, if applicable.
* Or anything else appropriate.
*
* @param armor
*
* @return encrypted data.
* @exception IOException
* @exception PGPException
* @exception NoSuchProviderException
*/
public static byte[] encrypt(byte[] clearData, PGPPublicKey encKey,
String fileName,boolean withIntegrityCheck, boolean armor)
throws IOException, PGPException, NoSuchProviderException {
if (fileName == null) {
fileName = PGPLiteralData.CONSOLE;
}

ByteArrayOutputStream encOut = new ByteArrayOutputStream();

OutputStream out = encOut;
if (armor) {
out = new ArmoredOutputStream(out);
}

ByteArrayOutputStream bOut = new ByteArrayOutputStream();

PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
PGPCompressedDataGenerator.ZIP);
OutputStream cos = comData.open(bOut); // open it with the final
// destination
PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();

// we want to generate compressed data. This might be a user option
// later,
// in which case we would pass in bOut.
OutputStream pOut = lData.open(cos, // the compressed output stream
PGPLiteralData.BINARY, fileName, // "filename" to store
clearData.length, // length of clear data
new Date() // current time
);
pOut.write(clearData);

lData.close();
comData.close();

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); // obtain the actual bytes from the compressed stream

cOut.close();

out.close();

return encOut.toByteArray();
}

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.");
}

public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);

// Get the size of the file
long length = file.length();

if (length > Integer.MAX_VALUE) {
// File is too large
}

// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];

// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}

// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}

// Close the input stream and return bytes
is.close();
return bytes;
}

public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());


byte[] original = "Hello world".getBytes();
System.out.println("Starting PGP test");

FileInputStream pubKey = new FileInputStream("/Users/me/pub.key");
byte[] encrypted = encrypt(original, readPublicKey(pubKey), null,
true, true);

FileOutputStream dfis = new FileOutputStream("/Users/me/enc.asc");
dfis.write(encrypted);
dfis.close();

byte[] encFromFile = getBytesFromFile(new File("/Users/me/enc.asc"));
FileInputStream secKey = new FileInputStream("/Users/me/sec.key");

System.out.println("\nencrypted data = '" + new String(encrypted) + "'");

byte[] decrypted = decrypt(encFromFile, secKey, "passphrase".toCharArray());

System.out.println("\ndecrypted data = '" + new String(decrypted) + "'");


}
}

关于java - BouncycaSTLe pgp 解密大小正确但全部空白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3962911/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com