From 515f53364796324fc2b024e1ccab9b5adc4bcd7b Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Thu, 12 Jan 2023 18:15:17 +0700 Subject: Improvements to EdDSA use cases - see https://github.com/bcgit/bc-csharp/issues/406 --- crypto/src/security/SignerUtilities.cs | 121 ++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 33 deletions(-) (limited to 'crypto/src/security') diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index 6500cdf13..917759a8e 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -10,16 +10,16 @@ using Org.BouncyCastle.Asn1.GM; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Asn1.Rosstandart; using Org.BouncyCastle.Asn1.TeleTrust; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X9; -using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Signers; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Collections; -using Org.BouncyCastle.Asn1.Rosstandart; namespace Org.BouncyCastle.Security { @@ -28,9 +28,10 @@ namespace Org.BouncyCastle.Security /// public static class SignerUtilities { - internal static readonly IDictionary AlgorithmMap = + private static readonly IDictionary AlgorithmMap = new Dictionary(StringComparer.OrdinalIgnoreCase); - internal static readonly IDictionary Oids = + private static readonly HashSet NoRandom = new HashSet(StringComparer.OrdinalIgnoreCase); + private static readonly IDictionary Oids = new Dictionary(StringComparer.OrdinalIgnoreCase); static SignerUtilities() @@ -408,6 +409,14 @@ namespace Org.BouncyCastle.Security AlgorithmMap["SM3WITHSM2"] = "SM3withSM2"; AlgorithmMap[GMObjectIdentifiers.sm2sign_with_sm3.Id] = "SM3withSM2"; + NoRandom.Add("Ed25519"); + NoRandom.Add(EdECObjectIdentifiers.id_Ed25519.Id); + NoRandom.Add("Ed25519ctx"); + NoRandom.Add("Ed25519ph"); + NoRandom.Add("Ed448"); + NoRandom.Add(EdECObjectIdentifiers.id_Ed448.Id); + NoRandom.Add("Ed448ph"); + Oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption; Oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption; Oids["MD5withRSA"] = PkcsObjectIdentifiers.MD5WithRsaEncryption; @@ -519,6 +528,11 @@ namespace Org.BouncyCastle.Security return DerNull.Instance; } + private static string GetMechanism(string algorithm) + { + return AlgorithmMap.TryGetValue(algorithm, out var v) ? v : algorithm.ToUpperInvariant(); + } + private static Asn1Encodable GetPssX509Parameters( string digestName) { @@ -536,6 +550,9 @@ namespace Org.BouncyCastle.Security public static ISigner GetSigner(DerObjectIdentifier id) { + if (id == null) + throw new ArgumentNullException(nameof(id)); + return GetSigner(id.Id); } @@ -544,8 +561,17 @@ namespace Org.BouncyCastle.Security if (algorithm == null) throw new ArgumentNullException(nameof(algorithm)); - string mechanism = CollectionUtilities.GetValueOrKey(AlgorithmMap, algorithm.ToUpperInvariant()); + string mechanism = GetMechanism(algorithm); + + var signer = GetSignerForMechanism(mechanism); + if (signer == null) + throw new SecurityUtilityException("Signer " + algorithm + " not recognised."); + + return signer; + } + private static ISigner GetSignerForMechanism(string mechanism) + { if (Platform.StartsWith(mechanism, "Ed")) { if (mechanism.Equals("Ed25519")) @@ -638,30 +664,37 @@ namespace Org.BouncyCastle.Security { return new Gost3410DigestSigner(new Gost3410Signer(), new Gost3411Digest()); } - if (mechanism.Equals("ECGOST3410")) - { - return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411Digest()); - } - if (mechanism.Equals("ECGOST3410-2012-256")) - { - return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411_2012_256Digest()); - } - if (mechanism.Equals("ECGOST3410-2012-512")) - { - return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411_2012_512Digest()); - } - if (mechanism.Equals("SHA1WITHRSA/ISO9796-2")) - { - return new Iso9796d2Signer(new RsaBlindedEngine(), new Sha1Digest(), true); - } - if (mechanism.Equals("MD5WITHRSA/ISO9796-2")) + if (Platform.StartsWith(mechanism, "ECGOST3410")) { - return new Iso9796d2Signer(new RsaBlindedEngine(), new MD5Digest(), true); + if (mechanism.Equals("ECGOST3410")) + { + return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411Digest()); + } + if (mechanism.Equals("ECGOST3410-2012-256")) + { + return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411_2012_256Digest()); + } + if (mechanism.Equals("ECGOST3410-2012-512")) + { + return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411_2012_512Digest()); + } } - if (mechanism.Equals("RIPEMD160WITHRSA/ISO9796-2")) + + if (Platform.EndsWith(mechanism, "/ISO9796-2")) { - return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true); + if (mechanism.Equals("SHA1WITHRSA/ISO9796-2")) + { + return new Iso9796d2Signer(new RsaBlindedEngine(), new Sha1Digest(), true); + } + if (mechanism.Equals("MD5WITHRSA/ISO9796-2")) + { + return new Iso9796d2Signer(new RsaBlindedEngine(), new MD5Digest(), true); + } + if (mechanism.Equals("RIPEMD160WITHRSA/ISO9796-2")) + { + return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true); + } } if (Platform.EndsWith(mechanism, "/X9.31")) @@ -672,19 +705,20 @@ namespace Org.BouncyCastle.Security { int endPos = withPos + "WITH".Length; - string digestName = x931.Substring(0, withPos); - IDigest digest = DigestUtilities.GetDigest(digestName); - string cipherName = x931.Substring(endPos, x931.Length - endPos); if (cipherName.Equals("RSA")) { IAsymmetricBlockCipher cipher = new RsaBlindedEngine(); + + string digestName = x931.Substring(0, withPos); + IDigest digest = DigestUtilities.GetDigest(digestName); + return new X931Signer(cipher, digest); } } } - throw new SecurityUtilityException("Signer " + algorithm + " not recognised."); + return null; } public static string GetEncodingName(DerObjectIdentifier oid) @@ -692,15 +726,36 @@ namespace Org.BouncyCastle.Security return CollectionUtilities.GetValueOrNull(AlgorithmMap, oid.Id); } - public static ISigner InitSigner(DerObjectIdentifier algorithmOid, bool forSigning, AsymmetricKeyParameter privateKey, SecureRandom random) + // TODO Rename 'privateKey' to 'key' + public static ISigner InitSigner(DerObjectIdentifier algorithmOid, bool forSigning, + AsymmetricKeyParameter privateKey, SecureRandom random) { + if (algorithmOid == null) + throw new ArgumentNullException(nameof(algorithmOid)); + return InitSigner(algorithmOid.Id, forSigning, privateKey, random); } - public static ISigner InitSigner(string algorithm, bool forSigning, AsymmetricKeyParameter privateKey, SecureRandom random) + // TODO Rename 'privateKey' to 'key' + public static ISigner InitSigner(string algorithm, bool forSigning, AsymmetricKeyParameter privateKey, + SecureRandom random) { - ISigner signer = GetSigner(algorithm); - signer.Init(forSigning, ParameterUtilities.WithRandom(privateKey, random)); + if (algorithm == null) + throw new ArgumentNullException(nameof(algorithm)); + + string mechanism = GetMechanism(algorithm); + + var signer = GetSignerForMechanism(mechanism); + if (signer == null) + throw new SecurityUtilityException("Signer " + algorithm + " not recognised."); + + ICipherParameters cipherParameters = privateKey; + if (forSigning && !NoRandom.Contains(mechanism)) + { + cipherParameters = ParameterUtilities.WithRandom(cipherParameters, random); + } + + signer.Init(forSigning, cipherParameters); return signer; } } -- cgit 1.4.1