AirScout/BouncyCastle/crypto/src/asn1/BerOctetString.cs

197 wiersze
5.7 KiB
C#

using System;
using System.Collections;
using System.Diagnostics;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1
{
public class BerOctetString
: DerOctetString, IEnumerable
{
private const int DefaultSegmentLimit = 1000;
public static BerOctetString FromSequence(Asn1Sequence seq)
{
int count = seq.Count;
Asn1OctetString[] v = new Asn1OctetString[count];
for (int i = 0; i < count; ++i)
{
v[i] = GetInstance(seq[i]);
}
return new BerOctetString(v);
}
internal static byte[] FlattenOctetStrings(Asn1OctetString[] octetStrings)
{
int count = octetStrings.Length;
switch (count)
{
case 0:
return EmptyOctets;
case 1:
return octetStrings[0].contents;
default:
{
int totalOctets = 0;
for (int i = 0; i < count; ++i)
{
totalOctets += octetStrings[i].contents.Length;
}
byte[] str = new byte[totalOctets];
int pos = 0;
for (int i = 0; i < count; ++i)
{
byte[] octets = octetStrings[i].contents;
Array.Copy(octets, 0, str, pos, octets.Length);
pos += octets.Length;
}
Debug.Assert(pos == totalOctets);
return str;
}
}
}
private static Asn1OctetString[] ToOctetStringArray(IEnumerable e)
{
IList list = Platform.CreateArrayList(e);
int count = list.Count;
Asn1OctetString[] v = new Asn1OctetString[count];
for (int i = 0; i < count; ++i)
{
v[i] = GetInstance(list[i]);
}
return v;
}
private readonly int segmentLimit;
private readonly Asn1OctetString[] elements;
[Obsolete("Will be removed")]
public BerOctetString(IEnumerable e)
: this(ToOctetStringArray(e))
{
}
public BerOctetString(byte[] contents)
: this(contents, DefaultSegmentLimit)
{
}
public BerOctetString(Asn1OctetString[] elements)
: this(elements, DefaultSegmentLimit)
{
}
public BerOctetString(byte[] contents, int segmentLimit)
: this(contents, null, segmentLimit)
{
}
public BerOctetString(Asn1OctetString[] elements, int segmentLimit)
: this(FlattenOctetStrings(elements), elements, segmentLimit)
{
}
private BerOctetString(byte[] contents, Asn1OctetString[] elements, int segmentLimit)
: base(contents)
{
this.elements = elements;
this.segmentLimit = segmentLimit;
}
/**
* return the DER octets that make up this string.
*/
public IEnumerator GetEnumerator()
{
if (elements == null)
return new ChunkEnumerator(contents, segmentLimit);
return elements.GetEnumerator();
}
[Obsolete("Use GetEnumerator() instead")]
public IEnumerator GetObjects()
{
return GetEnumerator();
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
if (Asn1OutputStream.EncodingBer != encoding)
return base.GetEncoding(encoding);
if (null == elements)
return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.OctetString, contents);
return new ConstructedILEncoding(Asn1Tags.Universal, Asn1Tags.OctetString,
Asn1OutputStream.GetContentsEncodings(encoding, elements));
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
if (Asn1OutputStream.EncodingBer != encoding)
return base.GetEncodingImplicit(encoding, tagClass, tagNo);
if (null == elements)
return new PrimitiveEncoding(tagClass, tagNo, contents);
return new ConstructedILEncoding(tagClass, tagNo,
Asn1OutputStream.GetContentsEncodings(encoding, elements));
}
private class ChunkEnumerator
: IEnumerator
{
private readonly byte[] octets;
private readonly int segmentLimit;
private DerOctetString currentSegment = null;
private int nextSegmentPos = 0;
internal ChunkEnumerator(byte[] octets, int segmentLimit)
{
this.octets = octets;
this.segmentLimit = segmentLimit;
}
public object Current
{
get
{
if (null == currentSegment)
throw new InvalidOperationException();
return currentSegment;
}
}
public bool MoveNext()
{
if (nextSegmentPos >= octets.Length)
{
this.currentSegment = null;
return false;
}
int length = System.Math.Min(octets.Length - nextSegmentPos, segmentLimit);
byte[] segment = new byte[length];
Array.Copy(octets, nextSegmentPos, segment, 0, length);
this.currentSegment = new DerOctetString(segment);
this.nextSegmentPos += length;
return true;
}
public void Reset()
{
this.currentSegment = null;
this.nextSegmentPos = 0;
}
}
}
}