Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
AsnWriter.cs
Go to the documentation of this file.
8using System.Text;
9
10namespace System.Formats.Asn1;
11
12public sealed class AsnWriter
13{
14 private sealed class ArrayIndexSetOfValueComparer : IComparer<(int, int)>
15 {
16 private readonly byte[] _data;
17
18 public ArrayIndexSetOfValueComparer(byte[] data)
19 {
20 _data = data;
21 }
22
23 public int Compare((int, int) x, (int, int) y)
24 {
25 (int, int) tuple = x;
26 int item = tuple.Item1;
27 int item2 = tuple.Item2;
28 (int, int) tuple2 = y;
29 int item3 = tuple2.Item1;
30 int item4 = tuple2.Item2;
32 if (num == 0)
33 {
34 return item - item3;
35 }
36 return num;
37 }
38 }
39
40 private readonly struct StackFrame : IEquatable<StackFrame>
41 {
42 public Asn1Tag Tag { get; }
43
44 public int Offset { get; }
45
46 public UniversalTagNumber ItemType { get; }
47
49 {
50 Tag = tag;
51 Offset = offset;
52 ItemType = itemType;
53 }
54
56 {
57 tag = Tag;
58 offset = Offset;
60 }
61
62 public bool Equals(StackFrame other)
63 {
64 if (Tag.Equals(other.Tag) && Offset == other.Offset)
65 {
66 return ItemType == other.ItemType;
67 }
68 return false;
69 }
70
71 public override bool Equals([NotNullWhen(true)] object obj)
72 {
74 {
75 return Equals(other);
76 }
77 return false;
78 }
79
80 public override int GetHashCode()
81 {
82 return (Tag, Offset, ItemType).GetHashCode();
83 }
84
85 public static bool operator ==(StackFrame left, StackFrame right)
86 {
87 return left.Equals(right);
88 }
89 }
90
91 public readonly struct Scope : IDisposable
92 {
93 private readonly AsnWriter _writer;
94
95 private readonly StackFrame _frame;
96
97 private readonly int _depth;
98
100 {
101 _writer = writer;
104 }
105
106 public void Dispose()
107 {
108 if (_writer == null || _writer._nestingStack.Count == 0)
109 {
110 return;
111 }
112 if (_writer._nestingStack.Peek() == _frame)
113 {
114 switch (_frame.ItemType)
115 {
116 case UniversalTagNumber.Set:
118 break;
119 case UniversalTagNumber.Sequence:
121 break;
122 case UniversalTagNumber.OctetString:
124 break;
125 default:
126 throw new InvalidOperationException();
127 }
128 }
130 {
132 }
133 }
134 }
135
136 private byte[] _buffer;
137
138 private int _offset;
139
141
142 public AsnEncodingRules RuleSet { get; }
143
145 {
146 if (ruleSet != 0 && ruleSet != AsnEncodingRules.CER && ruleSet != AsnEncodingRules.DER)
147 {
148 throw new ArgumentOutOfRangeException("ruleSet");
149 }
151 }
152
153 public void Reset()
154 {
155 if (_offset > 0)
156 {
158 _offset = 0;
160 }
161 }
162
163 public int GetEncodedLength()
164 {
166 if (nestingStack != null && nestingStack.Count != 0)
167 {
169 }
170 return _offset;
171 }
172
174 {
176 if (nestingStack != null && nestingStack.Count != 0)
177 {
179 }
180 if (destination.Length < _offset)
181 {
182 bytesWritten = 0;
183 return false;
184 }
185 if (_offset == 0)
186 {
187 bytesWritten = 0;
188 return true;
189 }
191 _buffer.AsSpan(0, _offset).CopyTo(destination);
192 return true;
193 }
194
196 {
198 {
200 }
201 return bytesWritten;
202 }
203
204 public byte[] Encode()
205 {
207 if (nestingStack != null && nestingStack.Count != 0)
208 {
210 }
211 if (_offset == 0)
212 {
213 return Array.Empty<byte>();
214 }
215 return _buffer.AsSpan(0, _offset).ToArray();
216 }
217
219 {
221 if (nestingStack != null && nestingStack.Count != 0)
222 {
224 }
225 if (_offset == 0)
226 {
227 return ReadOnlySpan<byte>.Empty;
228 }
229 return new ReadOnlySpan<byte>(_buffer, 0, _offset);
230 }
231
233 {
234 return EncodeAsSpan().SequenceEqual(other);
235 }
236
238 {
239 if (other == null)
240 {
241 throw new ArgumentNullException("other");
242 }
243 return EncodeAsSpan().SequenceEqual(other.EncodeAsSpan());
244 }
245
247 {
248 if (pendingCount < 0)
249 {
250 throw new OverflowException();
251 }
252 if (_buffer == null || _buffer.Length - _offset < pendingCount)
253 {
254 int num = checked(_offset + pendingCount + 1023) / 1024;
255 byte[] buffer = _buffer;
256 Array.Resize(ref _buffer, 1024 * num);
257 buffer?.AsSpan(0, _offset).Clear();
258 }
259 }
260
261 private void WriteTag(Asn1Tag tag)
262 {
263 int num = tag.CalculateEncodedSize();
265 if (!tag.TryEncode(_buffer.AsSpan(_offset, num), out var bytesWritten) || bytesWritten != num)
266 {
267 throw new InvalidOperationException();
268 }
269 _offset += num;
270 }
271
272 private void WriteLength(int length)
273 {
274 if (length == -1)
275 {
277 _buffer[_offset] = 128;
278 _offset++;
279 return;
280 }
281 if (length < 128)
282 {
284 _buffer[_offset] = (byte)length;
285 _offset++;
286 return;
287 }
292 int num2 = length;
293 do
294 {
295 _buffer[num] = (byte)num2;
296 num2 >>= 8;
297 num--;
298 }
299 while (num2 > 0);
301 }
302
304 {
305 if (length < 0)
306 {
307 throw new OverflowException();
308 }
309 if (length <= 127)
310 {
311 return 0;
312 }
313 if (length <= 255)
314 {
315 return 1;
316 }
317 if (length <= 65535)
318 {
319 return 2;
320 }
321 if (length <= 16777215)
322 {
323 return 3;
324 }
325 return 4;
326 }
327
329 {
330 if (destination == null)
331 {
332 throw new ArgumentNullException("destination");
333 }
334 try
335 {
336 destination.WriteEncodedValue(EncodeAsSpan());
337 }
339 {
341 }
342 }
343
354
355 private void WriteEndOfContents()
356 {
358 _buffer[_offset++] = 0;
359 _buffer[_offset++] = 0;
360 }
361
363 {
364 if (_nestingStack == null)
365 {
367 }
368 WriteTag(tag);
369 _nestingStack.Push(new StackFrame(tag, _offset, tagType));
370 WriteLength(-1);
371 return new Scope(this);
372 }
373
374 private void PopTag(Asn1Tag tag, UniversalTagNumber tagType, bool sortContents = false)
375 {
376 if (_nestingStack == null || _nestingStack.Count == 0)
377 {
379 }
381 if (asn1Tag2 != tag || universalTagNumber2 != tagType)
382 {
384 }
385 _nestingStack.Pop();
386 if (sortContents)
387 {
389 }
390 if (RuleSet == AsnEncodingRules.CER && tagType != UniversalTagNumber.OctetString)
391 {
393 return;
394 }
395 int num3 = _offset - 1 - num2;
396 int num4 = num2 + 1;
397 if (tagType == UniversalTagNumber.OctetString)
398 {
399 if (RuleSet == AsnEncodingRules.CER && num3 > 1000)
400 {
401 int result;
402 int num5 = Math.DivRem(num3, 1000, out result);
403 int num6 = 4 * num5 + 2 + GetEncodedLengthSubsequentByteCount(result);
406 Span<byte> span = _buffer.AsSpan(num4 + num6, num3);
408 int num7 = num4 + num3 + num6 + 2;
411 return;
412 }
413 int num8 = tag.CalculateEncodedSize();
414 tag.AsPrimitive().Encode(_buffer.AsSpan(num2 - num8, num8));
415 }
418 {
419 _buffer[num2] = (byte)num3;
420 return;
421 }
424 int offset = _offset;
425 _offset = num2;
428 }
429
430 private static void SortContents(byte[] buffer, int start, int end)
431 {
432 int num = end - start;
433 if (num == 0)
434 {
435 return;
436 }
438 List<(int, int)> list = new List<(int, int)>();
439 int num2 = start;
440 while (asnReader.HasData)
441 {
442 ReadOnlyMemory<byte> readOnlyMemory = asnReader.ReadEncodedValue();
443 list.Add((num2, readOnlyMemory.Length));
444 num2 += readOnlyMemory.Length;
445 }
447 list.Sort(comparer);
449 num2 = 0;
450 foreach (var (srcOffset, num3) in list)
451 {
453 num2 += num3;
454 }
455 Buffer.BlockCopy(array, 0, buffer, start, num);
457 }
458
459 internal static void Reverse(Span<byte> span)
460 {
461 int num = 0;
462 int num2 = span.Length - 1;
463 while (num < num2)
464 {
465 byte b = span[num];
466 span[num] = span[num2];
467 span[num2] = b;
468 num++;
469 num2--;
470 }
471 }
472
474 {
475 if (tag.HasValue)
476 {
477 Asn1Tag value = tag.Value;
478 if (value.TagClass == TagClass.Universal && value.TagValue != (int)universalTagNumber)
479 {
481 }
482 }
483 }
484
490
492 {
494 {
496 }
497 if (bitString.Length == 0 && unusedBitCount != 0)
498 {
500 }
501 byte lastByte = (byte)((!bitString.IsEmpty) ? bitString[bitString.Length - 1] : 0);
502 if (!CheckValidLastByte(lastByte, unusedBitCount))
503 {
504 throw new ArgumentException(System.SR.Argument_UnusedBitWasSet, "unusedBitCount");
505 }
506 if (RuleSet == AsnEncodingRules.CER && bitString.Length >= 1000)
507 {
509 return;
510 }
511 WriteTag(tag.AsPrimitive());
512 WriteLength(bitString.Length + 1);
514 _offset++;
516 _offset += bitString.Length;
517 }
518
519 private static bool CheckValidLastByte(byte lastByte, int unusedBitCount)
520 {
521 int num = (1 << unusedBitCount) - 1;
522 return (lastByte & num) == 0;
523 }
524
526 {
527 int result;
528 int num = Math.DivRem(contentLength, 999, out result);
529 int num2 = ((result != 0) ? (3 + result + GetEncodedLengthSubsequentByteCount(result)) : 0);
530 return num * 1004 + num2 + 3 + tag.CalculateEncodedSize();
531 }
532
564
565 public void WriteBoolean(bool value, Asn1Tag? tag = null)
566 {
568 WriteBooleanCore(tag?.AsPrimitive() ?? Asn1Tag.Boolean, value);
569 }
570
571 private void WriteBooleanCore(Asn1Tag tag, bool value)
572 {
573 WriteTag(tag);
574 WriteLength(1);
575 _buffer[_offset] = (byte)(value ? 255u : 0u);
576 _offset++;
577 }
578
579 public void WriteEnumeratedValue(Enum value, Asn1Tag? tag = null)
580 {
581 if (value == null)
582 {
583 throw new ArgumentNullException("value");
584 }
585 WriteEnumeratedValue(tag?.AsPrimitive() ?? Asn1Tag.Enumerated, value.GetType(), value);
586 }
587
589 {
590 WriteEnumeratedValue(tag?.AsPrimitive() ?? Asn1Tag.Enumerated, typeof(TEnum), value);
591 }
592
593 private void WriteEnumeratedValue(Asn1Tag tag, Type tEnum, object value)
594 {
596 Type enumUnderlyingType = tEnum.GetEnumUnderlyingType();
597 if (tEnum.IsDefined(typeof(FlagsAttribute), inherit: false))
598 {
600 }
601 if (enumUnderlyingType == typeof(ulong))
602 {
603 ulong value2 = Convert.ToUInt64(value);
605 }
606 else
607 {
608 long value3 = Convert.ToInt64(value);
610 }
611 }
612
614 {
615 CheckUniversalTag(tag, UniversalTagNumber.GeneralizedTime);
617 }
618
620 {
621 DateTimeOffset dateTimeOffset = value.ToUniversalTime();
622 if (dateTimeOffset.Year > 9999)
623 {
624 throw new ArgumentOutOfRangeException("value");
625 }
628 {
629 long num = dateTimeOffset.Ticks % 10000000;
630 if (num != 0L)
631 {
632 destination = stackalloc byte[9];
633 decimal value2 = num;
634 value2 /= 10000000m;
636 {
637 throw new InvalidOperationException();
638 }
639 destination = destination.Slice(1, bytesWritten - 1);
640 }
641 }
642 int length = 15 + destination.Length;
643 WriteTag(tag);
645 int year = dateTimeOffset.Year;
646 int month = dateTimeOffset.Month;
647 int day = dateTimeOffset.Day;
648 int hour = dateTimeOffset.Hour;
649 int minute = dateTimeOffset.Minute;
650 int second = dateTimeOffset.Second;
651 Span<byte> span = _buffer.AsSpan(_offset);
655 {
656 throw new InvalidOperationException();
657 }
658 _offset += 14;
659 destination.CopyTo(span.Slice(14));
660 _offset += destination.Length;
661 _buffer[_offset] = 90;
662 _offset++;
663 }
664
665 public void WriteInteger(long value, Asn1Tag? tag = null)
666 {
668 WriteIntegerCore(tag?.AsPrimitive() ?? Asn1Tag.Integer, value);
669 }
670
671 [CLSCompliant(false)]
672 public void WriteInteger(ulong value, Asn1Tag? tag = null)
673 {
675 WriteNonNegativeIntegerCore(tag?.AsPrimitive() ?? Asn1Tag.Integer, value);
676 }
677
678 public void WriteInteger(BigInteger value, Asn1Tag? tag = null)
679 {
681 WriteIntegerCore(tag?.AsPrimitive() ?? Asn1Tag.Integer, value);
682 }
683
685 {
687 WriteIntegerCore(tag?.AsPrimitive() ?? Asn1Tag.Integer, value);
688 }
689
691 {
693 WriteIntegerUnsignedCore(tag?.AsPrimitive() ?? Asn1Tag.Integer, value);
694 }
695
696 private void WriteIntegerCore(Asn1Tag tag, long value)
697 {
698 if (value >= 0)
699 {
701 return;
702 }
703 int num = ((value >= -128) ? 1 : ((value >= -32768) ? 2 : ((value >= -8388608) ? 3 : ((value >= int.MinValue) ? 4 : ((value >= -549755813888L) ? 5 : ((value >= -140737488355328L) ? 6 : ((value < -36028797018963968L) ? 8 : 7)))))));
704 WriteTag(tag);
705 WriteLength(num);
706 long num2 = value;
707 int num3 = _offset + num - 1;
708 do
709 {
710 _buffer[num3] = (byte)num2;
711 num2 >>= 8;
712 num3--;
713 }
714 while (num3 >= _offset);
715 _offset += num;
716 }
717
719 {
720 int num = ((value < 128) ? 1 : ((value < 32768) ? 2 : ((value < 8388608) ? 3 : ((value < 2147483648u) ? 4 : ((value < 549755813888L) ? 5 : ((value < 140737488355328L) ? 6 : ((value < 36028797018963968L) ? 7 : ((value >= 9223372036854775808uL) ? 9 : 8))))))));
721 WriteTag(tag);
722 WriteLength(num);
723 ulong num2 = value;
724 int num3 = _offset + num - 1;
725 do
726 {
727 _buffer[num3] = (byte)num2;
728 num2 >>= 8;
729 num3--;
730 }
731 while (num3 >= _offset);
732 _offset += num;
733 }
734
736 {
737 if (value.IsEmpty)
738 {
740 }
741 if (value.Length > 1 && value[0] == 0 && value[1] < 128)
742 {
744 }
745 WriteTag(tag);
746 if (value[0] >= 128)
747 {
748 WriteLength(checked(value.Length + 1));
749 _buffer[_offset] = 0;
750 _offset++;
751 }
752 else
753 {
754 WriteLength(value.Length);
755 }
756 value.CopyTo(_buffer.AsSpan(_offset));
757 _offset += value.Length;
758 }
759
761 {
762 if (value.IsEmpty)
763 {
765 }
766 if (value.Length > 1)
767 {
768 ushort num = (ushort)((value[0] << 8) | value[1]);
769 ushort num2 = (ushort)(num & 0xFF80u);
770 if (num2 == 0 || num2 == 65408)
771 {
773 }
774 }
775 WriteTag(tag);
776 WriteLength(value.Length);
777 value.CopyTo(_buffer.AsSpan(_offset));
778 _offset += value.Length;
779 }
780
782 {
783 byte[] array = value.ToByteArray();
785 WriteTag(tag);
786 WriteLength(array.Length);
788 _offset += array.Length;
789 }
790
791 public void WriteNamedBitList(Enum value, Asn1Tag? tag = null)
792 {
793 if (value == null)
794 {
795 throw new ArgumentNullException("value");
796 }
798 WriteNamedBitList(tag, value.GetType(), value);
799 }
800
802 {
805 }
806
807 public void WriteNamedBitList(BitArray value, Asn1Tag? tag = null)
808 {
809 if (value == null)
810 {
811 throw new ArgumentNullException("value");
812 }
814 WriteBitArray(value, tag);
815 }
816
818 {
819 Type enumUnderlyingType = tEnum.GetEnumUnderlyingType();
820 if (!tEnum.IsDefined(typeof(FlagsAttribute), inherit: false))
821 {
823 }
824 ulong integralValue;
825 if (enumUnderlyingType == typeof(ulong))
826 {
828 }
829 else
830 {
831 long num = Convert.ToInt64(value);
832 integralValue = (ulong)num;
833 }
835 }
836
837 private void WriteNamedBitList(Asn1Tag? tag, ulong integralValue)
838 {
839 Span<byte> span = stackalloc byte[8];
840 span.Clear();
841 int num = -1;
842 int num2 = 0;
843 while (integralValue != 0L)
844 {
845 if ((integralValue & 1) != 0L)
846 {
847 span[num2 / 8] |= (byte)(128 >> num2 % 8);
848 num = num2;
849 }
850 integralValue >>= 1;
851 num2++;
852 }
853 if (num < 0)
854 {
856 return;
857 }
858 int length = num / 8 + 1;
859 int unusedBitCount = 7 - num % 8;
860 WriteBitString(span.Slice(0, length), unusedBitCount, tag);
861 }
862
864 {
865 if (value.Count == 0)
866 {
868 return;
869 }
870 int num = checked(value.Count + 7) / 8;
871 int unusedBitCount = num * 8 - value.Count;
873 value.CopyTo(array, 0);
874 Span<byte> span = array.AsSpan(0, num);
878 }
879
880 public void WriteNull(Asn1Tag? tag = null)
881 {
883 WriteNullCore(tag?.AsPrimitive() ?? Asn1Tag.Null);
884 }
885
886 private void WriteNullCore(Asn1Tag tag)
887 {
888 WriteTag(tag);
889 WriteLength(0);
890 }
891
892 public Scope PushOctetString(Asn1Tag? tag = null)
893 {
894 CheckUniversalTag(tag, UniversalTagNumber.OctetString);
895 return PushTag(tag?.AsConstructed() ?? Asn1Tag.ConstructedOctetString, UniversalTagNumber.OctetString);
896 }
897
898 public void PopOctetString(Asn1Tag? tag = null)
899 {
900 CheckUniversalTag(tag, UniversalTagNumber.OctetString);
901 PopTag(tag?.AsConstructed() ?? Asn1Tag.ConstructedOctetString, UniversalTagNumber.OctetString);
902 }
903
909
911 {
912 if (RuleSet == AsnEncodingRules.CER && octetString.Length > 1000)
913 {
915 return;
916 }
917 WriteTag(tag.AsPrimitive());
918 WriteLength(octetString.Length);
920 _offset += octetString.Length;
921 }
922
924 {
925 WriteTag(tag.AsConstructed());
926 WriteLength(-1);
927 int result;
928 int num = Math.DivRem(payload.Length, 1000, out result);
929 int num2 = ((result != 0) ? (2 + result + GetEncodedLengthSubsequentByteCount(result)) : 0);
930 int pendingCount = num * 1004 + num2 + 2;
932 byte[] buffer = _buffer;
933 int offset = _offset;
937 while (readOnlySpan.Length > 1000)
938 {
940 WriteLength(1000);
941 destination = _buffer.AsSpan(_offset);
942 readOnlySpan.Slice(0, 1000).CopyTo(destination);
943 _offset += 1000;
944 readOnlySpan = readOnlySpan.Slice(1000);
945 }
948 destination = _buffer.AsSpan(_offset);
950 _offset += readOnlySpan.Length;
952 }
953
954 public void WriteObjectIdentifier(string oidValue, Asn1Tag? tag = null)
955 {
956 if (oidValue == null)
957 {
958 throw new ArgumentNullException("oidValue");
959 }
960 WriteObjectIdentifier(oidValue.AsSpan(), tag);
961 }
962
964 {
965 CheckUniversalTag(tag, UniversalTagNumber.ObjectIdentifier);
967 }
968
970 {
971 if (oidValue.Length < 3)
972 {
974 }
975 if (oidValue[1] != '.')
976 {
978 }
980 int num = 0;
981 try
982 {
983 int num2 = oidValue[0] switch
984 {
985 '0' => 0,
986 '1' => 1,
987 '2' => 2,
988 _ => throw new ArgumentException(System.SR.Argument_InvalidOidValue, "oidValue"),
989 };
992 subIdentifier += (BigInteger)(40 * num2);
993 int num3 = EncodeSubIdentifier(array.AsSpan(num), ref subIdentifier);
994 num += num3;
995 while (!oidValue2.IsEmpty)
996 {
999 num += num3;
1000 }
1001 WriteTag(tag);
1002 WriteLength(num);
1004 _offset += num;
1005 }
1006 finally
1007 {
1009 }
1010 }
1011
1013 {
1014 int num = oidValue.IndexOf('.');
1015 if (num == -1)
1016 {
1017 num = oidValue.Length;
1018 }
1019 else if (num == 0 || num == oidValue.Length - 1)
1020 {
1021 throw new ArgumentException(System.SR.Argument_InvalidOidValue, "oidValue");
1022 }
1024 for (int i = 0; i < num; i++)
1025 {
1026 if (i > 0 && zero == 0L)
1027 {
1028 throw new ArgumentException(System.SR.Argument_InvalidOidValue, "oidValue");
1029 }
1030 zero *= (BigInteger)10;
1031 zero += (BigInteger)AtoI(oidValue[i]);
1032 }
1033 oidValue = oidValue.Slice(Math.Min(oidValue.Length, num + 1));
1034 return zero;
1035 }
1036
1037 private static int AtoI(char c)
1038 {
1039 if (c >= '0' && c <= '9')
1040 {
1041 return c - 48;
1042 }
1043 throw new ArgumentException(System.SR.Argument_InvalidOidValue, "oidValue");
1044 }
1045
1047 {
1048 if (subIdentifier.IsZero)
1049 {
1050 dest[0] = 0;
1051 return 1;
1052 }
1054 int num = 0;
1055 do
1056 {
1058 byte b = (byte)bigInteger2;
1060 {
1061 b = (byte)(b | 0x80u);
1062 }
1063 bigInteger >>= 7;
1064 dest[num] = b;
1065 num++;
1066 }
1067 while (bigInteger != BigInteger.Zero);
1068 Reverse(dest.Slice(0, num));
1069 return num;
1070 }
1071
1072 public Scope PushSequence(Asn1Tag? tag = null)
1073 {
1075 return PushSequenceCore(tag?.AsConstructed() ?? Asn1Tag.Sequence);
1076 }
1077
1078 public void PopSequence(Asn1Tag? tag = null)
1079 {
1081 PopSequenceCore(tag?.AsConstructed() ?? Asn1Tag.Sequence);
1082 }
1083
1085 {
1086 return PushTag(tag, UniversalTagNumber.Sequence);
1087 }
1088
1089 private void PopSequenceCore(Asn1Tag tag)
1090 {
1092 }
1093
1094 public Scope PushSetOf(Asn1Tag? tag = null)
1095 {
1097 return PushSetOfCore(tag?.AsConstructed() ?? Asn1Tag.SetOf);
1098 }
1099
1100 public void PopSetOf(Asn1Tag? tag = null)
1101 {
1103 PopSetOfCore(tag?.AsConstructed() ?? Asn1Tag.SetOf);
1104 }
1105
1107 {
1108 return PushTag(tag, UniversalTagNumber.Set);
1109 }
1110
1111 private void PopSetOfCore(Asn1Tag tag)
1112 {
1113 bool sortContents = RuleSet == AsnEncodingRules.CER || RuleSet == AsnEncodingRules.DER;
1115 }
1116
1118 {
1119 if (value == null)
1120 {
1121 throw new ArgumentNullException("value");
1122 }
1123 WriteCharacterString(encodingType, value.AsSpan(), tag);
1124 }
1125
1132
1134 {
1135 int byteCount = encoding.GetByteCount(str);
1136 if (RuleSet == AsnEncodingRules.CER && byteCount > 1000)
1137 {
1139 return;
1140 }
1141 WriteTag(tag.AsPrimitive());
1144 int bytes2 = encoding.GetBytes(str, bytes);
1145 if (bytes2 != byteCount)
1146 {
1147 throw new InvalidOperationException();
1148 }
1149 _offset += byteCount;
1150 }
1151
1153 {
1155 int bytes = encoding.GetBytes(str, array);
1156 if (bytes != size)
1157 {
1158 throw new InvalidOperationException();
1159 }
1160 WriteConstructedCerOctetString(tag, array.AsSpan(0, size));
1162 }
1163
1164 public void WriteUtcTime(DateTimeOffset value, Asn1Tag? tag = null)
1165 {
1167 WriteUtcTimeCore(tag?.AsPrimitive() ?? Asn1Tag.UtcTime, value);
1168 }
1169
1171 {
1173 value = value.ToUniversalTime();
1174 if (value.Year > twoDigitYearMax || value.Year <= twoDigitYearMax - 100)
1175 {
1176 throw new ArgumentOutOfRangeException("value");
1177 }
1178 WriteUtcTimeCore(tag?.AsPrimitive() ?? Asn1Tag.UtcTime, value);
1179 }
1180
1182 {
1183 WriteTag(tag);
1184 WriteLength(13);
1185 DateTimeOffset dateTimeOffset = value.ToUniversalTime();
1186 int year = dateTimeOffset.Year;
1187 int month = dateTimeOffset.Month;
1188 int day = dateTimeOffset.Day;
1189 int hour = dateTimeOffset.Hour;
1190 int minute = dateTimeOffset.Minute;
1191 int second = dateTimeOffset.Second;
1192 Span<byte> span = _buffer.AsSpan(_offset);
1193 StandardFormat format = new StandardFormat('D', 2);
1194 if (!Utf8Formatter.TryFormat(year % 100, span.Slice(0, 2), out var bytesWritten, format) || !Utf8Formatter.TryFormat(month, span.Slice(2, 2), out bytesWritten, format) || !Utf8Formatter.TryFormat(day, span.Slice(4, 2), out bytesWritten, format) || !Utf8Formatter.TryFormat(hour, span.Slice(6, 2), out bytesWritten, format) || !Utf8Formatter.TryFormat(minute, span.Slice(8, 2), out bytesWritten, format) || !Utf8Formatter.TryFormat(second, span.Slice(10, 2), out bytesWritten, format))
1195 {
1196 throw new InvalidOperationException();
1197 }
1198 _buffer[_offset + 12] = 90;
1199 _offset += 13;
1200 }
1201}
static void Reverse(Array array)
Definition Array.cs:2207
static unsafe void Clear(Array array)
Definition Array.cs:755
static void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count)
Definition Buffer.cs:102
static bool TryFormat(bool value, Span< byte > destination, out int bytesWritten, StandardFormat format=default(StandardFormat))
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
bool ICollection< KeyValuePair< TKey, TValue > >. Contains(KeyValuePair< TKey, TValue > keyValuePair)
void Add(TKey key, TValue value)
static long ToInt64(object? value)
Definition Convert.cs:1623
static ulong ToUInt64(object? value)
Definition Convert.cs:1738
static Encoding GetEncoding(UniversalTagNumber encodingType)
static void ReverseBitsPerByte(Span< byte > value)
static bool TryReadEncodedValue(ReadOnlySpan< byte > source, AsnEncodingRules ruleSet, out Asn1Tag tag, out int contentOffset, out int contentLength, out int bytesConsumed)
Definition AsnDecoder.cs:34
void WriteNullCore(Asn1Tag tag)
Definition AsnWriter.cs:886
void EnsureWriteCapacity(int pendingCount)
Definition AsnWriter.cs:246
void WriteObjectIdentifier(string oidValue, Asn1Tag? tag=null)
Definition AsnWriter.cs:954
Scope PushSetOf(Asn1Tag? tag=null)
void WriteNamedBitList(Asn1Tag? tag, ulong integralValue)
Definition AsnWriter.cs:837
void WriteConstructedCerOctetString(Asn1Tag tag, ReadOnlySpan< byte > payload)
Definition AsnWriter.cs:923
void WriteObjectIdentifierCore(Asn1Tag tag, ReadOnlySpan< char > oidValue)
Definition AsnWriter.cs:969
void WriteCharacterStringCore(Asn1Tag tag, Encoding encoding, ReadOnlySpan< char > str)
bool TryEncode(Span< byte > destination, out int bytesWritten)
Definition AsnWriter.cs:173
void WriteInteger(BigInteger value, Asn1Tag? tag=null)
Definition AsnWriter.cs:678
void WriteInteger(ReadOnlySpan< byte > value, Asn1Tag? tag=null)
Definition AsnWriter.cs:684
void WriteNonNegativeIntegerCore(Asn1Tag tag, ulong value)
Definition AsnWriter.cs:718
bool EncodedValueEquals(ReadOnlySpan< byte > other)
Definition AsnWriter.cs:232
void WriteOctetString(ReadOnlySpan< byte > value, Asn1Tag? tag=null)
Definition AsnWriter.cs:904
void PopOctetString(Asn1Tag? tag=null)
Definition AsnWriter.cs:898
bool EncodedValueEquals(AsnWriter other)
Definition AsnWriter.cs:237
void WriteUtcTimeCore(Asn1Tag tag, DateTimeOffset value)
void PopSequenceCore(Asn1Tag tag)
Scope PushSequence(Asn1Tag? tag=null)
Stack< StackFrame > _nestingStack
Definition AsnWriter.cs:140
Scope PushSequenceCore(Asn1Tag tag)
void CopyTo(AsnWriter destination)
Definition AsnWriter.cs:328
void WriteConstructedCerCharacterString(Asn1Tag tag, Encoding encoding, ReadOnlySpan< char > str, int size)
static int AtoI(char c)
int Encode(Span< byte > destination)
Definition AsnWriter.cs:195
void PopSetOf(Asn1Tag? tag=null)
void WriteBoolean(bool value, Asn1Tag? tag=null)
Definition AsnWriter.cs:565
ReadOnlySpan< byte > EncodeAsSpan()
Definition AsnWriter.cs:218
void WriteGeneralizedTime(DateTimeOffset value, bool omitFractionalSeconds=false, Asn1Tag? tag=null)
Definition AsnWriter.cs:613
void WriteIntegerCore(Asn1Tag tag, long value)
Definition AsnWriter.cs:696
void WriteIntegerCore(Asn1Tag tag, ReadOnlySpan< byte > value)
Definition AsnWriter.cs:760
static BigInteger ParseSubIdentifier(ref ReadOnlySpan< char > oidValue)
void PopTag(Asn1Tag tag, UniversalTagNumber tagType, bool sortContents=false)
Definition AsnWriter.cs:374
void WriteNamedBitList(BitArray value, Asn1Tag? tag=null)
Definition AsnWriter.cs:807
void WriteBitArray(BitArray value, Asn1Tag? tag)
Definition AsnWriter.cs:863
Scope PushTag(Asn1Tag tag, UniversalTagNumber tagType)
Definition AsnWriter.cs:362
Scope PushOctetString(Asn1Tag? tag=null)
Definition AsnWriter.cs:892
static void SortContents(byte[] buffer, int start, int end)
Definition AsnWriter.cs:430
static void Reverse(Span< byte > span)
Definition AsnWriter.cs:459
static void CheckUniversalTag(Asn1Tag? tag, UniversalTagNumber universalTagNumber)
Definition AsnWriter.cs:473
void WriteEnumeratedValue< TEnum >(TEnum value, Asn1Tag? tag=null)
Definition AsnWriter.cs:588
static int GetEncodedLengthSubsequentByteCount(int length)
Definition AsnWriter.cs:303
void WriteInteger(ulong value, Asn1Tag? tag=null)
Definition AsnWriter.cs:672
void WriteEnumeratedValue(Enum value, Asn1Tag? tag=null)
Definition AsnWriter.cs:579
void WriteIntegerUnsignedCore(Asn1Tag tag, ReadOnlySpan< byte > value)
Definition AsnWriter.cs:735
static bool CheckValidLastByte(byte lastByte, int unusedBitCount)
Definition AsnWriter.cs:519
void WriteNamedBitList< TEnum >(TEnum value, Asn1Tag? tag=null)
Definition AsnWriter.cs:801
void WriteUtcTime(DateTimeOffset value, Asn1Tag? tag=null)
static int DetermineCerBitStringTotalLength(Asn1Tag tag, int contentLength)
Definition AsnWriter.cs:525
void WriteUtcTime(DateTimeOffset value, int twoDigitYearMax, Asn1Tag? tag=null)
void WriteEnumeratedValue(Asn1Tag tag, Type tEnum, object value)
Definition AsnWriter.cs:593
void WriteLength(int length)
Definition AsnWriter.cs:272
void PopSetOfCore(Asn1Tag tag)
void WriteInteger(long value, Asn1Tag? tag=null)
Definition AsnWriter.cs:665
void WriteConstructedCerBitString(Asn1Tag tag, ReadOnlySpan< byte > payload, int unusedBitCount)
Definition AsnWriter.cs:533
void WriteBitString(ReadOnlySpan< byte > value, int unusedBitCount=0, Asn1Tag? tag=null)
Definition AsnWriter.cs:485
static int EncodeSubIdentifier(Span< byte > dest, ref BigInteger subIdentifier)
void WriteCharacterString(UniversalTagNumber encodingType, string value, Asn1Tag? tag=null)
void WriteGeneralizedTimeCore(Asn1Tag tag, DateTimeOffset value, bool omitFractionalSeconds)
Definition AsnWriter.cs:619
void WriteBooleanCore(Asn1Tag tag, bool value)
Definition AsnWriter.cs:571
Scope PushSetOfCore(Asn1Tag tag)
void WriteCharacterString(UniversalTagNumber encodingType, ReadOnlySpan< char > str, Asn1Tag? tag=null)
AsnWriter(AsnEncodingRules ruleSet)
Definition AsnWriter.cs:144
void WriteTag(Asn1Tag tag)
Definition AsnWriter.cs:261
void WriteObjectIdentifier(ReadOnlySpan< char > oidValue, Asn1Tag? tag=null)
Definition AsnWriter.cs:963
void WriteNull(Asn1Tag? tag=null)
Definition AsnWriter.cs:880
void WriteNamedBitList(Enum value, Asn1Tag? tag=null)
Definition AsnWriter.cs:791
void WriteOctetStringCore(Asn1Tag tag, ReadOnlySpan< byte > octetString)
Definition AsnWriter.cs:910
void WriteEncodedValue(ReadOnlySpan< byte > value)
Definition AsnWriter.cs:344
void WriteBitStringCore(Asn1Tag tag, ReadOnlySpan< byte > bitString, int unusedBitCount)
Definition AsnWriter.cs:491
void WriteIntegerUnsigned(ReadOnlySpan< byte > value, Asn1Tag? tag=null)
Definition AsnWriter.cs:690
void WriteNamedBitList(Asn1Tag? tag, Type tEnum, Enum value)
Definition AsnWriter.cs:817
void PopSequence(Asn1Tag? tag=null)
void WriteIntegerCore(Asn1Tag tag, BigInteger value)
Definition AsnWriter.cs:781
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static int DivRem(int a, int b, out int result)
Definition Math.cs:329
static string Argument_DestinationTooShort
Definition SR.cs:14
static string Argument_UnusedBitWasSet
Definition SR.cs:38
static string Argument_UnusedBitCountMustBeZero
Definition SR.cs:34
static string Argument_EnumeratedValueRequiresNonFlagsEnum
Definition SR.cs:16
static string Argument_IntegerRedundantByte
Definition SR.cs:30
static string Argument_WriteEncodedValue_OneValueAtATime
Definition SR.cs:40
static string Argument_InvalidOidValue
Definition SR.cs:20
static string Argument_NamedBitListRequiresFlagsEnum
Definition SR.cs:22
static string Argument_IntegerCannotBeEmpty
Definition SR.cs:28
static string Argument_UnusedBitCountRange
Definition SR.cs:36
static string AsnWriter_PopWrongTag
Definition SR.cs:44
static string AsnWriter_EncodeUnbalancedStack
Definition SR.cs:42
static string Argument_UniversalValueIsFixed
Definition SR.cs:32
Definition SR.cs:7
static void Return(byte[] array, int clearSize=-1)
Definition CryptoPool.cs:12
static byte[] Rent(int minimumLength)
Definition CryptoPool.cs:7
virtual byte[] GetBytes(char[] chars)
Definition Encoding.cs:781
virtual int GetByteCount(char[] chars)
Definition Encoding.cs:713
static readonly Asn1Tag Integer
Definition Asn1Tag.cs:13
static readonly Asn1Tag Enumerated
Definition Asn1Tag.cs:27
static readonly Asn1Tag Sequence
Definition Asn1Tag.cs:29
static readonly Asn1Tag ConstructedOctetString
Definition Asn1Tag.cs:21
static readonly Asn1Tag PrimitiveBitString
Definition Asn1Tag.cs:15
bool TryEncode(Span< byte > destination, out int bytesWritten)
Definition Asn1Tag.cs:175
static readonly Asn1Tag SetOf
Definition Asn1Tag.cs:31
int Encode(Span< byte > destination)
Definition Asn1Tag.cs:209
static readonly Asn1Tag UtcTime
Definition Asn1Tag.cs:33
static readonly Asn1Tag PrimitiveOctetString
Definition Asn1Tag.cs:19
static readonly Asn1Tag GeneralizedTime
Definition Asn1Tag.cs:35
static readonly Asn1Tag ObjectIdentifier
Definition Asn1Tag.cs:25
static readonly Asn1Tag Boolean
Definition Asn1Tag.cs:11
bool Equals(Asn1Tag other)
Definition Asn1Tag.cs:218
static readonly Asn1Tag Null
Definition Asn1Tag.cs:23
void Deconstruct(out Asn1Tag tag, out int offset, out UniversalTagNumber itemType)
Definition AsnWriter.cs:55
override bool Equals([NotNullWhen(true)] object obj)
Definition AsnWriter.cs:71
static bool operator==(StackFrame left, StackFrame right)
Definition AsnWriter.cs:85
StackFrame(Asn1Tag tag, int offset, UniversalTagNumber itemType)
Definition AsnWriter.cs:48
static BigInteger Zero
Definition BigInteger.cs:32