using System.Collections; using System.IO; using System.Text; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Bcpg; public class ArmoredInputStream : BaseInputStream { private static readonly byte[] decodingTable; private Stream input; private bool start = true; private int[] outBuf = new int[3]; private int bufPtr = 3; private Crc24 crc = new Crc24(); private bool crcFound = false; private bool hasHeaders = true; private string header = null; private bool newLineFound = false; private bool clearText = false; private bool restart = false; private IList headerList = Platform.CreateArrayList(); private int lastC = 0; private bool isEndOfStream; static ArmoredInputStream() { decodingTable = new byte[128]; for (int i = 65; i <= 90; i++) { decodingTable[i] = (byte)(i - 65); } for (int j = 97; j <= 122; j++) { decodingTable[j] = (byte)(j - 97 + 26); } for (int k = 48; k <= 57; k++) { decodingTable[k] = (byte)(k - 48 + 52); } decodingTable[43] = 62; decodingTable[47] = 63; } private int Decode(int in0, int in1, int in2, int in3, int[] result) { if (in3 < 0) { throw new EndOfStreamException("unexpected end of file in armored stream."); } int num; int num2; if (in2 == 61) { num = decodingTable[in0] & 0xFF; num2 = decodingTable[in1] & 0xFF; result[2] = ((num << 2) | (num2 >> 4)) & 0xFF; return 2; } int num3; if (in3 == 61) { num = decodingTable[in0]; num2 = decodingTable[in1]; num3 = decodingTable[in2]; result[1] = ((num << 2) | (num2 >> 4)) & 0xFF; result[2] = ((num2 << 4) | (num3 >> 2)) & 0xFF; return 1; } num = decodingTable[in0]; num2 = decodingTable[in1]; num3 = decodingTable[in2]; int num4 = decodingTable[in3]; result[0] = ((num << 2) | (num2 >> 4)) & 0xFF; result[1] = ((num2 << 4) | (num3 >> 2)) & 0xFF; result[2] = ((num3 << 6) | num4) & 0xFF; return 0; } public ArmoredInputStream(Stream input) : this(input, hasHeaders: true) { } public ArmoredInputStream(Stream input, bool hasHeaders) { this.input = input; this.hasHeaders = hasHeaders; if (hasHeaders) { ParseHeaders(); } start = false; } private bool ParseHeaders() { header = null; int num = 0; bool flag = false; headerList = Platform.CreateArrayList(); if (restart) { flag = true; } else { int num2; while ((num2 = input.ReadByte()) >= 0) { if (num2 == 45 && (num == 0 || num == 10 || num == 13)) { flag = true; break; } num = num2; } } if (flag) { StringBuilder stringBuilder = new StringBuilder("-"); bool flag2 = false; bool flag3 = false; if (restart) { stringBuilder.Append('-'); } int num2; while ((num2 = input.ReadByte()) >= 0) { if (num == 13 && num2 == 10) { flag3 = true; } if ((flag2 && num != 13 && num2 == 10) || (flag2 && num2 == 13)) { break; } if (num2 == 13 || (num != 13 && num2 == 10)) { string text = stringBuilder.ToString(); if (text.Trim().Length < 1) { break; } headerList.Add(text); stringBuilder.Length = 0; } if (num2 != 10 && num2 != 13) { stringBuilder.Append((char)num2); flag2 = false; } else if (num2 == 13 || (num != 13 && num2 == 10)) { flag2 = true; } num = num2; } if (flag3) { input.ReadByte(); } } if (headerList.Count > 0) { header = (string)headerList[0]; } clearText = "-----BEGIN PGP SIGNED MESSAGE-----".Equals(header); newLineFound = true; return flag; } public bool IsClearText() { return clearText; } public bool IsEndOfStream() { return isEndOfStream; } public string GetArmorHeaderLine() { return header; } public string[] GetArmorHeaders() { if (headerList.Count <= 1) { return null; } string[] array = new string[headerList.Count - 1]; for (int i = 0; i != array.Length; i++) { array[i] = (string)headerList[i + 1]; } return array; } private int ReadIgnoreSpace() { int num; do { num = input.ReadByte(); } while (num == 32 || num == 9); return num; } private int ReadIgnoreWhitespace() { int num; do { num = input.ReadByte(); } while (num == 32 || num == 9 || num == 13 || num == 10); return num; } private int ReadByteClearText() { int num = input.ReadByte(); if (num == 13 || (num == 10 && lastC != 13)) { newLineFound = true; } else if (newLineFound && num == 45) { num = input.ReadByte(); if (num == 45) { clearText = false; start = true; restart = true; } else { num = input.ReadByte(); } newLineFound = false; } else if (num != 10 && lastC != 13) { newLineFound = false; } lastC = num; if (num < 0) { isEndOfStream = true; } return num; } private int ReadClearText(byte[] buffer, int offset, int count) { int num = offset; try { int num2 = offset + count; while (num < num2) { int num3 = ReadByteClearText(); if (num3 != -1) { buffer[num++] = (byte)num3; continue; } break; } } catch (IOException ex) { if (num == offset) { throw ex; } } return num - offset; } private int DoReadByte() { if (bufPtr > 2 || crcFound) { int num = ReadIgnoreSpace(); if (num == 10 || num == 13) { num = ReadIgnoreWhitespace(); if (num == 61) { bufPtr = Decode(ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf); if (bufPtr != 0) { throw new IOException("no crc found in armored message."); } crcFound = true; int num2 = ((outBuf[0] & 0xFF) << 16) | ((outBuf[1] & 0xFF) << 8) | (outBuf[2] & 0xFF); if (num2 != crc.Value) { throw new IOException("crc check failed in armored message."); } return ReadByte(); } if (num == 45) { while ((num = input.ReadByte()) >= 0 && num != 10 && num != 13) { } if (!crcFound) { throw new IOException("crc check not found."); } crcFound = false; start = true; bufPtr = 3; if (num < 0) { isEndOfStream = true; } return -1; } } if (num < 0) { isEndOfStream = true; return -1; } bufPtr = Decode(num, ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf); } return outBuf[bufPtr++]; } public override int ReadByte() { if (start) { if (hasHeaders) { ParseHeaders(); } crc.Reset(); start = false; } if (clearText) { return ReadByteClearText(); } int num = DoReadByte(); crc.Update(num); return num; } public override int Read(byte[] buffer, int offset, int count) { if (start && count > 0) { if (hasHeaders) { ParseHeaders(); } start = false; } if (clearText) { return ReadClearText(buffer, offset, count); } int num = offset; try { int num2 = offset + count; while (num < num2) { int num3 = DoReadByte(); crc.Update(num3); if (num3 != -1) { buffer[num++] = (byte)num3; continue; } break; } } catch (IOException ex) { if (num == offset) { throw ex; } } return num - offset; } public override void Close() { Platform.Dispose(input); base.Close(); } }