Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pg/src/main/j2me/org/spongycastle/openpgp/PGPPBEEncryptedData.java')
-rw-r--r--pg/src/main/j2me/org/spongycastle/openpgp/PGPPBEEncryptedData.java141
1 files changed, 141 insertions, 0 deletions
diff --git a/pg/src/main/j2me/org/spongycastle/openpgp/PGPPBEEncryptedData.java b/pg/src/main/j2me/org/spongycastle/openpgp/PGPPBEEncryptedData.java
new file mode 100644
index 00000000..d13edf6a
--- /dev/null
+++ b/pg/src/main/j2me/org/spongycastle/openpgp/PGPPBEEncryptedData.java
@@ -0,0 +1,141 @@
+package org.spongycastle.openpgp;
+
+import java.io.EOFException;
+import java.io.InputStream;
+
+import org.spongycastle.bcpg.BCPGInputStream;
+import org.spongycastle.bcpg.InputStreamPacket;
+import org.spongycastle.bcpg.SymmetricEncIntegrityPacket;
+import org.spongycastle.bcpg.SymmetricKeyEncSessionPacket;
+import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
+import org.spongycastle.openpgp.operator.PGPDataDecryptor;
+import org.spongycastle.util.io.TeeInputStream;
+
+/**
+ * A password based encryption object.
+ */
+public class PGPPBEEncryptedData
+ extends PGPEncryptedData
+{
+ SymmetricKeyEncSessionPacket keyData;
+
+ PGPPBEEncryptedData(
+ SymmetricKeyEncSessionPacket keyData,
+ InputStreamPacket encData)
+ {
+ super(encData);
+
+ this.keyData = keyData;
+ }
+
+ /**
+ * Return the raw input stream for the data stream.
+ *
+ * @return InputStream
+ */
+ public InputStream getInputStream()
+ {
+ return encData.getInputStream();
+ }
+
+ /**
+ * Return the symmetric key algorithm required to decrypt the data protected by this object.
+ *
+ * @param dataDecryptorFactory decryptor factory to use to recover the session data.
+ * @return the integer encryption algorithm code.
+ * @throws PGPException if the session data cannot be recovered.
+ */
+ public int getSymmetricAlgorithm(
+ PBEDataDecryptorFactory dataDecryptorFactory)
+ throws PGPException
+ {
+ byte[] key = dataDecryptorFactory.makeKeyFromPassPhrase(keyData.getEncAlgorithm(), keyData.getS2K());
+ byte[] sessionData = dataDecryptorFactory.recoverSessionData(keyData.getEncAlgorithm(), key, keyData.getSecKeyData());
+
+ return sessionData[0];
+ }
+
+ /**
+ * Open an input stream which will provide the decrypted data protected by this object.
+ *
+ * @param dataDecryptorFactory decryptor factory to use to recover the session data and provide the stream.
+ * @return the resulting input stream
+ * @throws PGPException if the session data cannot be recovered or the stream cannot be created.
+ */
+ public InputStream getDataStream(
+ PBEDataDecryptorFactory dataDecryptorFactory)
+ throws PGPException
+ {
+ try
+ {
+ int keyAlgorithm = keyData.getEncAlgorithm();
+ byte[] key = dataDecryptorFactory.makeKeyFromPassPhrase(keyAlgorithm, keyData.getS2K());
+ boolean withIntegrityPacket = encData instanceof SymmetricEncIntegrityPacket;
+
+ byte[] sessionData = dataDecryptorFactory.recoverSessionData(keyData.getEncAlgorithm(), key, keyData.getSecKeyData());
+ byte[] sessionKey = new byte[sessionData.length - 1];
+
+ System.arraycopy(sessionData, 1, sessionKey, 0, sessionKey.length);
+
+ PGPDataDecryptor dataDecryptor = dataDecryptorFactory.createDataDecryptor(withIntegrityPacket, sessionData[0] & 0xff, sessionKey);
+
+ encStream = new BCPGInputStream(dataDecryptor.getInputStream(encData.getInputStream()));
+
+ if (withIntegrityPacket)
+ {
+ truncStream = new TruncatedStream(encStream);
+
+ integrityCalculator = dataDecryptor.getIntegrityCalculator();
+
+ encStream = new TeeInputStream(truncStream, integrityCalculator.getOutputStream());
+ }
+
+ byte[] iv = new byte[dataDecryptor.getBlockSize()];
+ for (int i = 0; i != iv.length; i++)
+ {
+ int ch = encStream.read();
+
+ if (ch < 0)
+ {
+ throw new EOFException("unexpected end of stream.");
+ }
+
+ iv[i] = (byte)ch;
+ }
+
+ int v1 = encStream.read();
+ int v2 = encStream.read();
+
+ if (v1 < 0 || v2 < 0)
+ {
+ throw new EOFException("unexpected end of stream.");
+ }
+
+
+ // Note: the oracle attack on "quick check" bytes is not deemed
+ // a security risk for PBE (see PGPPublicKeyEncryptedData)
+
+ boolean repeatCheckPassed = iv[iv.length - 2] == (byte) v1
+ && iv[iv.length - 1] == (byte) v2;
+
+ // Note: some versions of PGP appear to produce 0 for the extra
+ // bytes rather than repeating the two previous bytes
+ boolean zeroesCheckPassed = v1 == 0 && v2 == 0;
+
+ if (!repeatCheckPassed && !zeroesCheckPassed)
+ {
+ throw new PGPDataValidationException("data check failed.");
+ }
+
+ return encStream;
+ }
+ catch (PGPException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new PGPException("Exception creating cipher", e);
+ }
+ }
+}