@@ -24,6 +24,7 @@ public class Asn1Reader {
2424 static readonly List < Byte > _excludedTags = new List < Byte > (
2525 new Byte [ ] { 0 , 1 , 2 , 5 , 6 , 9 , 10 , 13 }
2626 ) ;
27+ readonly List < Byte > _rawData = new List < Byte > ( ) ;
2728 readonly Dictionary < Int64 , AsnInternalMap > _offsetMap = new Dictionary < Int64 , AsnInternalMap > ( ) ;
2829 readonly List < Byte > _multiNestedTypes = new List < Byte > (
2930 new [ ] {
@@ -94,6 +95,10 @@ public Asn1Reader(Byte[] rawData) : this(rawData, 0) { }
9495 /// </summary>
9596 public Int32 PayloadLength { get ; private set ; }
9697 /// <summary>
98+ /// Gets the internal ASN.1 stream length in bytes.
99+ /// </summary>
100+ public Int32 Length => _rawData . Count ;
101+ /// <summary>
97102 /// This property is subject to change.
98103 /// </summary>
99104 [ Obsolete ( "Use 'NextSiblingOffset' property instead" , false ) ]
@@ -113,17 +118,27 @@ public Asn1Reader(Byte[] rawData) : this(rawData, 0) { }
113118 /// <summary>
114119 /// Get's original ASN.1-encoded byte array.
115120 /// </summary>
116- public Byte [ ] RawData { get ; private set ; }
121+ [ Obsolete ( "" , true ) ]
122+ public Byte [ ] RawData => _rawData . ToArray ( ) ;
123+ /// <summary>
124+ ///
125+ /// </summary>
126+ /// <param name="index"></param>
127+ public Byte this [ Int32 index ] => _rawData [ index ] ;
117128
118129 void decode ( Byte [ ] raw , Int32 pOffset ) {
119130 IsConstructed = false ;
120- if ( raw != null ) { RawData = raw ; }
131+ if ( raw != null ) {
132+ _rawData . Clear ( ) ;
133+ _rawData . AddRange ( raw ) ;
134+ }
121135 Offset = pOffset ;
122- Tag = RawData [ Offset ] ;
136+ Tag = _rawData [ Offset ] ;
123137 calculateLength ( ) ;
124138 // strip possible unnecessary bytes
125- if ( raw != null && TagLength != RawData . Length ) {
126- RawData = raw . Take ( TagLength ) . ToArray ( ) ;
139+ if ( raw != null && TagLength != _rawData . Count ) {
140+ _rawData . Clear ( ) ;
141+ _rawData . AddRange ( raw . Take ( TagLength ) . ToArray ( ) ) ;
127142 }
128143 TagName = GetTagName ( Tag ) ;
129144 // 0 Tag is reserved for BER and is not available in DER
@@ -138,7 +153,7 @@ void decode(Byte[] raw, Int32 pOffset) {
138153 }
139154 if ( PayloadLength == 0 ) {
140155 // if current node is the last node in binary data, set NextOffset to 0, this means EOF.
141- NextOffset = Offset + TagLength == RawData . Length
156+ NextOffset = Offset + TagLength == _rawData . Count
142157 ? 0
143158 : Offset + TagLength ;
144159 NextSiblingOffset = currentPosition . LevelEnd == 0 || Offset - currentPosition . LevelStart + TagLength == currentPosition . LevelEnd
@@ -155,7 +170,7 @@ void decode(Byte[] raw, Int32 pOffset) {
155170 // skip unused bits byte
156171 ? PayloadStartOffset + 1
157172 : PayloadStartOffset
158- : Offset + TagLength < RawData . Length
173+ : Offset + TagLength < _rawData . Count
159174 ? Offset + TagLength
160175 : 0 ;
161176 }
@@ -194,7 +209,10 @@ void parseNestedType() {
194209 }
195210 }
196211 Boolean validateArrayBoundaries ( Int64 start ) {
197- return start >= 0 && start < RawData . Length && RawData [ start ] != 0 ;
212+ if ( start > Int32 . MaxValue ) {
213+ return false ;
214+ }
215+ return start >= 0 && start < _rawData . Count && _rawData [ ( Int32 ) start ] != 0 ;
198216 }
199217 /// <summary>
200218 /// Checks if current primitive type is sub-typed (contains nested types) or not.
@@ -207,8 +225,11 @@ Boolean validateArrayBoundaries(Int64 start) {
207225 /// <strong>True</strong> if current type has proper single nested type, otherwise <strong>False</strong>.
208226 /// </returns>
209227 Boolean testNestedForUniversal ( Int64 start , Int32 estimatedLength ) {
228+ if ( start > Int32 . MaxValue ) {
229+ return false ;
230+ }
210231 // if current type is primitive, then nested type can be either, primitive or constructed only.
211- if ( RawData [ start ] >= ( Byte ) Asn1Class . APPLICATION ) {
232+ if ( _rawData [ ( Int32 ) start ] >= ( Byte ) Asn1Class . APPLICATION ) {
212233 return false ;
213234 }
214235 // otherwise, attempt to resolve nested type. Only single nested type is allowed for primitive types.
@@ -243,20 +264,20 @@ Boolean predict(Int64 start, Int32 projectedLength, Boolean assignMap, out Int32
243264 return sum == projectedLength ;
244265 }
245266 void calculateLength ( ) {
246- if ( RawData [ Offset + 1 ] < 128 ) {
267+ if ( _rawData [ Offset + 1 ] < 128 ) {
247268 PayloadStartOffset = Offset + 2 ;
248- PayloadLength = RawData [ Offset + 1 ] ;
269+ PayloadLength = _rawData [ Offset + 1 ] ;
249270 TagLength = PayloadLength + 2 ;
250271 } else {
251- Int32 lengthBytes = RawData [ Offset + 1 ] - 128 ;
272+ Int32 lengthBytes = _rawData [ Offset + 1 ] - 128 ;
252273 // max length can be encoded by using 4 bytes.
253274 if ( lengthBytes > 4 ) {
254275 throw new OverflowException ( "Data length is too large." ) ;
255276 }
256277 PayloadStartOffset = Offset + 2 + lengthBytes ;
257- PayloadLength = RawData [ Offset + 2 ] ;
278+ PayloadLength = _rawData [ Offset + 2 ] ;
258279 for ( Int32 i = Offset + 3 ; i < PayloadStartOffset ; i ++ ) {
259- PayloadLength = ( PayloadLength << 8 ) | RawData [ i ] ;
280+ PayloadLength = ( PayloadLength << 8 ) | _rawData [ i ] ;
260281 }
261282 TagLength = PayloadLength + lengthBytes + 2 ;
262283 }
@@ -267,18 +288,21 @@ void calculateLength() {
267288 /// <param name="offset">Start offset for suggested nested type.</param>
268289 /// <returns>Estimated full tag length for nested type.</returns>
269290 Int64 calculatePredictLength ( Int64 offset ) {
270- if ( offset + 1 >= RawData . Length || offset < 0 ) { return Int32 . MaxValue ; }
271- if ( RawData [ offset + 1 ] < 128 ) {
272- return RawData [ offset + 1 ] + 2 ;
291+ if ( offset + 1 >= _rawData . Count || offset < 0 ) {
292+ return Int32 . MaxValue ;
293+ }
294+
295+ if ( _rawData [ ( Int32 ) ( offset + 1 ) ] < 128 ) {
296+ return _rawData [ ( Int32 ) ( offset + 1 ) ] + 2 ;
273297 }
274- Int32 lengthBytes = RawData [ offset + 1 ] - 128 ;
298+ Int32 lengthBytes = _rawData [ ( Int32 ) ( offset + 1 ) ] - 128 ;
275299 // max length can be encoded by using 4 bytes.
276- if ( lengthBytes > 4 ) {
300+ if ( lengthBytes > 4 || offset + 2 >= _rawData . Count ) {
277301 return Int32 . MaxValue ;
278302 }
279- Int32 ppayloadLength = RawData [ offset + 2 ] ;
280- for ( Int64 i = offset + 3 ; i < offset + 2 + lengthBytes ; i ++ ) {
281- ppayloadLength = ( ppayloadLength << 8 ) | RawData [ i ] ;
303+ Int32 ppayloadLength = _rawData [ ( Int32 ) ( offset + 2 ) ] ;
304+ for ( Int32 i = ( Int32 ) ( offset + 3 ) ; i < offset + 2 + lengthBytes ; i ++ ) {
305+ ppayloadLength = ( ppayloadLength << 8 ) | _rawData [ i ] ;
282306 }
283307 // 2 -- transitional + tag
284308 return ppayloadLength + lengthBytes + 2 ;
@@ -301,21 +325,28 @@ void moveAndExpectTypes(Func<Boolean> action, params Byte[] expectedTypes) {
301325 /// </summary>
302326 /// <returns>Current structure header. Header contains tag and tag length byte (or bytes).</returns>
303327 public Byte [ ] GetHeader ( ) {
304- return RawData . Skip ( Offset ) . Take ( PayloadStartOffset - Offset ) . ToArray ( ) ;
328+ return _rawData . Skip ( Offset ) . Take ( PayloadStartOffset - Offset ) . ToArray ( ) ;
305329 }
306330 /// <summary>
307331 /// Gets the byte array of the current structure's payload.
308332 /// </summary>
309333 /// <returns>Byte array of the current structure's payload</returns>
310334 public Byte [ ] GetPayload ( ) {
311- return RawData . Skip ( PayloadStartOffset ) . Take ( PayloadLength ) . ToArray ( ) ;
335+ return _rawData . Skip ( PayloadStartOffset ) . Take ( PayloadLength ) . ToArray ( ) ;
312336 }
313337 /// <summary>
314338 /// Gets the raw data of the tag, which includes tag, length bytes and payload.
315339 /// </summary>
316340 /// <returns>A full binary copy of the tag.</returns>
317341 public Byte [ ] GetTagRawData ( ) {
318- return RawData . Skip ( Offset ) . Take ( TagLength ) . ToArray ( ) ;
342+ return _rawData . Skip ( Offset ) . Take ( TagLength ) . ToArray ( ) ;
343+ }
344+ /// <summary>
345+ /// Gets a copy of internal ASN.1 stream. The size of the stream is equals to <see cref="Length"/> member value.
346+ /// </summary>
347+ /// <returns>A full binary copy of the internal byte stream.</returns>
348+ public Byte [ ] GetRawData ( ) {
349+ return _rawData . ToArray ( ) ;
319350 }
320351 /// <summary>
321352 /// Gets the count of nested nodes under node in the current position.
0 commit comments