PgpEncryptedData
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
using System;
using System.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 = 490;
private readonly byte[] m_lookAhead = new byte[512];
private readonly Stream m_inStr;
private int m_bufStart;
private int m_bufEnd;
internal TruncatedStream(Stream inStr)
{
int num = Streams.ReadFully(inStr, m_lookAhead);
if (num < 22)
throw new EndOfStreamException();
m_inStr = inStr;
m_bufStart = 0;
m_bufEnd = num - 22;
}
private int FillBuffer()
{
if (m_bufEnd < 490)
return 0;
Array.Copy(m_lookAhead, 490, m_lookAhead, 0, 22);
m_bufEnd = Streams.ReadFully(m_inStr, m_lookAhead, 22, 490);
m_bufStart = 0;
return m_bufEnd;
}
public override int Read(byte[] buffer, int offset, int count)
{
Streams.ValidateBufferArguments(buffer, offset, count);
int num = m_bufEnd - m_bufStart;
int num2 = offset;
while (count > num) {
Array.Copy(m_lookAhead, m_bufStart, buffer, num2, num);
m_bufStart += num;
num2 += num;
count -= num;
if ((num = FillBuffer()) < 1)
return num2 - offset;
}
Array.Copy(m_lookAhead, m_bufStart, buffer, num2, count);
m_bufStart += count;
return num2 + count - offset;
}
public override int ReadByte()
{
if (m_bufStart >= m_bufEnd && FillBuffer() < 1)
return -1;
return m_lookAhead[m_bufStart++];
}
internal bool CheckMdc(IDigest digest)
{
byte[] array = DigestUtilities.DoFinal(digest, m_lookAhead, m_bufStart, 2);
return Arrays.FixedTimeEquals(array.Length, array, 0, m_lookAhead, m_bufStart + 2);
}
}
private readonly InputStreamPacket m_encData;
private Stream m_decStream;
internal PgpEncryptedData(InputStreamPacket encData)
{
m_encData = encData;
}
public virtual Stream GetInputStream()
{
return m_encData.GetInputStream();
}
public bool IsIntegrityProtected()
{
return m_encData is SymmetricEncIntegrityPacket;
}
public bool Verify()
{
if (!IsIntegrityProtected())
throw new PgpException("data not integrity protected.");
DigestStream digestStream = (DigestStream)m_decStream;
if (digestStream.ReadByte() >= 0)
Streams.Drain(digestStream);
return ((TruncatedStream)digestStream.Stream).CheckMdc(digestStream.ReadDigest);
}
internal IBufferedCipher CreateBufferedCipher(string cipherName)
{
string str = IsIntegrityProtected() ? "CFB" : "OpenPGPCFB";
return CipherUtilities.GetCipher(cipherName + "/" + str + "/NoPadding");
}
internal Stream InitDecStream(Stream decStream)
{
if (IsIntegrityProtected()) {
TruncatedStream stream = new TruncatedStream(decStream);
IDigest readDigest = PgpUtilities.CreateDigest(HashAlgorithmTag.Sha1);
decStream = new DigestStream(stream, readDigest, null);
}
m_decStream = decStream;
return decStream;
}
internal static void QuickCheck(byte[] prefix)
{
int num = prefix.Length;
byte b = prefix[num - 4];
byte b2 = prefix[num - 3];
byte num2 = prefix[num - 2];
byte b3 = prefix[num - 1];
bool flag = num2 == b && b3 == b2;
bool flag2 = num2 == 0 && b3 == 0;
if (!flag && !flag2)
throw new PgpDataValidationException("quick check failed.");
}
}
}