diff --git a/crypto/src/asn1/Asn1RelativeOid.cs b/crypto/src/asn1/Asn1RelativeOid.cs
index b7df4b75a..1d2ecb3df 100644
--- a/crypto/src/asn1/Asn1RelativeOid.cs
+++ b/crypto/src/asn1/Asn1RelativeOid.cs
@@ -137,8 +137,11 @@ namespace Org.BouncyCastle.Asn1
return new PrimitiveDerEncoding(tagClass, tagNo, GetContents());
}
- private void DoOutput(MemoryStream bOut)
+ private byte[] GetContents() => Objects.EnsureSingletonInitialized(ref contents, identifier, CreateContents);
+
+ private static byte[] CreateContents(string identifier)
{
+ MemoryStream bOut = new MemoryStream();
OidTokenizer tok = new OidTokenizer(identifier);
while (tok.HasMoreTokens)
{
@@ -152,21 +155,7 @@ namespace Org.BouncyCastle.Asn1
WriteField(bOut, new BigInteger(token));
}
}
- }
-
- private byte[] GetContents()
- {
- lock (this)
- {
- if (contents == null)
- {
- MemoryStream bOut = new MemoryStream();
- DoOutput(bOut);
- contents = bOut.ToArray();
- }
-
- return contents;
- }
+ return bOut.ToArray();
}
internal static Asn1RelativeOid CreatePrimitive(byte[] contents, bool clone)
diff --git a/crypto/src/asn1/DerObjectIdentifier.cs b/crypto/src/asn1/DerObjectIdentifier.cs
index 91e427d0b..12e8ea0a8 100644
--- a/crypto/src/asn1/DerObjectIdentifier.cs
+++ b/crypto/src/asn1/DerObjectIdentifier.cs
@@ -168,8 +168,11 @@ namespace Org.BouncyCastle.Asn1
return new PrimitiveDerEncoding(tagClass, tagNo, GetContents());
}
- private void DoOutput(MemoryStream bOut)
+ private byte[] GetContents() => Objects.EnsureSingletonInitialized(ref contents, identifier, CreateContents);
+
+ private static byte[] CreateContents(string identifier)
{
+ MemoryStream bOut = new MemoryStream();
OidTokenizer tok = new OidTokenizer(identifier);
string token = tok.NextToken();
@@ -197,21 +200,8 @@ namespace Org.BouncyCastle.Asn1
Asn1RelativeOid.WriteField(bOut, new BigInteger(token));
}
}
- }
-
- private byte[] GetContents()
- {
- lock (this)
- {
- if (contents == null)
- {
- MemoryStream bOut = new MemoryStream();
- DoOutput(bOut);
- contents = bOut.ToArray();
- }
- return contents;
- }
+ return bOut.ToArray();
}
internal static DerObjectIdentifier CreatePrimitive(byte[] contents, bool clone)
diff --git a/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs b/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
index 1b3227c47..63fb29cf4 100644
--- a/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
+++ b/crypto/src/asn1/cmp/CmpObjectIdentifiers.cs
@@ -58,108 +58,110 @@ namespace Org.BouncyCastle.Asn1.Cmp
// and
// id-it OBJECT IDENTIFIER ::= {id-pkix 4}
- /** RFC 4120: it-id: PKIX.4 = 1.3.6.1.5.5.7.4 */
-
+ /** RFC 4120: id-it: PKIX.4 = 1.3.6.1.5.5.7.4 */
+ public static readonly DerObjectIdentifier id_it = new DerObjectIdentifier("1.3.6.1.5.5.7.4");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.1
*/
- public static readonly DerObjectIdentifier it_caProtEncCert = new DerObjectIdentifier("1.3.6.1.5.5.7.4.1");
+ public static readonly DerObjectIdentifier it_caProtEncCert = id_it.Branch("1");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.2
*/
- public static readonly DerObjectIdentifier it_signKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.2");
+ public static readonly DerObjectIdentifier it_signKeyPairTypes = id_it.Branch("2");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.3
*/
- public static readonly DerObjectIdentifier it_encKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.3");
+ public static readonly DerObjectIdentifier it_encKeyPairTypes = id_it.Branch("3");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.4
*/
- public static readonly DerObjectIdentifier it_preferredSymAlg = new DerObjectIdentifier("1.3.6.1.5.5.7.4.4");
+ public static readonly DerObjectIdentifier it_preferredSymAlg = id_it.Branch("4");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.5
*/
- public static readonly DerObjectIdentifier it_caKeyUpdateInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.4.5");
+ public static readonly DerObjectIdentifier it_caKeyUpdateInfo = id_it.Branch("5");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.6
*/
- public static readonly DerObjectIdentifier it_currentCRL = new DerObjectIdentifier("1.3.6.1.5.5.7.4.6");
+ public static readonly DerObjectIdentifier it_currentCRL = id_it.Branch("6");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.7
*/
- public static readonly DerObjectIdentifier it_unsupportedOIDs = new DerObjectIdentifier("1.3.6.1.5.5.7.4.7");
+ public static readonly DerObjectIdentifier it_unsupportedOIDs = id_it.Branch("7");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.10
*/
- public static readonly DerObjectIdentifier it_keyPairParamReq = new DerObjectIdentifier("1.3.6.1.5.5.7.4.10");
+ public static readonly DerObjectIdentifier it_keyPairParamReq = id_it.Branch("10");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.11
*/
- public static readonly DerObjectIdentifier it_keyPairParamRep = new DerObjectIdentifier("1.3.6.1.5.5.7.4.11");
+ public static readonly DerObjectIdentifier it_keyPairParamRep = id_it.Branch("11");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.12
*/
- public static readonly DerObjectIdentifier it_revPassphrase = new DerObjectIdentifier("1.3.6.1.5.5.7.4.12");
+ public static readonly DerObjectIdentifier it_revPassphrase = id_it.Branch("12");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.13
*/
- public static readonly DerObjectIdentifier it_implicitConfirm = new DerObjectIdentifier("1.3.6.1.5.5.7.4.13");
+ public static readonly DerObjectIdentifier it_implicitConfirm = id_it.Branch("13");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.14
*/
- public static readonly DerObjectIdentifier it_confirmWaitTime = new DerObjectIdentifier("1.3.6.1.5.5.7.4.14");
+ public static readonly DerObjectIdentifier it_confirmWaitTime = id_it.Branch("14");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.15
*/
- public static readonly DerObjectIdentifier it_origPKIMessage = new DerObjectIdentifier("1.3.6.1.5.5.7.4.15");
+ public static readonly DerObjectIdentifier it_origPKIMessage = id_it.Branch("15");
/**
* RFC 4120: 1.3.6.1.5.5.7.4.16
*/
- public static readonly DerObjectIdentifier it_suppLangTags = new DerObjectIdentifier("1.3.6.1.5.5.7.4.16");
+ public static readonly DerObjectIdentifier it_suppLangTags = id_it.Branch("16");
/**
* Update 16, RFC 4210
* {id-it 17}
*/
- public static readonly DerObjectIdentifier id_it_caCerts = new DerObjectIdentifier("1.3.6.1.5.5.7.4.17");
+ public static readonly DerObjectIdentifier id_it_caCerts = id_it.Branch("17");
/**
* Update 16, RFC 4210
* GenRep: {id-it 18}, RootCaKeyUpdateContent
*/
- public static readonly DerObjectIdentifier id_it_rootCaKeyUpdate = new DerObjectIdentifier("1.3.6.1.5.5.7.4.18");
+ public static readonly DerObjectIdentifier id_it_rootCaKeyUpdate = id_it.Branch("18");
/**
* Update 16, RFC 4210
* {id-it 19}
*/
- public static readonly DerObjectIdentifier id_it_certReqTemplate = new DerObjectIdentifier("1.3.6.1.5.5.7.4.19");
+ public static readonly DerObjectIdentifier id_it_certReqTemplate = id_it.Branch("19");
/**
* Update 16, RFC 4210
* GenMsg: {id-it 20}, RootCaCertValue
*/
- public static readonly DerObjectIdentifier id_it_rootCaCert = new DerObjectIdentifier("1.3.6.1.5.5.7.4.20");
+ public static readonly DerObjectIdentifier id_it_rootCaCert = id_it.Branch("20");
/**
* Update-16 to RFC 4210
* id-it-certProfile OBJECT IDENTIFIER ::= {id-it 21}
*/
- public static readonly DerObjectIdentifier id_it_certProfile = new DerObjectIdentifier("1.3.6.1.5.5.7.4.21");
-
- public static readonly DerObjectIdentifier id_it_crlStatusList = new DerObjectIdentifier("1.3.6.1.5.5.7.4.22");
+ public static readonly DerObjectIdentifier id_it_certProfile = id_it.Branch("21");
- public static readonly DerObjectIdentifier id_it_crls = new DerObjectIdentifier("1.3.6.1.5.5.7.4.23");
+ public static readonly DerObjectIdentifier id_it_crlStatusList = id_it.Branch("22");
- // Not yet formally defined.
-
- //public static readonly DerObjectIdentifier id_it_crlStatusList = null;
- //public static readonly DerObjectIdentifier id_it_crls = null;
+ public static readonly DerObjectIdentifier id_it_crls = id_it.Branch("23");
+ // TODO Update once OID allocated.
+#if false
+ /**
+ * id-it-KemCiphertextInfo OBJECT IDENTIFIER ::= { id-it TBD1 }
+ */
+ public static readonly DerObjectIdentifier id_it_KemCiphertextInfo = id_it.Branch("TBD1");
+#endif
// RFC 4211
@@ -254,5 +256,13 @@ namespace Org.BouncyCastle.Asn1.Cmp
* mechanisms(5) pkix(7) pkip(5) regCtrl(1) 12 }
*/
public static readonly DerObjectIdentifier id_regCtrl_rsaKeyLen = id_pkip.Branch("1.12");
- }
+
+ // TODO Update once OID allocated.
+#if false
+ /**
+ * id-KemBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 TBD4}
+ */
+ public static readonly DerObjectIdentifier id_KemBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.TBD4");
+#endif
+ }
}
diff --git a/crypto/src/asn1/cmp/KemBMParameter.cs b/crypto/src/asn1/cmp/KemBMParameter.cs
new file mode 100644
index 000000000..846233054
--- /dev/null
+++ b/crypto/src/asn1/cmp/KemBMParameter.cs
@@ -0,0 +1,76 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /**
+ * <pre>
+ * KemBMParameter ::= SEQUENCE {
+ * kdf AlgorithmIdentifier{KEY-DERIVATION, {...}},
+ * len INTEGER (1..MAX),
+ * mac AlgorithmIdentifier{MAC-ALGORITHM, {...}}
+ * }
+ * </pre>
+ */
+ public class KemBMParameter
+ : Asn1Encodable
+ {
+ public static KemBMParameter GetInstance(object obj)
+ {
+ if (obj == null)
+ return null;
+ if (obj is KemBMParameter kemBMParameter)
+ return kemBMParameter;
+ return new KemBMParameter(Asn1Sequence.GetInstance(obj));
+ }
+
+ public static KemBMParameter GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+ new KemBMParameter(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+ private readonly AlgorithmIdentifier m_kdf;
+ private readonly DerInteger m_len;
+ private readonly AlgorithmIdentifier m_mac;
+
+ private KemBMParameter(Asn1Sequence seq)
+ {
+ if (seq.Count != 3)
+ throw new ArgumentException("sequence size should 3", nameof(seq));
+
+ m_kdf = AlgorithmIdentifier.GetInstance(seq[0]);
+ m_len = DerInteger.GetInstance(seq[1]);
+ m_mac = AlgorithmIdentifier.GetInstance(seq[2]);
+ }
+
+ public KemBMParameter(AlgorithmIdentifier kdf, DerInteger len, AlgorithmIdentifier mac)
+ {
+ m_kdf = kdf;
+ m_len = len;
+ m_mac = mac;
+ }
+
+ public KemBMParameter(AlgorithmIdentifier kdf, long len, AlgorithmIdentifier mac)
+ : this(kdf, new DerInteger(len), mac)
+ {
+ }
+
+ public virtual AlgorithmIdentifier Kdf => m_kdf;
+
+ public virtual DerInteger Len => m_len;
+
+ public virtual AlgorithmIdentifier Mac => m_mac;
+
+ /**
+ * <pre>
+ * KemBMParameter ::= SEQUENCE {
+ * kdf AlgorithmIdentifier{KEY-DERIVATION, {...}},
+ * len INTEGER (1..MAX),
+ * mac AlgorithmIdentifier{MAC-ALGORITHM, {...}}
+ * }
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object() => new DerSequence(m_kdf, m_len, m_mac);
+ }
+}
diff --git a/crypto/src/asn1/cmp/KemCiphertextInfo.cs b/crypto/src/asn1/cmp/KemCiphertextInfo.cs
new file mode 100644
index 000000000..7a6c3b25e
--- /dev/null
+++ b/crypto/src/asn1/cmp/KemCiphertextInfo.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /**
+ * <pre>
+ * KemCiphertextInfo ::= SEQUENCE {
+ * kem AlgorithmIdentifier{KEM-ALGORITHM, {...}},
+ * ct OCTET STRING
+ * }
+ * </pre>
+ */
+ public class KemCiphertextInfo
+ : Asn1Encodable
+ {
+ public static KemCiphertextInfo GetInstance(object obj)
+ {
+ if (obj == null)
+ return null;
+ if (obj is KemCiphertextInfo kemCiphertextInfo)
+ return kemCiphertextInfo;
+ return new KemCiphertextInfo(Asn1Sequence.GetInstance(obj));
+ }
+
+ public static KemCiphertextInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+ new KemCiphertextInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+ private readonly AlgorithmIdentifier m_kem;
+ private readonly Asn1OctetString m_ct;
+
+ private KemCiphertextInfo(Asn1Sequence seq)
+ {
+ if (seq.Count != 2)
+ throw new ArgumentException("sequence size should 2", nameof(seq));
+
+ m_kem = AlgorithmIdentifier.GetInstance(seq[0]);
+ m_ct = Asn1OctetString.GetInstance(seq[1]);
+ }
+
+ public KemCiphertextInfo(AlgorithmIdentifier kem, Asn1OctetString ct)
+ {
+ m_kem = kem;
+ m_ct = ct;
+ }
+
+ public virtual AlgorithmIdentifier Kem => m_kem;
+
+ public virtual Asn1OctetString Ct => m_ct;
+
+ /**
+ * <pre>
+ * KemCiphertextInfo ::= SEQUENCE {
+ * kem AlgorithmIdentifier{KEM-ALGORITHM, {...}},
+ * ct OCTET STRING
+ * }
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object() => new DerSequence(m_kem, m_ct);
+ }
+}
diff --git a/crypto/src/asn1/cmp/KemOtherInfo.cs b/crypto/src/asn1/cmp/KemOtherInfo.cs
new file mode 100644
index 000000000..3185495fc
--- /dev/null
+++ b/crypto/src/asn1/cmp/KemOtherInfo.cs
@@ -0,0 +1,150 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+ /*
+ * <pre>
+ * KemOtherInfo ::= SEQUENCE {
+ * staticString PKIFreeText, -- MUST be "CMP-KEM"
+ * transactionID [0] OCTET STRING OPTIONAL,
+ * senderNonce [1] OCTET STRING OPTIONAL,
+ * recipNonce [2] OCTET STRING OPTIONAL,
+ * len INTEGER (1..MAX),
+ * mac AlgorithmIdentifier{MAC-ALGORITHM, {...}}
+ * ct OCTET STRING
+ * }
+ * </pre>
+ */
+ public class KemOtherInfo
+ : Asn1Encodable
+ {
+ public static KemOtherInfo GetInstance(object obj)
+ {
+ if (obj == null)
+ return null;
+ if (obj is KemOtherInfo kemOtherInfo)
+ return kemOtherInfo;
+ return new KemOtherInfo(Asn1Sequence.GetInstance(obj));
+ }
+
+ public static KemOtherInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) =>
+ new KemOtherInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+
+ private static readonly PkiFreeText DEFAULT_staticString = new PkiFreeText("CMP-KEM");
+
+ private readonly PkiFreeText m_staticString;
+ private readonly Asn1OctetString m_transactionID;
+ private readonly Asn1OctetString m_senderNonce;
+ private readonly Asn1OctetString m_recipNonce;
+ private readonly DerInteger m_len;
+ private readonly AlgorithmIdentifier m_mac;
+ private readonly Asn1OctetString m_ct;
+
+ public KemOtherInfo(Asn1OctetString transactionID, Asn1OctetString senderNonce, Asn1OctetString recipNonce,
+ DerInteger len, AlgorithmIdentifier mac, Asn1OctetString ct)
+ {
+ m_staticString = DEFAULT_staticString;
+ m_transactionID = transactionID;
+ m_senderNonce = senderNonce;
+ m_recipNonce = recipNonce;
+ m_len = len;
+ m_mac = mac;
+ m_ct = ct;
+ }
+
+ public KemOtherInfo(Asn1OctetString transactionID, Asn1OctetString senderNonce, Asn1OctetString recipNonce,
+ long len, AlgorithmIdentifier mac, Asn1OctetString ct)
+ : this(transactionID, senderNonce, recipNonce, new DerInteger(len), mac, ct)
+ {
+ }
+
+ private KemOtherInfo(Asn1Sequence seq)
+ {
+ if (seq.Count < 4 || seq.Count > 7)
+ throw new ArgumentException("sequence size should be between 4 and 7 inclusive", nameof(seq));
+
+ int seqPos = 0;
+
+ m_staticString = PkiFreeText.GetInstance(seq[seqPos]);
+ if (!DEFAULT_staticString.Equals(m_staticString))
+ throw new ArgumentException("staticString field should be " + DEFAULT_staticString);
+
+ Asn1TaggedObject tagged = seq[++seqPos] as Asn1TaggedObject;
+
+ if (tagged != null &&
+ Asn1Utilities.TryGetContextBaseUniversal(tagged, 0, true, Asn1Tags.OctetString, out var transactionID))
+ {
+ m_transactionID = (Asn1OctetString)transactionID;
+ tagged = seq[++seqPos] as Asn1TaggedObject;
+ }
+
+ if (tagged != null &&
+ Asn1Utilities.TryGetContextBaseUniversal(tagged, 1, true, Asn1Tags.OctetString, out var senderNonce))
+ {
+ m_senderNonce = (Asn1OctetString)senderNonce;
+ tagged = seq[++seqPos] as Asn1TaggedObject;
+ }
+
+ if (tagged != null &&
+ Asn1Utilities.TryGetContextBaseUniversal(tagged, 2, true, Asn1Tags.OctetString, out var recipNonce))
+ {
+ m_recipNonce = (Asn1OctetString)recipNonce;
+ tagged = seq[++seqPos] as Asn1TaggedObject;
+ }
+
+ if (tagged != null)
+ throw new ArgumentException("unknown tag: " + Asn1Utilities.GetTagText(tagged));
+
+ m_len = DerInteger.GetInstance(seq[seqPos]);
+ m_mac = AlgorithmIdentifier.GetInstance(seq[++seqPos]);
+ m_ct = Asn1OctetString.GetInstance(seq[++seqPos]);
+
+ if (++seqPos != seq.Count)
+ throw new ArgumentException("unexpected data at end of sequence", nameof(seq));
+ }
+
+ public virtual Asn1OctetString TransactionID => m_transactionID;
+
+ public virtual Asn1OctetString SenderNonce => m_senderNonce;
+
+ public virtual Asn1OctetString RecipNonce => m_recipNonce;
+
+ public virtual DerInteger Len => m_len;
+
+ public virtual AlgorithmIdentifier Mac => m_mac;
+
+ public virtual Asn1OctetString Ct => m_ct;
+
+ /**
+ * <pre>
+ * KemOtherInfo ::= SEQUENCE {
+ * staticString PKIFreeText, -- MUST be "CMP-KEM"
+ * transactionID [0] OCTET STRING OPTIONAL,
+ * senderNonce [1] OCTET STRING OPTIONAL,
+ * recipNonce [2] OCTET STRING OPTIONAL,
+ * len INTEGER (1..MAX),
+ * mac AlgorithmIdentifier{MAC-ALGORITHM, {...}}
+ * ct OCTET STRING
+ * }
+ * </pre>
+ *
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector(7);
+
+ v.Add(m_staticString);
+ v.AddOptionalTagged(true, 0, m_transactionID);
+ v.AddOptionalTagged(true, 1, m_senderNonce);
+ v.AddOptionalTagged(true, 2, m_recipNonce);
+ v.Add(m_len);
+ v.Add(m_mac);
+ v.Add(m_ct);
+
+ return new DerSequence(v);
+ }
+ }
+}
diff --git a/crypto/src/asn1/x9/X9ECParametersHolder.cs b/crypto/src/asn1/x9/X9ECParametersHolder.cs
index ea72cc6ac..535dad9f7 100644
--- a/crypto/src/asn1/x9/X9ECParametersHolder.cs
+++ b/crypto/src/asn1/x9/X9ECParametersHolder.cs
@@ -1,4 +1,5 @@
using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Asn1.X9
{
@@ -7,42 +8,12 @@ namespace Org.BouncyCastle.Asn1.X9
private ECCurve m_curve;
private X9ECParameters m_parameters;
- public ECCurve Curve
- {
- get
- {
- lock (this)
- {
- if (m_curve == null)
- {
- m_curve = CreateCurve();
- }
+ public ECCurve Curve => Objects.EnsureSingletonInitialized(ref m_curve, this, self => self.CreateCurve());
- return m_curve;
- }
- }
- }
+ public X9ECParameters Parameters =>
+ Objects.EnsureSingletonInitialized(ref m_parameters, this, self => self.CreateParameters());
- public X9ECParameters Parameters
- {
- get
- {
- lock (this)
- {
- if (m_parameters == null)
- {
- m_parameters = CreateParameters();
- }
-
- return m_parameters;
- }
- }
- }
-
- protected virtual ECCurve CreateCurve()
- {
- return CreateParameters().Curve;
- }
+ protected virtual ECCurve CreateCurve() => Parameters.Curve;
protected abstract X9ECParameters CreateParameters();
}
diff --git a/crypto/src/crypto/agreement/DHStandardGroups.cs b/crypto/src/crypto/agreement/DHStandardGroups.cs
index e334489c8..08afb801c 100644
--- a/crypto/src/crypto/agreement/DHStandardGroups.cs
+++ b/crypto/src/crypto/agreement/DHStandardGroups.cs
@@ -9,8 +9,6 @@ namespace Org.BouncyCastle.Crypto.Agreement
/// <summary>Standard Diffie-Hellman groups from various IETF specifications.</summary>
public class DHStandardGroups
{
- private static readonly BigInteger Two = BigInteger.ValueOf(2);
-
private static BigInteger FromHex(string hex)
{
return new BigInteger(1, Hex.DecodeStrict(hex));
@@ -30,7 +28,7 @@ namespace Org.BouncyCastle.Crypto.Agreement
{
// NOTE: A group using a safe prime (i.e. q = (p-1)/2), and generator g = 2
BigInteger p = FromHex(hexP);
- return new DHParameters(p, Two, p.ShiftRight(1), l);
+ return new DHParameters(p, BigInteger.Two, p.ShiftRight(1), l);
}
/*
diff --git a/crypto/src/crypto/generators/DHParametersHelper.cs b/crypto/src/crypto/generators/DHParametersHelper.cs
index 385690430..a05918944 100644
--- a/crypto/src/crypto/generators/DHParametersHelper.cs
+++ b/crypto/src/crypto/generators/DHParametersHelper.cs
@@ -9,21 +9,9 @@ namespace Org.BouncyCastle.Crypto.Generators
{
internal class DHParametersHelper
{
- private static readonly BigInteger Six = BigInteger.ValueOf(6);
-
private static readonly int[][] primeLists = BigInteger.primeLists;
private static readonly int[] primeProducts = BigInteger.primeProducts;
- private static readonly BigInteger[] BigPrimeProducts = ConstructBigPrimeProducts(primeProducts);
-
- private static BigInteger[] ConstructBigPrimeProducts(int[] primeProducts)
- {
- BigInteger[] bpp = new BigInteger[primeProducts.Length];
- for (int i = 0; i < bpp.Length; ++i)
- {
- bpp[i] = BigInteger.ValueOf(primeProducts[i]);
- }
- return bpp;
- }
+ private static readonly BigInteger[] BigPrimeProducts = Array.ConvertAll(primeProducts, BigInteger.ValueOf);
/*
* Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
@@ -83,7 +71,7 @@ namespace Org.BouncyCastle.Crypto.Generators
int qRem = test % prime;
if (qRem == 0 || qRem == (prime >> 1))
{
- q = q.Add(Six);
+ q = q.Add(BigInteger.Six);
goto retry;
}
}
@@ -146,7 +134,7 @@ namespace Org.BouncyCastle.Crypto.Generators
{
BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
- g = h.ModPow(BigInteger.Two, p);
+ g = h.Square().Mod(p);
}
while (g.Equals(BigInteger.One));
diff --git a/crypto/src/crypto/parameters/ECDomainParameters.cs b/crypto/src/crypto/parameters/ECDomainParameters.cs
index b5ca183de..8bd58d018 100644
--- a/crypto/src/crypto/parameters/ECDomainParameters.cs
+++ b/crypto/src/crypto/parameters/ECDomainParameters.cs
@@ -81,20 +81,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
get { return h; }
}
- public BigInteger HInv
- {
- get
- {
- lock (this)
- {
- if (hInv == null)
- {
- hInv = BigIntegers.ModOddInverseVar(n, h);
- }
- return hInv;
- }
- }
- }
+ public BigInteger HInv =>
+ Objects.EnsureSingletonInitialized(ref hInv, this, self => BigIntegers.ModOddInverseVar(self.n, self.h));
public byte[] GetSeed()
{
diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
index 3a760afc1..4d2746065 100644
--- a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
@@ -76,22 +76,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
internal ReadOnlyMemory<byte> DataMemory => data;
#endif
- public Ed25519PublicKeyParameters GeneratePublicKey()
- {
- lock (data)
- {
- if (null == cachedPublicKey)
- {
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- cachedPublicKey = new Ed25519PublicKeyParameters(Ed25519.GeneratePublicKey(data));
-#else
- cachedPublicKey = new Ed25519PublicKeyParameters(Ed25519.GeneratePublicKey(data, 0));
-#endif
- }
-
- return cachedPublicKey;
- }
- }
+ public Ed25519PublicKeyParameters GeneratePublicKey() =>
+ Objects.EnsureSingletonInitialized(ref cachedPublicKey, data, CreatePublicKey);
public void Sign(Ed25519.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen,
byte[] sig, int sigOff)
@@ -140,6 +126,13 @@ namespace Org.BouncyCastle.Crypto.Parameters
}
}
+ private static Ed25519PublicKeyParameters CreatePublicKey(byte[] data) =>
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ new Ed25519PublicKeyParameters(Ed25519.GeneratePublicKey(data));
+#else
+ new Ed25519PublicKeyParameters(Ed25519.GeneratePublicKey(data, 0));
+#endif
+
private static byte[] Validate(byte[] buf)
{
if (buf.Length != KeySize)
diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
index 544dbf32d..664716ae9 100644
--- a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
@@ -76,22 +76,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
internal ReadOnlyMemory<byte> DataMemory => data;
#endif
- public Ed448PublicKeyParameters GeneratePublicKey()
- {
- lock (data)
- {
- if (null == cachedPublicKey)
- {
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- cachedPublicKey = new Ed448PublicKeyParameters(Ed448.GeneratePublicKey(data));
-#else
- cachedPublicKey = new Ed448PublicKeyParameters(Ed448.GeneratePublicKey(data, 0));
-#endif
- }
-
- return cachedPublicKey;
- }
- }
+ public Ed448PublicKeyParameters GeneratePublicKey() =>
+ Objects.EnsureSingletonInitialized(ref cachedPublicKey, data, CreatePublicKey);
public void Sign(Ed448.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen,
byte[] sig, int sigOff)
@@ -132,6 +118,13 @@ namespace Org.BouncyCastle.Crypto.Parameters
}
}
+ private static Ed448PublicKeyParameters CreatePublicKey(byte[] data) =>
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ new Ed448PublicKeyParameters(Ed448.GeneratePublicKey(data));
+#else
+ new Ed448PublicKeyParameters(Ed448.GeneratePublicKey(data, 0));
+#endif
+
private static byte[] Validate(byte[] buf)
{
if (buf.Length != KeySize)
diff --git a/crypto/src/math/BigInteger.cs b/crypto/src/math/BigInteger.cs
index 7da886c4f..42b5b5089 100644
--- a/crypto/src/math/BigInteger.cs
+++ b/crypto/src/math/BigInteger.cs
@@ -139,6 +139,8 @@ namespace Org.BouncyCastle.Math
public static readonly BigInteger Two;
public static readonly BigInteger Three;
public static readonly BigInteger Four;
+ public static readonly BigInteger Five;
+ public static readonly BigInteger Six;
public static readonly BigInteger Ten;
#if !NETCOREAPP3_0_OR_GREATER
@@ -181,27 +183,34 @@ namespace Org.BouncyCastle.Math
static BigInteger()
{
Zero = new BigInteger(0, ZeroMagnitude, false);
- Zero.nBits = 0; Zero.nBitLength = 0;
+ Zero.nBits = 0;
+ Zero.nBitLength = 0;
SMALL_CONSTANTS[0] = Zero;
for (uint i = 1; i < SMALL_CONSTANTS.Length; ++i)
{
- SMALL_CONSTANTS[i] = CreateUValueOf(i);
+ var sc = CreateUValueOf(i);
+ sc.nBits = Integers.PopCount(i);
+ sc.nBitLength = BitLen(i);
+
+ SMALL_CONSTANTS[i] = sc;
}
One = SMALL_CONSTANTS[1];
Two = SMALL_CONSTANTS[2];
Three = SMALL_CONSTANTS[3];
Four = SMALL_CONSTANTS[4];
+ Five = SMALL_CONSTANTS[5];
+ Six = SMALL_CONSTANTS[6];
Ten = SMALL_CONSTANTS[10];
- radix2 = ValueOf(2);
+ radix2 = Two;
radix2E = radix2.Pow(chunk2);
radix8 = ValueOf(8);
radix8E = radix8.Pow(chunk8);
- radix10 = ValueOf(10);
+ radix10 = Ten;
radix10E = radix10.Pow(chunk10);
radix16 = ValueOf(16);
@@ -1171,7 +1180,7 @@ namespace Org.BouncyCastle.Math
? 1
: sign == 0
? 0
- : sign * CompareNoLeadingZeroes(0, magnitude, 0, other.magnitude);
+ : sign * CompareNoLeadingZeros(0, magnitude, 0, other.magnitude);
}
/**
@@ -1190,10 +1199,10 @@ namespace Org.BouncyCastle.Math
yIndx++;
}
- return CompareNoLeadingZeroes(xIndx, x, yIndx, y);
+ return CompareNoLeadingZeros(xIndx, x, yIndx, y);
}
- private static int CompareNoLeadingZeroes(int xIndx, uint[] x, int yIndx, uint[] y)
+ private static int CompareNoLeadingZeros(int xIndx, uint[] x, int yIndx, uint[] y)
{
int diff = (x.Length - y.Length) - (xIndx - yIndx);
@@ -1234,7 +1243,7 @@ namespace Org.BouncyCastle.Math
Debug.Assert(yStart < y.Length);
- int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+ int xyCmp = CompareNoLeadingZeros(xStart, x, yStart, y);
uint[] count;
if (xyCmp > 0)
@@ -1271,7 +1280,7 @@ namespace Org.BouncyCastle.Math
for (;;)
{
if (cBitLength < xBitLength
- || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
+ || CompareNoLeadingZeros(xStart, x, cStart, c) >= 0)
{
Subtract(xStart, x, cStart, c);
AddMagnitudes(count, iCount);
@@ -1289,7 +1298,7 @@ namespace Org.BouncyCastle.Math
if (xBitLength < yBitLength)
return count;
- xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+ xyCmp = CompareNoLeadingZeros(xStart, x, yStart, y);
if (xyCmp <= 0)
break;
@@ -1623,6 +1632,8 @@ namespace Org.BouncyCastle.Math
BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n);
BigInteger minusMontRadix = n.Subtract(montRadix);
+ uint[] yAccum = new uint[n.magnitude.Length + 1];
+
do
{
BigInteger a;
@@ -1633,7 +1644,7 @@ namespace Org.BouncyCastle.Math
while (a.sign == 0 || a.CompareTo(n) >= 0
|| a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix));
- BigInteger y = ModPowMonty(a, r, n, false);
+ BigInteger y = ModPowMonty(yAccum, a, r, n, false);
if (!y.Equals(montRadix))
{
@@ -1643,7 +1654,7 @@ namespace Org.BouncyCastle.Math
if (++j == s)
return false;
- y = ModPowMonty(y, Two, n, false);
+ y = ModSquareMonty(yAccum, y, n);
if (y.Equals(montRadix))
return false;
@@ -1725,12 +1736,12 @@ namespace Org.BouncyCastle.Math
// for (;;)
// {
// // While F is even, do F=F/u, C=C*u, k=k+1.
-// int zeroes = F.GetLowestSetBit();
-// if (zeroes > 0)
+// int zeros = F.GetLowestSetBit();
+// if (zeros > 0)
// {
-// F = F.ShiftRight(zeroes);
-// C = C.ShiftLeft(zeroes);
-// k += zeroes;
+// F = F.ShiftRight(zeros);
+// C = C.ShiftLeft(zeros);
+// k += zeros;
// }
//
// // If F = 1, then return B,k.
@@ -1891,7 +1902,8 @@ namespace Org.BouncyCastle.Math
}
else
{
- result = ModPowMonty(result, e, m, true);
+ uint[] yAccum = new uint[m.magnitude.Length + 1];
+ result = ModPowMonty(yAccum, result, e, m, true);
}
}
@@ -1925,17 +1937,17 @@ namespace Org.BouncyCastle.Math
oddPowers[i] = ReduceBarrett(oddPowers[i - 1].Multiply(b2), m, mr, yu);
}
- int[] windowList = GetWindowList(e.magnitude, extraBits);
+ uint[] windowList = GetWindowList(e.magnitude, extraBits);
Debug.Assert(windowList.Length > 0);
- int window = windowList[0];
- int mult = window & 0xFF, lastZeroes = window >> 8;
+ uint window = windowList[0];
+ uint mult = window & 0xFFU, lastZeros = window >> 8;
BigInteger y;
if (mult == 1)
{
y = b2;
- --lastZeroes;
+ --lastZeros;
}
else
{
@@ -1943,11 +1955,11 @@ namespace Org.BouncyCastle.Math
}
int windowPos = 1;
- while ((window = windowList[windowPos++]) != -1)
+ while ((window = windowList[windowPos++]) != uint.MaxValue)
{
mult = window & 0xFF;
- int bits = lastZeroes + BitLen((byte)mult);
+ int bits = (int)lastZeros + BitLen((byte)mult);
for (int j = 0; j < bits; ++j)
{
y = ReduceBarrett(y.Square(), m, mr, yu);
@@ -1955,10 +1967,10 @@ namespace Org.BouncyCastle.Math
y = ReduceBarrett(y.Multiply(oddPowers[mult >> 1]), m, mr, yu);
- lastZeroes = window >> 8;
+ lastZeros = window >> 8;
}
- for (int i = 0; i < lastZeroes; ++i)
+ for (int i = 0; i < lastZeros; ++i)
{
y = ReduceBarrett(y.Square(), m, mr, yu);
}
@@ -1999,7 +2011,7 @@ namespace Org.BouncyCastle.Math
return x;
}
- private static BigInteger ModPowMonty(BigInteger b, BigInteger e, BigInteger m, bool convert)
+ private static BigInteger ModPowMonty(uint[] yAccum, BigInteger b, BigInteger e, BigInteger m, bool convert)
{
int n = m.magnitude.Length;
int powR = 32 * n;
@@ -2012,7 +2024,7 @@ namespace Org.BouncyCastle.Math
b = b.ShiftLeft(powR).Remainder(m);
}
- uint[] yAccum = new uint[n + 1];
+ Debug.Assert(yAccum.Length == n + 1);
uint[] zVal = b.magnitude;
Debug.Assert(zVal.Length <= n);
@@ -2050,17 +2062,17 @@ namespace Org.BouncyCastle.Math
MultiplyMonty(yAccum, oddPowers[i], zSquared, m.magnitude, mDash, smallMontyModulus);
}
- int[] windowList = GetWindowList(e.magnitude, extraBits);
+ uint[] windowList = GetWindowList(e.magnitude, extraBits);
Debug.Assert(windowList.Length > 1);
- int window = windowList[0];
- int mult = window & 0xFF, lastZeroes = window >> 8;
+ uint window = windowList[0];
+ uint mult = window & 0xFF, lastZeros = window >> 8;
uint[] yVal;
if (mult == 1)
{
yVal = zSquared;
- --lastZeroes;
+ --lastZeros;
}
else
{
@@ -2068,11 +2080,11 @@ namespace Org.BouncyCastle.Math
}
int windowPos = 1;
- while ((window = windowList[windowPos++]) != -1)
+ while ((window = windowList[windowPos++]) != uint.MaxValue)
{
mult = window & 0xFF;
- int bits = lastZeroes + BitLen((byte)mult);
+ int bits = (int)lastZeros + BitLen((byte)mult);
for (int j = 0; j < bits; ++j)
{
SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
@@ -2080,10 +2092,10 @@ namespace Org.BouncyCastle.Math
MultiplyMonty(yAccum, yVal, oddPowers[mult >> 1], m.magnitude, mDash, smallMontyModulus);
- lastZeroes = window >> 8;
+ lastZeros = window >> 8;
}
- for (int i = 0; i < lastZeroes; ++i)
+ for (int i = 0; i < lastZeros; ++i)
{
SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
}
@@ -2101,22 +2113,49 @@ namespace Org.BouncyCastle.Math
return new BigInteger(1, yVal, true);
}
- private static int[] GetWindowList(uint[] mag, int extraBits)
+ private static BigInteger ModSquareMonty(uint[] yAccum, BigInteger b, BigInteger m)
+ {
+ int n = m.magnitude.Length;
+ int powR = 32 * n;
+ bool smallMontyModulus = m.BitLength + 2 <= powR;
+ uint mDash = m.GetMQuote();
+
+ Debug.Assert(yAccum.Length == n + 1);
+
+ uint[] zVal = b.magnitude;
+ Debug.Assert(zVal.Length <= n);
+
+ uint[] yVal = new uint[n];
+ zVal.CopyTo(yVal, n - zVal.Length);
+
+ SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
+
+ if (smallMontyModulus && CompareTo(0, yVal, 0, m.magnitude) >= 0)
+ {
+ Subtract(0, yVal, 0, m.magnitude);
+ }
+
+ return new BigInteger(1, yVal, true);
+ }
+
+ private static uint[] GetWindowList(uint[] mag, int extraBits)
{
- int v = (int)mag[0];
- Debug.Assert(v != 0);
+ uint v = mag[0];
+ Debug.Assert(v != 0U);
- int leadingBits = BitLen((uint)v);
+ int leadingBits = BitLen(v);
+ int totalBits = ((mag.Length - 1) << 5) + leadingBits;
- int resultSize = (((mag.Length - 1) << 5) + leadingBits) / (1 + extraBits) + 2;
- int[] result = new int[resultSize];
+ int resultSize = (totalBits + extraBits) / (1 + extraBits) + 1;
+ uint[] result = new uint[resultSize];
int resultPos = 0;
int bitPos = 33 - leadingBits;
v <<= bitPos;
- int mult = 1, multLimit = 1 << extraBits;
- int zeroes = 0;
+ uint mult = 1U;
+ uint multLimit = 1U << extraBits;
+ uint zeros = 0U;
int i = 0;
for (;;)
@@ -2125,17 +2164,17 @@ namespace Org.BouncyCastle.Math
{
if (mult < multLimit)
{
- mult = (mult << 1) | (int)((uint)v >> 31);
+ mult = (mult << 1) | (v >> 31);
}
- else if (v < 0)
+ else if ((int)v < 0)
{
- result[resultPos++] = CreateWindowEntry(mult, zeroes);
- mult = 1;
- zeroes = 0;
+ result[resultPos++] = CreateWindowEntry(mult, zeros);
+ mult = 1U;
+ zeros = 0U;
}
else
{
- ++zeroes;
+ ++zeros;
}
v <<= 1;
@@ -2143,35 +2182,35 @@ namespace Org.BouncyCastle.Math
if (++i == mag.Length)
{
- result[resultPos++] = CreateWindowEntry(mult, zeroes);
+ result[resultPos++] = CreateWindowEntry(mult, zeros);
break;
}
- v = (int)mag[i];
+ v = mag[i];
bitPos = 0;
}
- result[resultPos] = -1;
+ result[resultPos] = uint.MaxValue; // Sentinel value
return result;
}
- private static int CreateWindowEntry(int mult, int zeroes)
+ private static uint CreateWindowEntry(uint mult, uint zeros)
{
Debug.Assert(mult > 0);
#if NETCOREAPP3_0_OR_GREATER
int tz = BitOperations.TrailingZeroCount(mult);
mult >>= tz;
- zeroes += tz;
+ zeros += (uint)tz;
#else
- while ((mult & 1) == 0)
+ while ((mult & 1U) == 0U)
{
mult >>= 1;
- ++zeroes;
+ ++zeros;
}
#endif
- return mult | (zeroes << 8);
+ return mult | (zeros << 8);
}
/**
@@ -2682,7 +2721,7 @@ namespace Org.BouncyCastle.Math
Debug.Assert(yStart < y.Length);
- int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+ int xyCmp = CompareNoLeadingZeros(xStart, x, yStart, y);
if (xyCmp > 0)
{
@@ -2709,7 +2748,7 @@ namespace Org.BouncyCastle.Math
for (;;)
{
if (cBitLength < xBitLength
- || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
+ || CompareNoLeadingZeros(xStart, x, cStart, c) >= 0)
{
Subtract(xStart, x, cStart, c);
@@ -2726,7 +2765,7 @@ namespace Org.BouncyCastle.Math
if (xBitLength < yBitLength)
return x;
- xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+ xyCmp = CompareNoLeadingZeros(xStart, x, yStart, y);
if (xyCmp <= 0)
break;
@@ -2799,7 +2838,7 @@ namespace Org.BouncyCastle.Math
}
}
- if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0)
+ if (CompareNoLeadingZeros(0, magnitude, 0, n.magnitude) < 0)
return this;
uint[] result;
@@ -3094,7 +3133,7 @@ namespace Org.BouncyCastle.Math
if (this.sign != n.sign)
return Add(n.Negate());
- int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
+ int compare = CompareNoLeadingZeros(0, magnitude, 0, n.magnitude);
if (compare == 0)
return Zero;
@@ -3607,47 +3646,55 @@ namespace Org.BouncyCastle.Math
sb.Append(s);
}
+ private static BigInteger CreateUValueOf(uint value)
+ {
+ if (value == 0)
+ return Zero;
+
+ return new BigInteger(1, new uint[]{ value }, false);
+ }
+
private static BigInteger CreateUValueOf(ulong value)
{
uint msw = (uint)(value >> 32);
uint lsw = (uint)value;
- if (msw != 0)
- return new BigInteger(1, new uint[]{ msw, lsw }, false);
-
- if (lsw != 0)
- {
- BigInteger n = new BigInteger(1, new uint[]{ lsw }, false);
- // Check for a power of two
- if ((lsw & -lsw) == lsw)
- {
- n.nBits = 1;
- }
- return n;
- }
+ if (msw == 0)
+ return CreateUValueOf(lsw);
- return Zero;
+ return new BigInteger(1, new uint[]{ msw, lsw }, false);
}
- private static BigInteger CreateValueOf(long value)
+ public static BigInteger ValueOf(int value)
{
- if (value < 0)
+ if (value >= 0)
{
- if (value == long.MinValue)
- return CreateValueOf(~value).Not();
+ if (value < SMALL_CONSTANTS.Length)
+ return SMALL_CONSTANTS[value];
- return CreateValueOf(-value).Negate();
+ return CreateUValueOf((uint)value);
}
- return CreateUValueOf((ulong)value);
+ if (value == int.MinValue)
+ return CreateUValueOf((uint)~value).Not();
+
+ return ValueOf(-value).Negate();
}
public static BigInteger ValueOf(long value)
{
- if (value >= 0 && value < SMALL_CONSTANTS.Length)
- return SMALL_CONSTANTS[value];
+ if (value >= 0L)
+ {
+ if (value < SMALL_CONSTANTS.Length)
+ return SMALL_CONSTANTS[value];
+
+ return CreateUValueOf((ulong)value);
+ }
+
+ if (value == long.MinValue)
+ return CreateUValueOf((ulong)~value).Not();
- return CreateValueOf(value);
+ return ValueOf(-value).Negate();
}
public int GetLowestSetBit()
diff --git a/crypto/src/math/ec/abc/Tnaf.cs b/crypto/src/math/ec/abc/Tnaf.cs
index 88a4eeb96..d8e9b6ae0 100644
--- a/crypto/src/math/ec/abc/Tnaf.cs
+++ b/crypto/src/math/ec/abc/Tnaf.cs
@@ -500,12 +500,12 @@ namespace Org.BouncyCastle.Math.EC.Abc
{
if (mu == 1)
{
- return BigInteger.ValueOf(6);
+ return BigInteger.Six;
}
else
{
// mu == -1
- return BigInteger.ValueOf(10);
+ return BigInteger.Ten;
}
}
else
diff --git a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs
index 85b781228..01bac93b8 100644
--- a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs
@@ -96,7 +96,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
}
LmsSignedPubKey[] signedPubKeys = signature.GetSignedPubKeys();
- LmsPublicKeyParameters key = signedPubKeys[signedPubKeys.Length - 1].GetPublicKey();
+ LmsPublicKeyParameters key = LmsPublicKey;
+ if (signedPubKeys.Length != 0)
+ {
+ key = signedPubKeys[signedPubKeys.Length - 1].GetPublicKey();
+ }
return key.GenerateOtsContext(signature.Signature).WithSignedPublicKeys(signedPubKeys);
}
diff --git a/crypto/test/BouncyCastle.Crypto.Tests.csproj b/crypto/test/BouncyCastle.Crypto.Tests.csproj
index 0264491a3..08fcae206 100644
--- a/crypto/test/BouncyCastle.Crypto.Tests.csproj
+++ b/crypto/test/BouncyCastle.Crypto.Tests.csproj
@@ -30,7 +30,7 @@
<EmbeddedResource Include="data\**\*.*" Exclude="**\README.txt" />
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.0" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
diff --git a/crypto/test/src/pqc/crypto/test/HSSTest.cs b/crypto/test/src/pqc/crypto/test/HSSTest.cs
index 29b5e1f5a..45cabb906 100644
--- a/crypto/test/src/pqc/crypto/test/HSSTest.cs
+++ b/crypto/test/src/pqc/crypto/test/HSSTest.cs
@@ -13,16 +13,46 @@ namespace Org.BouncyCastle.Pqc.Crypto.Tests
public class HSSTest
{
[Test]
+ public void TestOneLevelKeyGenAndSign()
+ {
+ byte[] msg = Strings.ToByteArray("Hello, world!");
+ IAsymmetricCipherKeyPairGenerator kpGen = new HssKeyPairGenerator();
+
+ var lmsParameters = new LmsParameters[]
+ {
+ new LmsParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4)
+ };
+ kpGen.Init(new HssKeyGenerationParameters(lmsParameters, new SecureRandom()));
+
+ AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+ HssSigner signer = new HssSigner();
+
+ signer.Init(true, kp.Private);
+
+ byte[] sig = signer.GenerateSignature(msg);
+
+ signer.Init(false, kp.Public);
+
+ Assert.True(signer.VerifySignature(msg, sig));
+
+ HssPublicKeyParameters hssPubKey = (HssPublicKeyParameters)kp.Public;
+
+ hssPubKey.GenerateLmsContext(sig);
+ }
+
+ [Test]
public void TestKeyGenAndSign()
{
byte[] msg = Strings.ToByteArray("Hello, world!");
IAsymmetricCipherKeyPairGenerator kpGen = new HssKeyPairGenerator();
- kpGen.Init(new HssKeyGenerationParameters(
- new LmsParameters[]{
- new LmsParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4),
- new LmsParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4)
- }, new SecureRandom()));
+ var lmsParameters = new LmsParameters[]
+ {
+ new LmsParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4),
+ new LmsParameters(LMSigParameters.lms_sha256_n32_h5, LMOtsParameters.sha256_n32_w4)
+ };
+ kpGen.Init(new HssKeyGenerationParameters(lmsParameters, new SecureRandom()));
AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
|