From fd0d2d40b55157c88c7304a8fcfb4c8e947aa01f Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 16 Feb 2021 21:01:31 +0700 Subject: Use cached encodings for Equals/GetHashCode --- crypto/src/x509/X509Crl.cs | 110 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 21 deletions(-) (limited to 'crypto/src/x509/X509Crl.cs') diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs index 7b841599f..5cf4bd53c 100644 --- a/crypto/src/x509/X509Crl.cs +++ b/crypto/src/x509/X509Crl.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.IO; using System.Text; using Org.BouncyCastle.Asn1; @@ -31,11 +32,42 @@ namespace Org.BouncyCastle.X509 : X509ExtensionBase // TODO Add interface Crl? { - private readonly CertificateList c; + private class CachedEncoding + { + private readonly byte[] encoding; + private readonly CrlException exception; + + internal CachedEncoding(byte[] encoding, CrlException exception) + { + this.encoding = encoding; + this.exception = exception; + } + + internal byte[] Encoding + { + get { return encoding; } + } + + internal byte[] GetEncoded() + { + if (null != exception) + throw exception; + + if (null == encoding) + throw new CrlException(); + + return encoding; + } + } + + private readonly CertificateList c; private readonly string sigAlgName; private readonly byte[] sigAlgParams; private readonly bool isIndirect; + private readonly object cacheLock = new object(); + private CachedEncoding cachedEncoding; + private volatile bool hashValueSet; private volatile int hashValue; @@ -66,18 +98,6 @@ namespace Org.BouncyCastle.X509 : null; } - public virtual byte[] GetEncoded() - { - try - { - return c.GetDerEncoded(); - } - catch (Exception e) - { - throw new CrlException(e.ToString()); - } - } - public virtual void Verify( AsymmetricKeyParameter publicKey) { @@ -226,7 +246,17 @@ namespace Org.BouncyCastle.X509 return Arrays.Clone(sigAlgParams); } - public override bool Equals(object other) + /// + /// Return the DER encoding of this CRL. + /// + /// A byte array containing the DER encoding of this CRL. + /// If there is an error encoding the CRL. + public virtual byte[] GetEncoded() + { + return Arrays.Clone(GetCachedEncoding().GetEncoded()); + } + + public override bool Equals(object other) { if (this == other) return true; @@ -240,22 +270,28 @@ namespace Org.BouncyCastle.X509 if (this.hashValue != that.hashValue) return false; } - else if (!this.c.Signature.Equals(that.c.Signature)) + else if (null == this.cachedEncoding || null == that.cachedEncoding) { - return false; + DerBitString signature = c.Signature; + if (null != signature && !signature.Equals(that.c.Signature)) + return false; } - return this.c.Equals(that.c); + byte[] thisEncoding = this.GetCachedEncoding().Encoding; + byte[] thatEncoding = that.GetCachedEncoding().Encoding; - // NB: May prefer this implementation of Equals if more than one CRL implementation in play - //return Arrays.AreEqual(this.GetEncoded(), that.GetEncoded()); + return null != thisEncoding + && null != thatEncoding + && Arrays.AreEqual(thisEncoding, thatEncoding); } public override int GetHashCode() { if (!hashValueSet) { - hashValue = this.c.GetHashCode(); + byte[] thisEncoding = this.GetCachedEncoding().Encoding; + + hashValue = Arrays.GetHashCode(thisEncoding); hashValueSet = true; } @@ -433,5 +469,37 @@ namespace Org.BouncyCastle.X509 return isIndirect; } } - } + + private CachedEncoding GetCachedEncoding() + { + lock (cacheLock) + { + if (null != cachedEncoding) + return cachedEncoding; + } + + byte[] encoding = null; + CrlException exception = null; + try + { + encoding = c.GetEncoded(Asn1Encodable.Der); + } + catch (IOException e) + { + exception = new CrlException("Failed to DER-encode CRL", e); + } + + CachedEncoding temp = new CachedEncoding(encoding, exception); + + lock (cacheLock) + { + if (null == cachedEncoding) + { + cachedEncoding = temp; + } + + return cachedEncoding; + } + } + } } -- cgit 1.4.1