summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpEncryptedData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/openpgp/PgpEncryptedData.cs')
-rw-r--r--crypto/src/openpgp/PgpEncryptedData.cs151
1 files changed, 151 insertions, 0 deletions
diff --git a/crypto/src/openpgp/PgpEncryptedData.cs b/crypto/src/openpgp/PgpEncryptedData.cs
new file mode 100644
index 000000000..0d237b56c
--- /dev/null
+++ b/crypto/src/openpgp/PgpEncryptedData.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+    public abstract class PgpEncryptedData
+    {
+		internal class TruncatedStream
+			: BaseInputStream
+		{
+			private const int LookAheadSize = 22;
+			private const int LookAheadBufSize = 512;
+			private const int LookAheadBufLimit = LookAheadBufSize - LookAheadSize;
+
+			private readonly Stream inStr;
+			private readonly byte[] lookAhead = new byte[LookAheadBufSize];
+			private int bufStart, bufEnd;
+
+			internal TruncatedStream(
+				Stream inStr)
+			{
+				int numRead = Streams.ReadFully(inStr, lookAhead, 0, lookAhead.Length);
+
+				if (numRead < LookAheadSize)
+					throw new EndOfStreamException();
+
+				this.inStr = inStr;
+				this.bufStart = 0;
+				this.bufEnd = numRead - LookAheadSize;
+			}
+
+			private int FillBuffer()
+			{
+				if (bufEnd < LookAheadBufLimit)
+					return 0;
+
+				Debug.Assert(bufStart == LookAheadBufLimit);
+				Debug.Assert(bufEnd == LookAheadBufLimit);
+
+				Array.Copy(lookAhead, LookAheadBufLimit, lookAhead, 0, LookAheadSize);
+				bufEnd = Streams.ReadFully(inStr, lookAhead, LookAheadSize, LookAheadBufLimit);
+				bufStart = 0;
+				return bufEnd;
+			}
+
+			public override int ReadByte()
+			{
+				if (bufStart < bufEnd)
+					return lookAhead[bufStart++];
+
+				if (FillBuffer() < 1)
+					return -1;
+
+				return lookAhead[bufStart++];
+			}
+
+			public override int Read(byte[] buf, int off, int len)
+			{
+				int avail = bufEnd - bufStart;
+
+				int pos = off;
+				while (len > avail)
+				{
+					Array.Copy(lookAhead, bufStart, buf, pos, avail);
+
+					bufStart += avail;
+					pos += avail;
+					len -= avail;
+
+					if ((avail = FillBuffer()) < 1)
+						return pos - off;
+				}
+
+				Array.Copy(lookAhead, bufStart, buf, pos, len);
+				bufStart += len;
+
+				return pos + len - off;;
+			}
+
+			internal byte[] GetLookAhead()
+			{
+				byte[] temp = new byte[LookAheadSize];
+				Array.Copy(lookAhead, bufStart, temp, 0, LookAheadSize);
+				return temp;
+			}
+		}
+
+		internal InputStreamPacket	encData;
+        internal Stream				encStream;
+        internal TruncatedStream	truncStream;
+
+		internal PgpEncryptedData(
+            InputStreamPacket encData)
+        {
+            this.encData = encData;
+        }
+
+		/// <summary>Return the raw input stream for the data stream.</summary>
+        public virtual Stream GetInputStream()
+        {
+            return encData.GetInputStream();
+        }
+
+		/// <summary>Return true if the message is integrity protected.</summary>
+		/// <returns>True, if there is a modification detection code namespace associated
+		/// with this stream.</returns>
+        public bool IsIntegrityProtected()
+        {
+			return encData is SymmetricEncIntegrityPacket;
+        }
+
+		/// <summary>Note: This can only be called after the message has been read.</summary>
+		/// <returns>True, if the message verifies, false otherwise</returns>
+        public bool Verify()
+        {
+            if (!IsIntegrityProtected())
+                throw new PgpException("data not integrity protected.");
+
+			DigestStream dIn = (DigestStream) encStream;
+
+			//
+            // make sure we are at the end.
+            //
+            while (encStream.ReadByte() >= 0)
+            {
+				// do nothing
+            }
+
+			//
+            // process the MDC packet
+            //
+			byte[] lookAhead = truncStream.GetLookAhead();
+
+			IDigest hash = dIn.ReadDigest();
+			hash.BlockUpdate(lookAhead, 0, 2);
+			byte[] digest = DigestUtilities.DoFinal(hash);
+
+			byte[] streamDigest = new byte[digest.Length];
+			Array.Copy(lookAhead, 2, streamDigest, 0, streamDigest.Length);
+
+			return Arrays.ConstantTimeAreEqual(digest, streamDigest);
+        }
+    }
+}