diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-10-15 17:10:01 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-10-15 17:10:01 +0700 |
commit | f84f98dcb1fff8ffdfa8a3b47708c6eb8f15c5cf (patch) | |
tree | 38160e84b7de77e8327fafddca26c1571c2d780d /crypto/src/asn1 | |
parent | Merge checks (diff) | |
download | BouncyCastle.NET-ed25519-f84f98dcb1fff8ffdfa8a3b47708c6eb8f15c5cf.tar.xz |
Use primitive encoding for short octet strings
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r-- | crypto/src/asn1/BerOctetString.cs | 135 | ||||
-rw-r--r-- | crypto/src/asn1/DerOctetString.cs | 7 |
2 files changed, 92 insertions, 50 deletions
diff --git a/crypto/src/asn1/BerOctetString.cs b/crypto/src/asn1/BerOctetString.cs index b092d8fb2..4855e31d1 100644 --- a/crypto/src/asn1/BerOctetString.cs +++ b/crypto/src/asn1/BerOctetString.cs @@ -9,7 +9,7 @@ namespace Org.BouncyCastle.Asn1 public class BerOctetString : DerOctetString, IEnumerable { - private static readonly int DefaultChunkSize = 1000; + private static readonly int DefaultSegmentLimit = 1000; public static BerOctetString FromSequence(Asn1Sequence seq) { @@ -17,7 +17,7 @@ namespace Org.BouncyCastle.Asn1 Asn1OctetString[] v = new Asn1OctetString[count]; for (int i = 0; i < count; ++i) { - v[i] = Asn1OctetString.GetInstance(seq[i]); + v[i] = GetInstance(seq[i]); } return new BerOctetString(v); } @@ -62,13 +62,13 @@ namespace Org.BouncyCastle.Asn1 Asn1OctetString[] v = new Asn1OctetString[count]; for (int i = 0; i < count; ++i) { - v[i] = Asn1OctetString.GetInstance(list[i]); + v[i] = GetInstance(list[i]); } return v; } - private readonly int chunkSize; - private readonly Asn1OctetString[] octs; + private readonly int segmentLimit; + private readonly Asn1OctetString[] elements; [Obsolete("Will be removed")] public BerOctetString(IEnumerable e) @@ -77,30 +77,30 @@ namespace Org.BouncyCastle.Asn1 } public BerOctetString(byte[] str) - : this(str, DefaultChunkSize) + : this(str, DefaultSegmentLimit) { } - public BerOctetString(Asn1OctetString[] octs) - : this(octs, DefaultChunkSize) + public BerOctetString(Asn1OctetString[] elements) + : this(elements, DefaultSegmentLimit) { } - public BerOctetString(byte[] str, int chunkSize) - : this(str, null, chunkSize) + public BerOctetString(byte[] str, int segmentLimit) + : this(str, null, segmentLimit) { } - public BerOctetString(Asn1OctetString[] octs, int chunkSize) - : this(FlattenOctetStrings(octs), octs, chunkSize) + public BerOctetString(Asn1OctetString[] elements, int segmentLimit) + : this(FlattenOctetStrings(elements), elements, segmentLimit) { } - private BerOctetString(byte[] str, Asn1OctetString[] octs, int chunkSize) - : base(str) + private BerOctetString(byte[] octets, Asn1OctetString[] elements, int segmentLimit) + : base(octets) { - this.octs = octs; - this.chunkSize = chunkSize; + this.elements = elements; + this.segmentLimit = segmentLimit; } /** @@ -108,10 +108,10 @@ namespace Org.BouncyCastle.Asn1 */ public IEnumerator GetEnumerator() { - if (octs == null) - return new ChunkEnumerator(str, chunkSize); + if (elements == null) + return new ChunkEnumerator(str, segmentLimit); - return octs.GetEnumerator(); + return elements.GetEnumerator(); } [Obsolete("Use GetEnumerator() instead")] @@ -120,82 +120,119 @@ namespace Org.BouncyCastle.Asn1 return GetEnumerator(); } + private bool IsConstructed + { + get { return null != elements || str.Length > segmentLimit; } + } + internal override int EncodedLength(bool withID) { throw Platform.CreateNotImplementedException("BerOctetString.EncodedLength"); + + // TODO This depends on knowing it's not DER + //if (!IsConstructed) + // return EncodedLength(withID, str.Length); + + //int totalLength = withID ? 4 : 3; + + //if (null != elements) + //{ + // for (int i = 0; i < elements.Length; ++i) + // { + // totalLength += elements[i].EncodedLength(true); + // } + //} + //else + //{ + // int fullSegments = str.Length / segmentLimit; + // totalLength += fullSegments * EncodedLength(true, segmentLimit); + + // int lastSegmentLength = str.Length - (fullSegments * segmentLimit); + // if (lastSegmentLength > 0) + // { + // totalLength += EncodedLength(true, lastSegmentLength); + // } + //} + + //return totalLength; } internal override void Encode(Asn1OutputStream asn1Out, bool withID) { - if (asn1Out.IsBer) + if (!asn1Out.IsBer || !IsConstructed) { - if (withID) - { - asn1Out.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString); - } + base.Encode(asn1Out, withID); + return; + } - asn1Out.WriteByte(0x80); + asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.OctetString); + asn1Out.WriteByte(0x80); - foreach (Asn1OctetString oct in this) - { - oct.Encode(asn1Out, true); - } - - asn1Out.WriteByte(0x00); - asn1Out.WriteByte(0x00); + if (null != elements) + { + asn1Out.WritePrimitives(elements); } else { - base.Encode(asn1Out, withID); + int pos = 0; + while (pos < str.Length) + { + int segmentLength = System.Math.Min(str.Length - pos, segmentLimit); + Encode(asn1Out, true, str, pos, segmentLength); + pos += segmentLength; + } } + + asn1Out.WriteByte(0x00); + asn1Out.WriteByte(0x00); } private class ChunkEnumerator : IEnumerator { private readonly byte[] octets; - private readonly int chunkSize; + private readonly int segmentLimit; - private DerOctetString currentChunk = null; - private int nextChunkPos = 0; + private DerOctetString currentSegment = null; + private int nextSegmentPos = 0; - internal ChunkEnumerator(byte[] octets, int chunkSize) + internal ChunkEnumerator(byte[] octets, int segmentLimit) { this.octets = octets; - this.chunkSize = chunkSize; + this.segmentLimit = segmentLimit; } public object Current { get { - if (null == currentChunk) + if (null == currentSegment) throw new InvalidOperationException(); - return currentChunk; + return currentSegment; } } public bool MoveNext() { - if (nextChunkPos >= octets.Length) + if (nextSegmentPos >= octets.Length) { - this.currentChunk = null; + this.currentSegment = null; return false; } - int length = System.Math.Min(octets.Length - nextChunkPos, chunkSize); - byte[] chunk = new byte[length]; - Array.Copy(octets, nextChunkPos, chunk, 0, length); - this.currentChunk = new DerOctetString(chunk); - this.nextChunkPos += length; + 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.currentChunk = null; - this.nextChunkPos = 0; + this.currentSegment = null; + this.nextSegmentPos = 0; } } } diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs index bdabb8221..bcd4e7333 100644 --- a/crypto/src/asn1/DerOctetString.cs +++ b/crypto/src/asn1/DerOctetString.cs @@ -36,5 +36,10 @@ namespace Org.BouncyCastle.Asn1 { asn1Out.WriteEncodingDL(withID, Asn1Tags.OctetString, buf, off, len); } - } + + internal static int EncodedLength(bool withID, int contentsLength) + { + return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); + } + } } |