<PackageReference Include="BouncyCastle.Cryptography" Version="2.7.0-beta.98" />

PgpEncryptedData

public abstract class 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); return Read(buffer.AsSpan(offset, count)); } public override int Read(Span<byte> buffer) { int num = m_bufEnd - m_bufStart; int num2 = 0; int num3 = buffer.Length; Span<byte> span; int num4; while (num3 > num) { span = m_lookAhead.AsSpan(m_bufStart, num); num4 = num2; span.CopyTo(buffer.Slice(num4, buffer.Length - num4)); m_bufStart += num; num2 += num; num3 -= num; if ((num = FillBuffer()) < 1) return num2; } span = m_lookAhead.AsSpan(m_bufStart, num3); num4 = num2; span.CopyTo(buffer.Slice(num4, buffer.Length - num4)); m_bufStart += num3; return num2 + num3; } 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."); } } }