123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- using System.Diagnostics;
- using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
- {
- public class BerBitString
- : DerBitString
- {
- private const int DefaultSegmentLimit = 1000;
- internal static byte[] FlattenBitStrings(DerBitString[] bitStrings)
- {
- int count = bitStrings.Length;
- switch (count)
- {
- case 0:
- // No bits
- return new byte[]{ 0 };
- case 1:
- return bitStrings[0].contents;
- default:
- {
- int last = count - 1, totalLength = 0;
- for (int i = 0; i < last; ++i)
- {
- byte[] elementContents = bitStrings[i].contents;
- if (elementContents[0] != 0)
- throw new ArgumentException("only the last nested bitstring can have padding", "bitStrings");
- totalLength += elementContents.Length - 1;
- }
- // Last one can have padding
- byte[] lastElementContents = bitStrings[last].contents;
- byte padBits = lastElementContents[0];
- totalLength += lastElementContents.Length;
- byte[] contents = new byte[totalLength];
- contents[0] = padBits;
- int pos = 1;
- for (int i = 0; i < count; ++i)
- {
- byte[] elementContents = bitStrings[i].contents;
- int length = elementContents.Length - 1;
- Array.Copy(elementContents, 1, contents, pos, length);
- pos += length;
- }
- Debug.Assert(pos == totalLength);
- return contents;
- }
- }
- }
- private readonly int segmentLimit;
- private readonly DerBitString[] elements;
- public BerBitString(byte data, int padBits)
- : base(data, padBits)
- {
- this.elements = null;
- this.segmentLimit = DefaultSegmentLimit;
- }
- public BerBitString(byte[] data)
- : this(data, 0)
- {
- }
- public BerBitString(byte[] data, int padBits)
- : this(data, padBits, DefaultSegmentLimit)
- {
- }
- public BerBitString(byte[] data, int padBits, int segmentLimit)
- : base(data, padBits)
- {
- this.elements = null;
- this.segmentLimit = segmentLimit;
- }
- public BerBitString(int namedBits)
- : base(namedBits)
- {
- this.elements = null;
- this.segmentLimit = DefaultSegmentLimit;
- }
- public BerBitString(Asn1Encodable obj)
- : this(obj.GetDerEncoded(), 0)
- {
- }
- public BerBitString(DerBitString[] elements)
- : this(elements, DefaultSegmentLimit)
- {
- }
- public BerBitString(DerBitString[] elements, int segmentLimit)
- : base(FlattenBitStrings(elements), false)
- {
- this.elements = elements;
- this.segmentLimit = segmentLimit;
- }
- internal BerBitString(byte[] contents, bool check)
- : base(contents, check)
- {
- this.elements = null;
- this.segmentLimit = DefaultSegmentLimit;
- }
- private bool IsConstructed
- {
- get { return null != elements || contents.Length > segmentLimit; }
- }
- internal override int EncodedLength(bool withID)
- {
- throw BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.CreateNotImplementedException("BerBitString.EncodedLength");
- // TODO This depends on knowing it's not DER
- //if (!IsConstructed)
- // return EncodedLength(withID, contents.Length);
- //int totalLength = withID ? 4 : 3;
- //if (null != elements)
- //{
- // for (int i = 0; i < elements.Length; ++i)
- // {
- // totalLength += elements[i].EncodedLength(true);
- // }
- //}
- //else if (contents.Length < 2)
- //{
- // // No bits
- //}
- //else
- //{
- // int extraSegments = (contents.Length - 2) / (segmentLimit - 1);
- // totalLength += extraSegments * EncodedLength(true, segmentLimit);
- // int lastSegmentLength = contents.Length - (extraSegments * (segmentLimit - 1));
- // totalLength += EncodedLength(true, lastSegmentLength);
- //}
- //return totalLength;
- }
- internal override void Encode(Asn1OutputStream asn1Out, bool withID)
- {
- if (!asn1Out.IsBer)
- {
- base.Encode(asn1Out, withID);
- return;
- }
- if (!IsConstructed)
- {
- Encode(asn1Out, withID, contents, 0, contents.Length);
- return;
- }
- asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.BitString);
- asn1Out.WriteByte(0x80);
- if (null != elements)
- {
- asn1Out.WritePrimitives(elements);
- }
- else if (contents.Length < 2)
- {
- // No bits
- }
- else
- {
- byte pad = contents[0];
- int length = contents.Length;
- int remaining = length - 1;
- int segmentLength = segmentLimit - 1;
- while (remaining > segmentLength)
- {
- Encode(asn1Out, true, (byte)0, contents, length - remaining, segmentLength);
- remaining -= segmentLength;
- }
- Encode(asn1Out, true, pad, contents, length - remaining, remaining);
- }
- asn1Out.WriteByte(0x00);
- asn1Out.WriteByte(0x00);
- }
- }
- }
- #pragma warning restore
- #endif
|