diff --git a/crypto/src/security/DotNetUtilities.cs b/crypto/src/security/DotNetUtilities.cs
index 3a7c5f0cb..08853e45e 100644
--- a/crypto/src/security/DotNetUtilities.cs
+++ b/crypto/src/security/DotNetUtilities.cs
@@ -5,9 +5,12 @@ using System.Runtime.Versioning;
using System.Security.Cryptography;
using SystemX509 = System.Security.Cryptography.X509Certificates;
+using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Utilities;
@@ -50,23 +53,11 @@ namespace Org.BouncyCastle.Security
public static AsymmetricCipherKeyPair GetDsaKeyPair(DSAParameters dp)
{
- DsaValidationParameters validationParameters = (dp.Seed != null)
- ? new DsaValidationParameters(dp.Seed, dp.Counter)
- : null;
-
- DsaParameters parameters = new DsaParameters(
- new BigInteger(1, dp.P),
- new BigInteger(1, dp.Q),
- new BigInteger(1, dp.G),
- validationParameters);
-
- DsaPublicKeyParameters pubKey = new DsaPublicKeyParameters(
- new BigInteger(1, dp.Y),
- parameters);
+ DsaPublicKeyParameters pubKey = GetDsaPublicKey(dp);
DsaPrivateKeyParameters privKey = new DsaPrivateKeyParameters(
new BigInteger(1, dp.X),
- parameters);
+ pubKey.Parameters);
return new AsymmetricCipherKeyPair(pubKey, privKey);
}
@@ -93,6 +84,62 @@ namespace Org.BouncyCastle.Security
parameters);
}
+#if NETCOREAPP1_0_OR_GREATER || NET47_OR_GREATER || NETSTANDARD1_6_OR_GREATER
+ public static AsymmetricCipherKeyPair GetECDsaKeyPair(ECDsa ecDsa)
+ {
+ return GetECKeyPair("ECDSA", ecDsa.ExportParameters(true));
+ }
+
+ public static ECPublicKeyParameters GetECDsaPublicKey(ECDsa ecDsa)
+ {
+ return GetECPublicKey("ECDSA", ecDsa.ExportParameters(false));
+ }
+
+ public static AsymmetricCipherKeyPair GetECKeyPair(string algorithm, ECParameters ec)
+ {
+ ECPublicKeyParameters pubKey = GetECPublicKey(algorithm, ec);
+
+ ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
+ pubKey.AlgorithmName,
+ new BigInteger(1, ec.D),
+ pubKey.Parameters);
+
+ return new AsymmetricCipherKeyPair(pubKey, privKey);
+ }
+
+ public static ECPublicKeyParameters GetECPublicKey(string algorithm, ECParameters ec)
+ {
+ X9ECParameters x9 = GetX9ECParameters(ec.Curve);
+ if (x9 == null)
+ throw new NotSupportedException("Unrecognized curve");
+
+ return new ECPublicKeyParameters(
+ algorithm,
+ GetECPoint(x9.Curve, ec.Q),
+ new ECDomainParameters(x9));
+ }
+
+ private static Math.EC.ECPoint GetECPoint(Math.EC.ECCurve curve, ECPoint point)
+ {
+ return curve.CreatePoint(new BigInteger(1, point.X), new BigInteger(1, point.Y));
+ }
+
+ private static X9ECParameters GetX9ECParameters(ECCurve curve)
+ {
+ if (!curve.IsNamed)
+ throw new NotSupportedException("Only named curves are supported");
+
+ Oid oid = curve.Oid;
+ if (oid != null)
+ {
+ string oidValue = oid.Value;
+ if (oidValue != null)
+ return ECKeyPairGenerator.FindECCurveByOid(new DerObjectIdentifier(oidValue));
+ }
+ return null;
+ }
+#endif
+
public static AsymmetricCipherKeyPair GetRsaKeyPair(RSA rsa)
{
return GetRsaKeyPair(rsa.ExportParameters(true));
@@ -100,17 +147,11 @@ namespace Org.BouncyCastle.Security
public static AsymmetricCipherKeyPair GetRsaKeyPair(RSAParameters rp)
{
- BigInteger modulus = new BigInteger(1, rp.Modulus);
- BigInteger pubExp = new BigInteger(1, rp.Exponent);
-
- RsaKeyParameters pubKey = new RsaKeyParameters(
- false,
- modulus,
- pubExp);
+ RsaKeyParameters pubKey = GetRsaPublicKey(rp);
RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
- modulus,
- pubExp,
+ pubKey.Modulus,
+ pubKey.Exponent,
new BigInteger(1, rp.D),
new BigInteger(1, rp.P),
new BigInteger(1, rp.Q),
@@ -137,17 +178,18 @@ namespace Org.BouncyCastle.Security
public static AsymmetricCipherKeyPair GetKeyPair(AsymmetricAlgorithm privateKey)
{
- if (privateKey is DSA)
- {
- return GetDsaKeyPair((DSA)privateKey);
- }
+ if (privateKey is DSA dsa)
+ return GetDsaKeyPair(dsa);
- if (privateKey is RSA)
- {
- return GetRsaKeyPair((RSA)privateKey);
- }
+#if NETCOREAPP1_0_OR_GREATER || NET47_OR_GREATER || NETSTANDARD1_6_OR_GREATER
+ if (privateKey is ECDsa ecDsa)
+ return GetECDsaKeyPair(ecDsa);
+#endif
- throw new ArgumentException("Unsupported algorithm specified", "privateKey");
+ if (privateKey is RSA rsa)
+ return GetRsaKeyPair(rsa);
+
+ throw new ArgumentException("Unsupported algorithm specified", nameof(privateKey));
}
#if NET5_0_OR_GREATER
@@ -244,6 +286,18 @@ namespace Org.BouncyCastle.Security
return BigIntegers.AsUnsignedByteArray(size, n);
}
+ // TODO Why do we use CspParameters instead of just RSA.Create in methods below?
+// private static RSA CreateRSA(RSAParameters rp)
+// {
+//#if NETCOREAPP2_0_OR_GREATER || NET472_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+// return RSA.Create(rp);
+//#else
+// var rsa = RSA.Create();
+// rsa.ImportParameters(rp);
+// return rsa;
+//#endif
+// }
+
#if NET5_0_OR_GREATER
[SupportedOSPlatform("windows")]
#endif
|