using GostCryptography.Properties; using System; using System.Text; namespace GostCryptography.Asn1.Ber { [Serializable] public class Asn1UniversalString : Asn1Type { public const int BitsPerChar = 0x20; public static readonly Asn1Tag Tag = new Asn1Tag(0, 0, UniversalStringTypeCode); [NonSerialized] private StringBuilder _stringBuffer; [NonSerialized] private int[] _value; public Asn1UniversalString() { _value = new int[0]; } public Asn1UniversalString(int[] value) { _value = value; } public Asn1UniversalString(string value) { _value = new int[value.Length]; for (var i = 0; i < value.Length; i++) { _value[i] = value[i]; } } public override int Length { get { return _value.Length; } } public override void Decode(Asn1BerDecodeBuffer buffer, bool explicitTagging, int implicitLength) { var llen = explicitTagging ? MatchTag(buffer, Tag) : implicitLength; var idx = new IntHolder(0); var lastTag = buffer.LastTag; if ((lastTag == null) || !lastTag.Constructed) { ReadSegment(buffer, llen, idx); } else { var context = new Asn1BerDecodeContext(buffer, llen); while (!context.Expired()) { var num2 = MatchTag(buffer, Asn1OctetString.Tag); if (num2 <= 0) { throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidFormatOfConstructedValue, buffer.ByteCount); } ReadSegment(buffer, num2, idx); } if (llen == Asn1Status.IndefiniteLength) { MatchTag(buffer, Asn1Tag.Eoc); } } buffer.TypeCode = UniversalStringTypeCode; } public override int Encode(Asn1BerEncodeBuffer buffer, bool explicitTagging) { var length = _value.Length; for (var i = length - 1; i >= 0; i--) { var num3 = _value[i]; for (var j = 0; j < 4; j++) { var num = num3 % 0x100; num3 /= 0x100; buffer.Copy((byte)num); } } length *= 4; if (explicitTagging) { length += buffer.EncodeTagAndLength(Tag, length); } return length; } public override void Encode(Asn1BerOutputStream outs, bool explicitTagging) { outs.EncodeUnivString(_value, explicitTagging, Tag); } public override bool Equals(object value) { var str = value as Asn1UniversalString; if (str == null) { return false; } if (_value.Length != str._value.Length) { return false; } for (var i = 0; i < _value.Length; i++) { if (_value[i] != str._value[i]) { return false; } } return true; } public override int GetHashCode() { if (_value.Length == 0) { return base.GetHashCode(); } var num = 0; var num2 = (_value.Length > 20) ? 20 : _value.Length; for (var i = 0; i < num2; i++) { num ^= _value[i]; } return num; } private void ReadSegment(Asn1BerDecodeBuffer buffer, int llen, IntHolder idx) { if ((llen < 0) || ((llen % 4) != 0)) { throw ExceptionUtility.CryptographicException(Resources.Asn1InvalidLengthException); } var num4 = llen / 4; if (_value.Length == 0) { _value = new int[num4]; } else if ((idx.Value + num4) >= _value.Length) { ReallocIntArray(idx.Value + num4); } var value = idx.Value; while (value < (idx.Value + num4)) { _value[value] = 0; for (var i = 0; i < 4; i++) { var num = buffer.Read(); if (num == -1) { throw ExceptionUtility.CryptographicException(Resources.Asn1EndOfBufferException, buffer.ByteCount); } _value[value] = (_value[value] * 0x100) + num; } value++; } idx.Value = value; } private void ReallocIntArray(int nint) { var value = _value; _value = new int[nint]; if (value != null) { Array.Copy(value, 0, _value, 0, value.Length); } } public override string ToString() { if (_stringBuffer == null) { _stringBuffer = new StringBuilder(); } _stringBuffer.Length = _value.Length; for (var i = 0; i < _value.Length; i++) { _stringBuffer[i] = (char)_value[i]; } return _stringBuffer.ToString(); } } }