diff options
author | David Hook <dgh@cryptoworkshop.com> | 2023-08-14 13:30:36 +1000 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2023-08-14 13:30:36 +1000 |
commit | f3dac948c7e6214663e58dc966bd10cb31689411 (patch) | |
tree | 60742057ef07d02d80162165b849a15a842503cb /crypto | |
parent | test vector updates to Kyber and Dilithium (diff) | |
parent | Microsoft.NET.Test.Sdk 17.7.0 (diff) | |
download | BouncyCastle.NET-ed25519-f3dac948c7e6214663e58dc966bd10cb31689411.tar.xz |
Merge remote-tracking branch 'refs/remotes/origin/master'
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/src/asn1/Asn1RelativeOid.cs | 21 | ||||
-rw-r--r-- | crypto/src/asn1/DerObjectIdentifier.cs | 20 | ||||
-rw-r--r-- | crypto/src/asn1/cmp/CmpObjectIdentifiers.cs | 68 | ||||
-rw-r--r-- | crypto/src/asn1/cmp/KemBMParameter.cs | 76 | ||||
-rw-r--r-- | crypto/src/asn1/cmp/KemCiphertextInfo.cs | 64 | ||||
-rw-r--r-- | crypto/src/asn1/cmp/KemOtherInfo.cs | 150 | ||||
-rw-r--r-- | crypto/src/asn1/x9/X9ECParametersHolder.cs | 39 | ||||
-rw-r--r-- | crypto/src/crypto/agreement/DHStandardGroups.cs | 4 | ||||
-rw-r--r-- | crypto/src/crypto/generators/DHParametersHelper.cs | 18 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/ECDomainParameters.cs | 16 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs | 25 | ||||
-rw-r--r-- | crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs | 25 | ||||
-rw-r--r-- | crypto/src/math/BigInteger.cs | 219 | ||||
-rw-r--r-- | crypto/src/math/ec/abc/Tnaf.cs | 4 | ||||
-rw-r--r-- | crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs | 6 | ||||
-rw-r--r-- | crypto/test/BouncyCastle.Crypto.Tests.csproj | 2 | ||||
-rw-r--r-- | crypto/test/src/pqc/crypto/test/HSSTest.cs | 40 |
17 files changed, 544 insertions, 253 deletions
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(); |