using System.IO; namespace GostCryptography.Asn1.Ber { public class Asn1CerOutputStream : Asn1BerOutputStream { public Asn1CerOutputStream(Stream outputStream) : base(outputStream) { } public Asn1CerOutputStream(Stream outputStream, int bufSize) : base(outputStream, bufSize) { } public override void Encode(Asn1Type type, bool explicitTagging) { type.Encode(this, explicitTagging); } public override void EncodeBitString(byte[] value, int numbits, bool explicitTagging, Asn1Tag tag) { if ((((numbits + 7) / 8) + 1) <= 0x3e8) { base.EncodeBitString(value, numbits, explicitTagging, tag); } else { if (explicitTagging) { EncodeTagAndIndefLen(Asn1BitString.Tag.Class, 0x20, Asn1BitString.Tag.IdCode); } else { OutputStream.WriteByte(0x80); } var num = (numbits + 7) / 8; var num2 = numbits % 8; if (num2 != 0) { num2 = 8 - num2; value[num - 1] = (byte)(value[num - 1] & ((byte)~((1 << num2) - 1))); } for (var i = 0; i < num; i += 0x3e8) { var len = num - i; if (len > 0x3e8) { len = 0x3e8; EncodeTagAndLength(Asn1BitString.Tag, len); } else { EncodeTagAndLength(Asn1BitString.Tag, len + 1); OutputStream.WriteByte((byte)num2); } if (len > 0) { OutputStream.Write(value, i, len); } } EncodeEoc(); } } public override void EncodeBmpString(string value, bool explicitTagging, Asn1Tag tag) { if ((value == null) || (value.Length <= 500)) { base.EncodeBmpString(value, explicitTagging, tag); } else { if (explicitTagging) { EncodeTagAndIndefLen(Asn1BmpString.Tag.Class, 0x20, Asn1BmpString.Tag.IdCode); } else { OutputStream.WriteByte(0x80); } for (var i = 0; i < value.Length; i += 500) { var num2 = value.Length - i; if (num2 > 500) { num2 = 500; } EncodeTagAndLength(Asn1OctetString.Tag, num2 * 2); for (var j = 0; j < num2; j++) { var num5 = value[j + i]; var num4 = num5 / 0x100; var num3 = num5 % 0x100; OutputStream.WriteByte((byte)num4); OutputStream.WriteByte((byte)num3); } } EncodeEoc(); } } public override void EncodeCharString(string value, bool explicitTagging, Asn1Tag tag) { if ((value == null) || (value.Length <= 0x3e8)) { base.EncodeCharString(value, explicitTagging, tag); } else { var data = Asn1Util.ToByteArray(value); if (explicitTagging) { EncodeTag(tag.Class, 0x20, tag.IdCode); } EncodeOctetString(data, false, tag); } } public override void EncodeOctetString(byte[] value, bool explicitTagging, Asn1Tag tag) { if ((value == null) || (value.Length <= 0x3e8)) { base.EncodeOctetString(value, explicitTagging, tag); } else { if (explicitTagging) { EncodeTagAndIndefLen(Asn1OctetString.Tag.Class, 0x20, Asn1OctetString.Tag.IdCode); } else { OutputStream.WriteByte(0x80); } for (var i = 0; i < value.Length; i += 0x3e8) { var len = value.Length - i; if (len > 0x3e8) { len = 0x3e8; } EncodeTagAndLength(Asn1OctetString.Tag, len); Write(value, i, len); } EncodeEoc(); } } public virtual void EncodeStringTag(int nbytes, Asn1Tag tag) { if (nbytes <= 0x3e8) { EncodeTag(tag); } else { EncodeTag(tag.Class, 0x20, tag.IdCode); } } public virtual void EncodeStringTag(int nbytes, short tagClass, short tagForm, int tagIdCode) { if (nbytes <= 0x3e8) { EncodeTag(new Asn1Tag(tagClass, tagForm, tagIdCode)); } else { EncodeTag(tagClass, 0x20, tagIdCode); } } public override void EncodeUnivString(int[] value, bool explicitTagging, Asn1Tag tag) { if ((value == null) || (value.Length <= 250)) { base.EncodeUnivString(value, explicitTagging, tag); } else { if (explicitTagging) { EncodeTagAndIndefLen(Asn1UniversalString.Tag.Class, 0x20, Asn1UniversalString.Tag.IdCode); } else { OutputStream.WriteByte(0x80); } for (var i = 0; i < value.Length; i += 250) { var num2 = value.Length - i; if (num2 > 250) { num2 = 250; } EncodeTagAndLength(Asn1OctetString.Tag, num2 * 4); for (int j = 0; j < num2; j++) { var number = value[j + 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)); } } EncodeEoc(); } } } }