diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2018-09-21 15:17:56 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2018-09-21 15:17:56 +0700 |
commit | fbae27fb1edcea6b0924dba977a6d94f0a3655db (patch) | |
tree | ffea8216ac6125b574dcd05bed38fccd0fe10ba5 /crypto/src/security | |
parent | Refactoring (diff) | |
download | BouncyCastle.NET-ed25519-fbae27fb1edcea6b0924dba977a6d94f0a3655db.tar.xz |
Higher-level API support for Ed25519/Ed448/X25519/X448
Diffstat (limited to 'crypto/src/security')
-rw-r--r-- | crypto/src/security/AgreementUtilities.cs | 55 | ||||
-rw-r--r-- | crypto/src/security/GeneratorUtilities.cs | 34 | ||||
-rw-r--r-- | crypto/src/security/PrivateKeyFactory.cs | 28 | ||||
-rw-r--r-- | crypto/src/security/PublicKeyFactory.cs | 32 | ||||
-rw-r--r-- | crypto/src/security/SignerUtilities.cs | 36 |
5 files changed, 159 insertions, 26 deletions
diff --git a/crypto/src/security/AgreementUtilities.cs b/crypto/src/security/AgreementUtilities.cs index 12d427c8c..26d1628cc 100644 --- a/crypto/src/security/AgreementUtilities.cs +++ b/crypto/src/security/AgreementUtilities.cs @@ -1,6 +1,7 @@ using System.Collections; using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Agreement; @@ -27,7 +28,10 @@ namespace Org.BouncyCastle.Security algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = "ECCDHWITHSHA1KDF"; algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "ECDHWITHSHA1KDF"; algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = "ECMQVWITHSHA1KDF"; - } + + algorithms[EdECObjectIdentifiers.id_X25519.Id] = "X25519"; + algorithms[EdECObjectIdentifiers.id_X448.Id] = "X448"; + } public static IBasicAgreement GetBasicAgreement( DerObjectIdentifier oid) @@ -38,15 +42,9 @@ namespace Org.BouncyCastle.Security public static IBasicAgreement GetBasicAgreement( string algorithm) { - string upper = Platform.ToUpperInvariant(algorithm); - string mechanism = (string) algorithms[upper]; - - if (mechanism == null) - { - mechanism = upper; - } + string mechanism = GetMechanism(algorithm); - if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN") + if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN") return new DHBasicAgreement(); if (mechanism == "ECDH") @@ -72,15 +70,9 @@ namespace Org.BouncyCastle.Security string agreeAlgorithm, string wrapAlgorithm) { - string upper = Platform.ToUpperInvariant(agreeAlgorithm); - string mechanism = (string) algorithms[upper]; + string mechanism = GetMechanism(agreeAlgorithm); - if (mechanism == null) - { - mechanism = upper; - } - - // 'DHWITHSHA1KDF' retained for backward compatibility + // 'DHWITHSHA1KDF' retained for backward compatibility if (mechanism == "DHWITHSHA1KDF" || mechanism == "ECDHWITHSHA1KDF") return new ECDHWithKdfBasicAgreement( wrapAlgorithm, @@ -96,10 +88,37 @@ namespace Org.BouncyCastle.Security throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised."); } + public static IRawAgreement GetRawAgreement( + DerObjectIdentifier oid) + { + return GetRawAgreement(oid.Id); + } + + public static IRawAgreement GetRawAgreement( + string algorithm) + { + string mechanism = GetMechanism(algorithm); + + if (mechanism == "X25519") + return new X25519Agreement(); + + if (mechanism == "X448") + return new X448Agreement(); + + throw new SecurityUtilityException("Raw Agreement " + algorithm + " not recognised."); + } + public static string GetAlgorithmName( DerObjectIdentifier oid) { - return (string) algorithms[oid.Id]; + return (string)algorithms[oid.Id]; } + + private static string GetMechanism(string algorithm) + { + string upper = Platform.ToUpperInvariant(algorithm); + string mechanism = (string)algorithms[upper]; + return mechanism == null ? upper : mechanism; + } } } diff --git a/crypto/src/security/GeneratorUtilities.cs b/crypto/src/security/GeneratorUtilities.cs index db1929c16..26ddb396b 100644 --- a/crypto/src/security/GeneratorUtilities.cs +++ b/crypto/src/security/GeneratorUtilities.cs @@ -2,6 +2,7 @@ using System.Collections; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.Iana; using Org.BouncyCastle.Asn1.Kisa; using Org.BouncyCastle.Asn1.Nist; @@ -180,12 +181,23 @@ namespace Org.BouncyCastle.Security AddKpgAlgorithm("ECGOST3410", "ECGOST-3410", "GOST-3410-2001"); + AddKpgAlgorithm("Ed25519", + "Ed25519ctx", + "Ed25519ph", + EdECObjectIdentifiers.id_Ed25519); + AddKpgAlgorithm("Ed448", + "Ed448ph", + EdECObjectIdentifiers.id_Ed448); AddKpgAlgorithm("ELGAMAL"); AddKpgAlgorithm("GOST3410", "GOST-3410", "GOST-3410-94"); AddKpgAlgorithm("RSA", "1.2.840.113549.1.1.1"); + AddKpgAlgorithm("X25519", + EdECObjectIdentifiers.id_X25519); + AddKpgAlgorithm("X448", + EdECObjectIdentifiers.id_X448); AddDefaultKeySizeEntries(64, "DES"); AddDefaultKeySizeEntries(80, "SKIPJACK"); @@ -216,11 +228,11 @@ namespace Org.BouncyCastle.Security string canonicalName, params object[] aliases) { - kgAlgorithms[canonicalName] = canonicalName; + kgAlgorithms[Platform.ToUpperInvariant(canonicalName)] = canonicalName; foreach (object alias in aliases) { - kgAlgorithms[alias.ToString()] = canonicalName; + kgAlgorithms[Platform.ToUpperInvariant(alias.ToString())] = canonicalName; } } @@ -228,11 +240,11 @@ namespace Org.BouncyCastle.Security string canonicalName, params object[] aliases) { - kpgAlgorithms[canonicalName] = canonicalName; + kpgAlgorithms[Platform.ToUpperInvariant(canonicalName)] = canonicalName; foreach (object alias in aliases) { - kpgAlgorithms[alias.ToString()] = canonicalName; + kpgAlgorithms[Platform.ToUpperInvariant(alias.ToString())] = canonicalName; } } @@ -248,7 +260,7 @@ namespace Org.BouncyCastle.Security foreach (object alias in aliases) { - kgAlgorithms[alias.ToString()] = mainName; + kgAlgorithms[Platform.ToUpperInvariant(alias.ToString())] = mainName; } } @@ -318,6 +330,12 @@ namespace Org.BouncyCastle.Security if (Platform.StartsWith(canonicalName, "EC")) return new ECKeyPairGenerator(canonicalName); + if (canonicalName == "Ed25519") + return new Ed25519KeyPairGenerator(); + + if (canonicalName == "Ed448") + return new Ed448KeyPairGenerator(); + if (canonicalName == "ELGAMAL") return new ElGamalKeyPairGenerator(); @@ -327,6 +345,12 @@ namespace Org.BouncyCastle.Security if (canonicalName == "RSA") return new RsaKeyPairGenerator(); + if (canonicalName == "X25519") + return new X25519KeyPairGenerator(); + + if (canonicalName == "X448") + return new X448KeyPairGenerator(); + throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " (" + canonicalName + ") not supported."); } diff --git a/crypto/src/security/PrivateKeyFactory.cs b/crypto/src/security/PrivateKeyFactory.cs index c9e19cc7d..0b07d0659 100644 --- a/crypto/src/security/PrivateKeyFactory.cs +++ b/crypto/src/security/PrivateKeyFactory.cs @@ -5,6 +5,7 @@ using System.Text; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.Sec; @@ -170,12 +171,37 @@ namespace Org.BouncyCastle.Security return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet); } + else if (algOid.Equals(EdECObjectIdentifiers.id_X25519)) + { + return new X25519PrivateKeyParameters(GetRawKey(keyInfo, X25519PrivateKeyParameters.KeySize), 0); + } + else if (algOid.Equals(EdECObjectIdentifiers.id_X448)) + { + return new X448PrivateKeyParameters(GetRawKey(keyInfo, X448PrivateKeyParameters.KeySize), 0); + } + else if (algOid.Equals(EdECObjectIdentifiers.id_Ed25519)) + { + return new Ed25519PrivateKeyParameters(GetRawKey(keyInfo, Ed25519PrivateKeyParameters.KeySize), 0); + } + else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448)) + { + return new Ed448PrivateKeyParameters(GetRawKey(keyInfo, Ed448PrivateKeyParameters.KeySize), 0); + } else { - throw new SecurityUtilityException("algorithm identifier in key not recognised"); + throw new SecurityUtilityException("algorithm identifier in private key not recognised"); } } + private static byte[] GetRawKey(PrivateKeyInfo keyInfo, int expectedSize) + { + byte[] result = Asn1OctetString.GetInstance(keyInfo.ParsePrivateKey()).GetOctets(); + if (expectedSize != result.Length) + throw new SecurityUtilityException("private key encoding has incorrect length"); + + return result; + } + public static AsymmetricKeyParameter DecryptKey( char[] passPhrase, EncryptedPrivateKeyInfo encInfo) diff --git a/crypto/src/security/PublicKeyFactory.cs b/crypto/src/security/PublicKeyFactory.cs index f1b28b774..e39748e45 100644 --- a/crypto/src/security/PublicKeyFactory.cs +++ b/crypto/src/security/PublicKeyFactory.cs @@ -5,6 +5,7 @@ using System.Text; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.Sec; @@ -218,12 +219,41 @@ namespace Org.BouncyCastle.Security return new Gost3410PublicKeyParameters(y, algParams.PublicKeyParamSet); } + else if (algOid.Equals(EdECObjectIdentifiers.id_X25519)) + { + return new X25519PublicKeyParameters(GetRawKey(keyInfo, X25519PublicKeyParameters.KeySize), 0); + } + else if (algOid.Equals(EdECObjectIdentifiers.id_X448)) + { + return new X448PublicKeyParameters(GetRawKey(keyInfo, X448PublicKeyParameters.KeySize), 0); + } + else if (algOid.Equals(EdECObjectIdentifiers.id_Ed25519)) + { + return new Ed25519PublicKeyParameters(GetRawKey(keyInfo, Ed25519PublicKeyParameters.KeySize), 0); + } + else if (algOid.Equals(EdECObjectIdentifiers.id_Ed448)) + { + return new Ed448PublicKeyParameters(GetRawKey(keyInfo, Ed448PublicKeyParameters.KeySize), 0); + } else { - throw new SecurityUtilityException("algorithm identifier in key not recognised: " + algOid); + throw new SecurityUtilityException("algorithm identifier in public key not recognised: " + algOid); } } + private static byte[] GetRawKey(SubjectPublicKeyInfo keyInfo, int expectedSize) + { + /* + * TODO[RFC 8422] + * - Require keyInfo.Algorithm.Parameters == null? + */ + byte[] result = keyInfo.PublicKeyData.GetOctets(); + if (expectedSize != result.Length) + throw new SecurityUtilityException("public key encoding has incorrect length"); + + return result; + } + private static bool IsPkcsDHParam(Asn1Sequence seq) { if (seq.Count == 2) diff --git a/crypto/src/security/SignerUtilities.cs b/crypto/src/security/SignerUtilities.cs index 44281503a..a9045ae6e 100644 --- a/crypto/src/security/SignerUtilities.cs +++ b/crypto/src/security/SignerUtilities.cs @@ -4,6 +4,7 @@ using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.CryptoPro; +using Org.BouncyCastle.Asn1.EdEC; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; @@ -231,7 +232,13 @@ namespace Org.BouncyCastle.Security algorithms["GOST3411WITHECGOST3410"] = "ECGOST3410"; algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001.Id] = "ECGOST3410"; - + algorithms["ED25519"] = "Ed25519"; + algorithms[EdECObjectIdentifiers.id_Ed25519.Id] = "Ed25519"; + algorithms["ED25519CTX"] = "Ed25519ctx"; + algorithms["ED25519PH"] = "Ed25519ph"; + algorithms["ED448"] = "Ed448"; + algorithms[EdECObjectIdentifiers.id_Ed448.Id] = "Ed448"; + algorithms["ED448PH"] = "Ed448ph"; oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption; oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption; @@ -264,6 +271,9 @@ namespace Org.BouncyCastle.Security oids["GOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94; oids["ECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001; + + oids["Ed25519"] = EdECObjectIdentifiers.id_Ed25519; + oids["Ed448"] = EdECObjectIdentifiers.id_Ed448; } /// <summary> @@ -361,6 +371,30 @@ namespace Org.BouncyCastle.Security if (mechanism == null) mechanism = algorithm; + if (Platform.StartsWith(mechanism, "Ed")) + { + if (mechanism.Equals("Ed25519")) + { + return new Ed25519Signer(); + } + if (mechanism.Equals("Ed25519ctx")) + { + return new Ed25519ctxSigner(Arrays.EmptyBytes); + } + if (mechanism.Equals("Ed25519ph")) + { + return new Ed25519phSigner(Arrays.EmptyBytes); + } + if (mechanism.Equals("Ed448")) + { + return new Ed448Signer(Arrays.EmptyBytes); + } + if (mechanism.Equals("Ed448ph")) + { + return new Ed448phSigner(Arrays.EmptyBytes); + } + } + if (mechanism.Equals("RSA")) { return (new RsaDigestSigner(new NullDigest(), (AlgorithmIdentifier)null)); |