diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-11-11 14:06:03 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-11-11 14:06:03 +0700 |
commit | 46230a012af2824a5e742db8e6dc5b23c720d696 (patch) | |
tree | 9cd842e680b7a9e3eac925f05bde504bb8670859 /crypto/src/asn1/DerSet.cs | |
parent | Handle high tag numbers (diff) | |
download | BouncyCastle.NET-ed25519-46230a012af2824a5e742db8e6dc5b23c720d696.tar.xz |
ASN.1: Update encoding in line with bc-java
Diffstat (limited to 'crypto/src/asn1/DerSet.cs')
-rw-r--r-- | crypto/src/asn1/DerSet.cs | 88 |
1 files changed, 60 insertions, 28 deletions
diff --git a/crypto/src/asn1/DerSet.cs b/crypto/src/asn1/DerSet.cs index 030b0a38f..d89285d9e 100644 --- a/crypto/src/asn1/DerSet.cs +++ b/crypto/src/asn1/DerSet.cs @@ -1,7 +1,4 @@ using System; -using System.IO; - -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1 { @@ -18,10 +15,12 @@ namespace Org.BouncyCastle.Asn1 return elementVector.Count < 1 ? Empty : new DerSet(elementVector); } - /** + private int m_contentsLengthDer = -1; + + /** * create an empty set */ - public DerSet() + public DerSet() : base() { } @@ -62,9 +61,20 @@ namespace Org.BouncyCastle.Asn1 { } - internal override int EncodedLength(bool withID) + internal override int EncodedLength(int encoding, bool withID) { - throw Platform.CreateNotImplementedException("DerSet.EncodedLength"); + encoding = Asn1OutputStream.EncodingDer; + + int count = elements.Length; + int contentsLength = 0; + + for (int i = 0; i < count; ++i) + { + Asn1Object asn1Object = elements[i].ToAsn1Object(); + contentsLength += asn1Object.EncodedLength(encoding, true); + } + + return Asn1OutputStream.GetLengthOfEncodingDL(withID, contentsLength); } /* @@ -83,34 +93,56 @@ namespace Org.BouncyCastle.Asn1 return; } + Asn1Encodable[] elements = this.elements; if (!isSorted) { - new DerSet(elements, true).ImplEncode(asn1Out, withID); - return; + elements = Sort((Asn1Encodable[])elements.Clone()); } - ImplEncode(asn1Out, withID); + asn1Out = asn1Out.GetDerSubStream(); + + asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Set); + + int count = elements.Length; + if (m_contentsLengthDer >= 0 || count > 16) + { + asn1Out.WriteDL(GetContentsLengthDer()); + + for (int i = 0; i < count; ++i) + { + Asn1Object asn1Object = elements[i].ToAsn1Object(); + asn1Object.Encode(asn1Out, true); + } + } + else + { + int contentsLength = 0; + + Asn1Object[] asn1Objects = new Asn1Object[count]; + for (int i = 0; i < count; ++i) + { + Asn1Object asn1Object = elements[i].ToAsn1Object(); + asn1Objects[i] = asn1Object; + contentsLength += asn1Object.EncodedLength(asn1Out.Encoding, true); + } + + this.m_contentsLengthDer = contentsLength; + asn1Out.WriteDL(contentsLength); + + for (int i = 0; i < count; ++i) + { + asn1Objects[i].Encode(asn1Out, true); + } + } } - private void ImplEncode(Asn1OutputStream asn1Out, bool withID) + private int GetContentsLengthDer() { - // TODO Intermediate buffer could be avoided if we could calculate expected length - MemoryStream bOut = new MemoryStream(); - Asn1OutputStream dOut = Asn1OutputStream.Create(bOut, Der); - dOut.WriteElements(elements); - dOut.FlushInternal(); - -#if PORTABLE - byte[] bytes = bOut.ToArray(); - int length = bytes.Length; -#else - byte[] bytes = bOut.GetBuffer(); - int length = (int)bOut.Position; -#endif - - asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, bytes, 0, length); - - Platform.Dispose(dOut); + if (m_contentsLengthDer < 0) + { + m_contentsLengthDer = CalculateContentsLength(Asn1OutputStream.EncodingDer); + } + return m_contentsLengthDer; } } } |