BouncyCastle PGP-Verschlüsselung / Entschlüsselung: Verursacht durch: java.io.EOFException: vorzeitige Ende des Stroms in PartialInputStream
Beim Versuch, verschlüsseln, entschlüsseln Sie eine Datei, die ich mit der folgenden Ausnahme:
com.example.common.crypto.CipherException: org.bouncycastle.openpgp.PGPException: Exception starting decryption
at com.example.common.crypto.PGPFileCipher.decrypt(PGPFileCipher.java:151)
at com.example.common.crypto.PGPFileCipherTest.testEncryptDecryptFile(PGPFileCipherTest.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:43)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)
Caused by: org.bouncycastle.openpgp.PGPException: Exception starting decryption
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at com.example.common.crypto.PGPFileCipher.decrypt(PGPFileCipher.java:128)
... 28 more
Caused by: java.io.EOFException: premature end of stream in PartialInputStream
at org.bouncycastle.bcpg.BCPGInputStream$PartialInputStream.read(Unknown Source)
at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
at java.io.InputStream.read(InputStream.java:82)
at javax.crypto.CipherInputStream.a(DashoA13*..)
at javax.crypto.CipherInputStream.read(DashoA13*..)
at org.bouncycastle.bcpg.BCPGInputStream.read(Unknown Source)
... 31 more
Meine PGPFileCipher Klasse:
package com.example.common.crypto;
public class PGPFileCipher implements FileCipher {
private static final Logger logger = LoggerFactory.getLogger(PGPFileCipher.class);
public File encryptFile(File inputFile, String encryptedFilePath, String publicKeyPath) throws CipherException {
FileInputStream publicKeyStream = null;
FileOutputStream encryptedFileOutputStream = null;
try {
publicKeyStream = new FileInputStream(new File(publicKeyPath));
File encryptedFile = new File(encryptedFilePath);
encryptedFileOutputStream = new FileOutputStream(encryptedFile);
encryptedFileOutputStream.write(encrypt(getBytesFromFile(inputFile), publicKeyStream, ""));
encryptedFileOutputStream.flush();
return encryptedFile;
} catch (Exception e) {
throw new CipherException(e);
} finally {
IOUtils.closeQuietly(encryptedFileOutputStream);
IOUtils.closeQuietly(publicKeyStream);
}
}
private PGPPrivateKey findSecretKey(PGPSecretKeyRingCollection pgpSec, long keyID, char[] pass) throws CipherException {
try {
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null) {
return null;
}
return pgpSecKey.extractPrivateKey(pass, new BouncyCastleProvider());
} catch (Exception e) {
throw new CipherException(e);
}
}
/**
* decrypt the passed in message stream
*
* @param encrypted
* The message to be decrypted.
* @param keyIn
* InputStream of the key
*
* @return Clear text as a byte array. I18N considerations are not handled
* by this routine
* @exception CipherException
*/
public byte[] decrypt(byte[] encrypted, InputStream keyIn, char[] password) throws CipherException {
ByteArrayOutputStream out = null;
InputStream clear = null;
InputStream in = null;
InputStream unc = null;
try {
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.");
}
clear = pbe.getDataStream(sKey, new BouncyCastleProvider());
PGPObjectFactory pgpFact = new PGPObjectFactory(clear);
PGPCompressedData cData = (PGPCompressedData) pgpFact.nextObject();
pgpFact = new PGPObjectFactory(cData.getDataStream());
PGPLiteralData ld = (PGPLiteralData) pgpFact.nextObject();
unc = ld.getInputStream();
out = new ByteArrayOutputStream();
int ch;
while ((ch = unc.read()) >= 0) {
out.write(ch);
}
out.flush();
byte[] returnBytes = out.toByteArray();
return returnBytes;
} catch (Exception e) {
e.printStackTrace();
throw new CipherException(e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(clear);
IOUtils.closeQuietly(unc);
}
}
/**
* Simple PGP encryptor between byte[].
*
* @param clearData
* The test to be encrypted
* @param keyInputStream
* Input stream of the key
* @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.
*
* @return encrypted data.
* @exception CipherException
*/
public byte[] encrypt(byte[] clearData, InputStream keyInputStream, String fileName)
throws CipherException {
OutputStream out = null;
OutputStream cOut = null;
PGPCompressedDataGenerator comData = null;
PGPLiteralDataGenerator lData = null;
ByteArrayOutputStream encOut = null;
ByteArrayOutputStream bOut = null;
OutputStream cos = null;
OutputStream pOut = null;
try {
PGPPublicKey encKey = readPublicKey(keyInputStream);
if (fileName == null || fileName.trim().length() < 1) {
fileName = PGPLiteralData.CONSOLE;
}
encOut = new ByteArrayOutputStream();
out = encOut;
bOut = new ByteArrayOutputStream();
comData = new PGPCompressedDataGenerator(
PGPCompressedDataGenerator.ZIP);
cos = comData.open(bOut); //open it with the final
//destination
lData = new PGPLiteralDataGenerator();
//we want to generate compressed data. This might be a user option
//later,
//in which case we would pass in bOut.
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);
pOut.flush();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(
PGPEncryptedData.CAST5, false, new SecureRandom(),
new BouncyCastleProvider());
cPk.addMethod(encKey);
byte[] bytes = bOut.toByteArray();
cOut = cPk.open(out, bytes.length);
cOut.write(bytes); //obtain the actual bytes from the compressed stream
cOut.flush();
encOut.flush();
return encOut.toByteArray();
} catch (Exception e) {
throw new CipherException(e);
} finally {
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(cOut);
IOUtils.closeQuietly(encOut);
IOUtils.closeQuietly(bOut);
IOUtils.closeQuietly(cos);
IOUtils.closeQuietly(pOut);
try {
if (lData != null) {
lData.close();
}
if (comData != null) {
comData.close();
}
} catch (IOException ignored) {}
}
}
private PGPPublicKey readPublicKey(InputStream in)
throws CipherException {
try {
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.");
} catch (Exception e) {
throw new CipherException(e);
}
}
private byte[] getBytesFromFile(File file) throws CipherException {
InputStream is = null;
try {
is = new FileInputStream(file);
//Get the size of the file
long length = file.length();
if (length > Integer.MAX_VALUE) {
throw new CipherException("File is too large: " + file.getName());
}
return IOUtils.toByteArray(is);
} catch (IOException e) {
throw new CipherException(e);
} finally {
IOUtils.closeQuietly(is);
}
}
}
Und den test-ich bin versucht zu laufen, ist:
package com.example.common.crypto;
public class PGPFileCipherTest {
private static final Logger logger = LoggerFactory.getLogger(PGPFileCipherTest.class);
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void testEncryptDecryptFile() throws IOException, CipherException {
FileOutputStream decryptedFileOutputStream = null;
InputStream privateKeyStream = null;
try {
PGPFileCipher fileCipher = new PGPFileCipher();
Resource inputFile = new ClassPathResource("testInputFile.txt");
Resource publicKey = new ClassPathResource("PUBLIC.asc");
Resource privateKey = new ClassPathResource("PRIVATE.asc");
//Encrypt file
File encryptedFile = fileCipher.encryptFile(inputFile.getFile(), folder.newFile("testInputFile_enc.txt").getPath(), publicKey.getFile().getPath());
//Now decrypt the file
File decryptedFile = folder.newFile("testInputFile_dec.txt");
decryptedFileOutputStream = new FileOutputStream(decryptedFile);
privateKeyStream = new FileInputStream(privateKey.getFile());
decryptedFileOutputStream.write(fileCipher.decrypt(FileUtils.readFileToByteArray(encryptedFile), privateKeyStream, "".toCharArray()));
decryptedFileOutputStream.flush();
} finally {
IOUtils.closeQuietly(decryptedFileOutputStream);
IOUtils.closeQuietly(privateKeyStream);
}
}
}
Leider bin ich nicht allzu vertraut mit der BouncyCastle-und es würde scheinen, als ob ein stream ist nicht richtig geschlossen /geleert, aber ich kann nicht scheinen, um es aufzuspüren. Dies ist eine modifizierte version von einem der BouncyCastle Beispiele FYI. Vielen Dank im Voraus für Eure Hilfe.
Du musst angemeldet sein, um einen Kommentar abzugeben.
überprüfen Sie die jdk-version.. wir waren vor Ausgabe läuft die Verschlüsselung und das sowohl im jdk1.5. aber jdk 1.6 ist es gut zu arbeiten. und ja, der bc-pro-Gläser "bcpg-jdk16" und" bcprov-ext-jdk16" verison sollte 1.46
Vorsichtig sein, wenn mit neuen BouncyCastleProvider() als Ergebnis den Anbieter registriert JceSecurity jeder Zeit, die Sie instanziieren. Dies verursacht ein Speicherleck.
Überlegen, etwas wie das zu tun, anstatt