summary refs log tree commit diff
path: root/crypto/src/x509
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/x509')
-rw-r--r--crypto/src/x509/X509Utilities.cs59
-rw-r--r--crypto/src/x509/X509V1CertificateGenerator.cs18
-rw-r--r--crypto/src/x509/X509V3CertificateGenerator.cs57
3 files changed, 75 insertions, 59 deletions
diff --git a/crypto/src/x509/X509Utilities.cs b/crypto/src/x509/X509Utilities.cs
index bb9b7155f..3ab6b926c 100644
--- a/crypto/src/x509/X509Utilities.cs
+++ b/crypto/src/x509/X509Utilities.cs
@@ -14,7 +14,7 @@ using Org.BouncyCastle.Utilities.Collections;
 
 namespace Org.BouncyCastle.X509
 {
-	internal class X509Utilities
+    internal static class X509Utilities
 	{
         private static readonly Dictionary<string, DerObjectIdentifier> m_algorithms =
 			new Dictionary<string, DerObjectIdentifier>(StringComparer.OrdinalIgnoreCase);
@@ -126,7 +126,17 @@ namespace Org.BouncyCastle.X509
 			m_exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
 		}
 
-		private static RsassaPssParameters CreatePssParams(
+        internal static TResult CalculateResult<TResult>(IStreamCalculator<TResult> streamCalculator,
+            Asn1Encodable asn1Encodable)
+        {
+            using (var stream = streamCalculator.Stream)
+            {
+                asn1Encodable.EncodeTo(stream, Asn1Encodable.Der);
+            }
+            return streamCalculator.GetResult();
+        }
+
+        private static RsassaPssParameters CreatePssParams(
 			AlgorithmIdentifier	hashAlgId,
 			int					saltSize)
 		{
@@ -137,7 +147,23 @@ namespace Org.BouncyCastle.X509
 				new DerInteger(1));
 		}
 
-		internal static DerObjectIdentifier GetAlgorithmOid(string algorithmName)
+        internal static DerBitString CollectDerBitString(IBlockResult result)
+        {
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            var maxResultLength = result.GetMaxResultLength();
+            Span<byte> data = maxResultLength <= 512
+                ? stackalloc byte[maxResultLength]
+                : new byte[maxResultLength];
+            int resultLength = result.Collect(data);
+            data = data[..resultLength];
+#else
+            var data = result.Collect();
+#endif
+
+            return new DerBitString(data);
+        }
+
+        internal static DerObjectIdentifier GetAlgorithmOid(string algorithmName)
 		{
 			if (m_algorithms.TryGetValue(algorithmName, out var oid))
 				return oid;
@@ -161,16 +187,29 @@ namespace Org.BouncyCastle.X509
 			return CollectionUtilities.Proxy(m_algorithms.Keys);
 		}
 
+        internal static DerBitString GenerateBitString(IStreamCalculator<IBlockResult> streamCalculator,
+			Asn1Encodable asn1Encodable)
+        {
+            var result = CalculateResult(streamCalculator, asn1Encodable);
+            return CollectDerBitString(result);
+        }
+
+        internal static DerBitString GenerateMac(IMacFactory macFactory, Asn1Encodable asn1Encodable)
+        {
+			return GenerateBitString(macFactory.CreateCalculator(), asn1Encodable);
+        }
+
         internal static DerBitString GenerateSignature(ISignatureFactory signatureFactory, Asn1Encodable asn1Encodable)
         {
-			var result = CalculateResult(signatureFactory.CreateCalculator(), asn1Encodable);
-            return new DerBitString(result.Collect());
+            return GenerateBitString(signatureFactory.CreateCalculator(), asn1Encodable);
         }
 
         internal static bool VerifySignature(IVerifierFactory verifierFactory, Asn1Encodable asn1Encodable,
 			DerBitString signature)
         {
             var result = CalculateResult(verifierFactory.CreateCalculator(), asn1Encodable);
+
+			// TODO[api] Use GetOctetsSpan() once IsVerified(ReadOnlySpan<byte>) is available
 			return result.IsVerified(signature.GetOctets());
         }
 
@@ -190,15 +229,5 @@ namespace Org.BouncyCastle.X509
 
             return new DerTaggedObject(true, tagNo, new DerSequence(extV));
         }
-
-		private static TResult CalculateResult<TResult>(IStreamCalculator<TResult> streamCalculator,
-			Asn1Encodable asn1Encodable)
-		{
-            using (var stream = streamCalculator.Stream)
-            {
-                asn1Encodable.EncodeTo(stream, Asn1Encodable.Der);
-            }
-            return streamCalculator.GetResult();
-        }
     }
 }
diff --git a/crypto/src/x509/X509V1CertificateGenerator.cs b/crypto/src/x509/X509V1CertificateGenerator.cs
index 93ec03ea3..2fc53ec7c 100644
--- a/crypto/src/x509/X509V1CertificateGenerator.cs
+++ b/crypto/src/x509/X509V1CertificateGenerator.cs
@@ -122,26 +122,16 @@ namespace Org.BouncyCastle.X509
 
 			tbsGen.SetSignature(sigAlgID);
 
-			TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
+			var tbsCertificate = tbsGen.GenerateTbsCertificate();
 
-			IStreamCalculator<IBlockResult> streamCalculator = signatureFactory.CreateCalculator();
-			using (var sigStream = streamCalculator.Stream)
-			{
-				tbsCert.EncodeTo(sigStream, Asn1Encodable.Der);
-			}
-
-			var signature = streamCalculator.GetResult().Collect();
+            var signature = X509Utilities.GenerateSignature(signatureFactory, tbsCertificate);
 
-			return new X509Certificate(
-				new X509CertificateStructure(tbsCert, sigAlgID, new DerBitString(signature)));
+            return new X509Certificate(new X509CertificateStructure(tbsCertificate, sigAlgID, signature));
 		}
 
 		/// <summary>
 		/// Allows enumeration of the signature names supported by the generator.
 		/// </summary>
-		public IEnumerable<string> SignatureAlgNames
-		{
-			get { return X509Utilities.GetAlgNames(); }
-		}
+		public IEnumerable<string> SignatureAlgNames => X509Utilities.GetAlgNames();
 	}
 }
diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs
index 65e3c9177..1dd1776be 100644
--- a/crypto/src/x509/X509V3CertificateGenerator.cs
+++ b/crypto/src/x509/X509V3CertificateGenerator.cs
@@ -143,7 +143,7 @@ namespace Org.BouncyCastle.X509
 		public void SetSubjectUniqueID(
 			bool[] uniqueID)
 		{
-			tbsGen.SetSubjectUniqueID(booleanToBitString(uniqueID));
+			tbsGen.SetSubjectUniqueID(BooleanToBitString(uniqueID));
 		}
 
 		/// <summary>
@@ -153,30 +153,7 @@ namespace Org.BouncyCastle.X509
 		public void SetIssuerUniqueID(
 			bool[] uniqueID)
 		{
-			tbsGen.SetIssuerUniqueID(booleanToBitString(uniqueID));
-		}
-
-		private DerBitString booleanToBitString(
-			bool[] id)
-		{
-			byte[] bytes = new byte[(id.Length + 7) / 8];
-
-			for (int i = 0; i != id.Length; i++)
-			{
-				if (id[i])
-				{
-					bytes[i / 8] |= (byte)(1 << ((7 - (i % 8))));
-				}
-			}
-
-			int pad = id.Length % 8;
-
-			if (pad == 0)
-			{
-				return new DerBitString(bytes);
-			}
-
-			return new DerBitString(bytes, 8 - pad);
+			tbsGen.SetIssuerUniqueID(BooleanToBitString(uniqueID));
 		}
 
 		/// <summary>
@@ -327,9 +304,29 @@ namespace Org.BouncyCastle.X509
 		/// <summary>
 		/// Allows enumeration of the signature names supported by the generator.
 		/// </summary>
-		public IEnumerable<string> SignatureAlgNames
-		{
-			get { return X509Utilities.GetAlgNames(); }
-		}
-	}
+		public IEnumerable<string> SignatureAlgNames => X509Utilities.GetAlgNames();
+
+        private static DerBitString BooleanToBitString(bool[] id)
+        {
+            int byteLength = (id.Length + 7) / 8;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Span<byte> bytes = byteLength <= 512
+                ? stackalloc byte[byteLength]
+                : new byte[byteLength];
+#else
+			byte[] bytes = new byte[byteLength];
+#endif
+
+            for (int i = 0; i != id.Length; i++)
+            {
+                if (id[i])
+                {
+                    bytes[i >> 3] |= (byte)(0x80 >> (i & 7));
+                }
+            }
+
+            return new DerBitString(bytes, (8 - id.Length) & 7);
+        }
+    }
 }