using System.IO; namespace GostCryptography.Asn1.Ber { public class Asn1BerOutputStream : Asn1OutputStream { private static readonly byte[] Eoc = new byte[2]; public Asn1BerOutputStream(Stream outputStream) : base(new BufferedStream(outputStream)) { } public Asn1BerOutputStream(Stream outputStream, int bufSize) : base((bufSize == 0) ? outputStream : new BufferedStream(outputStream, bufSize)) { } public virtual void Encode(Asn1Type type, bool explicitTagging) { type.Encode(this, explicitTagging); } public virtual void EncodeBitString(byte[] data, int numbits, bool explicitTagging, Asn1Tag tag) { if (explicitTagging) { EncodeTag(tag); } var count = (numbits + 7) / 8; EncodeLength(count + 1); var num2 = numbits % 8; if (num2 != 0) { num2 = 8 - num2; data[count - 1] = (byte)(data[count - 1] & ((byte)~((1 << num2) - 1))); } OutputStream.WriteByte((byte)num2); if (count > 0) { OutputStream.Write(data, 0, count); } } public virtual void EncodeBmpString(string data, bool explicitTagging, Asn1Tag tag) { if (explicitTagging) { EncodeTag(tag); } if (data == null) { EncodeLength(0); } else { EncodeLength(data.Length * 2); var length = data.Length; for (var i = 0; i < length; i++) { var num3 = data[i]; var num2 = num3 / 0x100; var num = num3 % 0x100; OutputStream.WriteByte((byte)num2); OutputStream.WriteByte((byte)num); } } } public virtual void EncodeCharString(string data, bool explicitTagging, Asn1Tag tag) { if (explicitTagging) { EncodeTag(tag); } if (data == null) { EncodeLength(0); } else { EncodeLength(data.Length); var buffer = Asn1Util.ToByteArray(data); OutputStream.Write(buffer, 0, buffer.Length); } } public virtual void EncodeEoc() { OutputStream.Write(Eoc, 0, Eoc.Length); } public virtual void EncodeIdentifier(long ident) { var number = 0x7fL; var identBytesCount = Asn1RunTime.GetIdentBytesCount(ident); number = number << (7 * identBytesCount); if (identBytesCount > 0) { while (identBytesCount > 0) { number = Asn1Util.UrShift(number, 7); identBytesCount--; var num3 = Asn1Util.UrShift(ident & number, identBytesCount * 7); if (identBytesCount != 0) { num3 |= 0x80L; } OutputStream.WriteByte((byte)num3); } } else { OutputStream.WriteByte(0); } } public virtual void EncodeIntValue(long data, bool encodeLen) { long num2; var num = data; var buffer = new byte[9]; var len = 0; var length = buffer.Length; do { num2 = num % 0x100L; num /= 0x100L; if ((num < 0L) && (num2 != 0L)) { num -= 1L; } buffer[--length] = (byte)num2; len++; } while ((num != 0L) && (num != -1L)); if ((data > 0L) && ((num2 & 0x80L) == 0x80L)) { buffer[--length] = 0; len++; } else if ((data < 0L) && ((num2 & 0x80L) == 0L)) { buffer[--length] = 0xff; len++; } if (encodeLen) { EncodeLength(len); } OutputStream.Write(buffer, length, len); } public virtual void EncodeLength(int len) { if (len >= 0) { var bytesCount = Asn1Util.GetBytesCount(len); if (len > 0x7f) { OutputStream.WriteByte((byte)(bytesCount | 0x80)); } for (var i = (8 * bytesCount) - 8; i >= 0; i -= 8) { var num3 = (byte)((len >> i) & 0xff); OutputStream.WriteByte(num3); } } else if (len == Asn1Status.IndefiniteLength) { OutputStream.WriteByte(0x80); } } public virtual void EncodeOctetString(byte[] data, bool explicitTagging, Asn1Tag tag) { if (explicitTagging) { EncodeTag(tag); } if (data == null) { EncodeLength(0); } else { EncodeLength(data.Length); OutputStream.Write(data, 0, data.Length); } } public virtual void EncodeTag(Asn1Tag tag) { var num = (byte)(((byte)tag.Class) | ((byte)tag.Form)); if (tag.IdCode < 0x1f) { OutputStream.WriteByte((byte)(num | tag.IdCode)); } else { OutputStream.WriteByte((byte)(num | 0x1f)); EncodeIdentifier(tag.IdCode); } } public virtual void EncodeTag(short tagClass, short tagForm, int tagIdCode) { EncodeTag(new Asn1Tag(tagClass, tagForm, tagIdCode)); } public virtual void EncodeTagAndIndefLen(Asn1Tag tag) { EncodeTag(tag); OutputStream.WriteByte(0x80); } public virtual void EncodeTagAndIndefLen(short tagClass, short tagForm, int tagIdCode) { EncodeTag(new Asn1Tag(tagClass, tagForm, tagIdCode)); OutputStream.WriteByte(0x80); } public virtual void EncodeTagAndLength(Asn1Tag tag, int len) { EncodeTag(tag); EncodeLength(len); } public virtual void EncodeUnivString(int[] data, bool explicitTagging, Asn1Tag tag) { if (explicitTagging) { EncodeTag(tag); } if (data == null) { EncodeLength(0); } else { EncodeLength(data.Length * 4); var length = data.Length; for (var i = 0; i < length; ++i) { var number = data[i]; OutputStream.WriteByte((byte)(Asn1Util.UrShift(number, 0x18) & 0xff)); OutputStream.WriteByte((byte)(Asn1Util.UrShift(number, 0x10) & 0xff)); OutputStream.WriteByte((byte)(Asn1Util.UrShift(number, 8) & 0xff)); OutputStream.WriteByte((byte)(number & 0xff)); } } } } }