-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathAsnFormatter.cs
More file actions
177 lines (171 loc) · 8.96 KB
/
AsnFormatter.cs
File metadata and controls
177 lines (171 loc) · 8.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using System;
using System.IO;
namespace SysadminsLV.Asn1Parser;
/// <summary>
/// This class contains methods to convert Base64, Hex and Binary strings to byte array and vice versa.
/// </summary>
public static class AsnFormatter {
/// <summary>
/// Converts and formats byte array to a string. See <see cref="EncodingType"/> for encoding examples.
/// </summary>
/// <param name="rawData">Byte array to format.</param>
/// <param name="encoding">Specifies the encoding for formatting. Default is <strong>HexRaw</strong></param>
/// <param name="format">
/// Specifies the encoding options. The default behavior is to use a carriage return/line feed
/// (CR/LF) pair (0x0D/0x0A) to represent a new line.
/// </param>
/// <param name="forceUpperCase">
/// Specifies whether the force hex octet representation in upper case. Default is lower case.
/// <para>
/// This parameter has effect only when hex encoding is selected in the <strong>encoding</strong> parameter:
/// <strong>Hex</strong>, <strong>HexRaw</strong>, <strong>HexAddress</strong>, <strong>HexAscii</strong>
/// and <strong>HexAsciiAddress</strong>. For other values, this parameter is silently ignored.
/// </para>
/// </param>
/// <exception cref="ArgumentException">An invalid encoding type was specified.</exception>
/// <returns>Encoded and formatted string.</returns>
/// <remarks>
/// This method do not support the following encoding types:
/// <list type="bullet">
/// <item><description>Binary</description></item>
/// <item><description>Base64Any</description></item>
/// <item><description>StringAny</description></item>
/// <item><description>HexAny</description></item>
/// </list>
/// </remarks>
public static String BinaryToString(ReadOnlySpan<Byte> rawData, EncodingType encoding = EncodingType.HexRaw, EncodingFormat format = EncodingFormat.CRLF, Boolean forceUpperCase = false) {
if (rawData.IsEmpty) {
return String.Empty;
}
if (encoding == EncodingType.Base64 || PemHeader.ContainsEncoding(encoding)) {
return BinaryToStringFormatter.ToBase64(rawData, encoding, format);
}
return encoding switch {
EncodingType.Hex => BinaryToStringFormatter.ToHex(rawData, format, forceUpperCase),
EncodingType.HexAddress => BinaryToStringFormatter.ToHexAddress(rawData, format, forceUpperCase),
EncodingType.HexAscii => BinaryToStringFormatter.ToHexAscii(rawData, format, forceUpperCase),
EncodingType.HexAsciiAddress => BinaryToStringFormatter.ToHexAddressAndAscii(rawData, format, forceUpperCase),
EncodingType.HexRaw => BinaryToStringFormatter.ToHexRaw(rawData, format, forceUpperCase),
_ => throw new ArgumentException("Specified encoding is invalid.")
};
}
/// <summary>
/// Converts and formats current position af the <see cref="Asn1Reader"/> object.
/// </summary>
/// <param name="asn"><see cref="Asn1Reader"/> object in the desired state.</param>
/// <param name="encoding">Specifies the encoding for formatting. Default is <strong>HexRaw</strong></param>
/// <param name="format">
/// Specifies the encoding options. The default behavior is to use a carriage return/line feed
/// (CR/LF) pair (0x0D/0x0A) to represent a new line.
/// </param>
/// <param name="forceUpperCase">
/// Specifies whether the force hex octet representation in upper case. Default is lower case.
/// <para>
/// This parameter has effect only when hex encoding is selected in the <strong>encoding</strong> parameter:
/// <strong>Hex</strong>, <strong>HexRaw</strong>, <strong>HexAddress</strong>, <strong>HexAscii</strong>
/// and <strong>HexAsciiAddress</strong>. For other values, this parameter is silently ignored.
/// </para>
/// </param>
/// <exception cref="ArgumentException">An invalid encoding type was specified.</exception>
/// <returns>Encoded and formatted string.</returns>
/// <remarks>
/// This method do not support the following encoding types:
/// <list type="bullet">
/// <item><description>Binary</description></item>
/// <item><description>Base64Any</description></item>
/// <item><description>StringAny</description></item>
/// <item><description>HexAny</description></item>
/// </list>
/// </remarks>
public static String BinaryToString(Asn1Reader asn, EncodingType encoding = EncodingType.HexRaw, EncodingFormat format = EncodingFormat.CRLF, Boolean forceUpperCase = false) {
if (asn is null) {
throw new ArgumentNullException(nameof(asn));
}
return BinaryToString(asn.GetTagRawDataAsMemory().Span, encoding, format, forceUpperCase);
}
/// <summary>
/// Converts previously formatted string back to a byte array.
/// </summary>
/// <param name="input">Formatted string</param>
/// <param name="encoding">Specifies the string encoding</param>
/// <exception cref="ArgumentException">And invalid encoding is specified.</exception>
/// <exception cref="InvalidDataException">The string cannot be decoded.</exception>
/// <returns>Original byte array.</returns>
/// <remarks>
/// This method may not be fully compatible with
/// <see cref="BinaryToString(ReadOnlySpan{Byte}, EncodingType, EncodingFormat, Boolean)">BinaryToString</see>
/// method.
/// <para>
/// If <strong>encoding</strong> parameter is set to <strong>Base64Header</strong>, the method will accept any PEM header
/// and footer.
/// </para>
/// </remarks>
public static Byte[] StringToBinary(String input, EncodingType encoding = EncodingType.Base64) {
Byte[]? rawData;
if (PemHeader.ContainsEncoding(encoding)) {
var pemHeader = PemHeader.GetHeader(encoding);
rawData = StringToBinaryFormatter.FromBase64Header(input, pemHeader.Header);
} else {
rawData = encoding switch {
EncodingType.Binary => StringToBinaryFormatter.FromBinary(input),
EncodingType.Base64 => StringToBinaryFormatter.FromBase64(input),
EncodingType.Base64Any => StringToBinaryFormatter.FromBase64Any(input),
EncodingType.StringAny => StringToBinaryFormatter.FromStringAny(input),
EncodingType.Hex
or EncodingType.HexRaw => StringToBinaryFormatter.FromHex(input),
EncodingType.HexAddress => StringToBinaryFormatter.FromHexAddr(input),
EncodingType.HexAscii => StringToBinaryFormatter.FromHexAscii(input),
EncodingType.HexAsciiAddress => StringToBinaryFormatter.FromHexAddrAscii(input),
EncodingType.HexAny => StringToBinaryFormatter.FromHexAny(input),
_ => throw new ArgumentException("Invalid encoding type is specified.")
};
}
if (rawData is null) {
throw new InvalidDataException("The data is invalid.");
}
return rawData;
}
/// <summary>
/// Attempts to determine input string format.
/// </summary>
/// <param name="input">Formatted string to process.</param>
/// <returns>
/// Resolved input string format. If format cannot be determined, <string>Binary</string> type is returned.
/// </returns>
/// <remarks>
/// Method returns <strong>Base64Header</strong> when input string contains
/// <c>-----BEGIN ...-----</c> PEM header and <c>-----END ...-----</c> PEM footer which is not
/// supported by <see cref="EncodingType"/> enumeration.
/// </remarks>
public static EncodingType TestInputString(String input) {
Byte[]? rawBytes;
foreach (PemHeader pemHeader in PemHeader.GetPemHeaders()) {
rawBytes = StringToBinaryFormatter.FromBase64Header(input, pemHeader.Header);
if (rawBytes is not null) {
return pemHeader.Encoding;
}
}
rawBytes = StringToBinaryFormatter.FromBase64Header(input, String.Empty, true);
if (rawBytes is not null) {
return EncodingType.Base64Header;
}
rawBytes = StringToBinaryFormatter.FromBase64(input);
if (rawBytes is not null) {
return EncodingType.Base64;
}
rawBytes = StringToBinaryFormatter.FromHexAddr(input);
if (rawBytes is not null) {
return EncodingType.HexAddress;
}
rawBytes = StringToBinaryFormatter.FromHexAddrAscii(input);
if (rawBytes is not null) {
return EncodingType.HexAsciiAddress;
}
rawBytes = StringToBinaryFormatter.FromHex(input);
if (rawBytes is not null) {
return EncodingType.Hex;
}
rawBytes = StringToBinaryFormatter.FromHexAscii(input);
return rawBytes is not null ? EncodingType.HexAscii : EncodingType.Binary;
}
}