summary refs log tree commit diff
path: root/crypto/src/security
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2018-09-21 15:17:56 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2018-09-21 15:17:56 +0700
commitfbae27fb1edcea6b0924dba977a6d94f0a3655db (patch)
treeffea8216ac6125b574dcd05bed38fccd0fe10ba5 /crypto/src/security
parentRefactoring (diff)
downloadBouncyCastle.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.cs55
-rw-r--r--crypto/src/security/GeneratorUtilities.cs34
-rw-r--r--crypto/src/security/PrivateKeyFactory.cs28
-rw-r--r--crypto/src/security/PublicKeyFactory.cs32
-rw-r--r--crypto/src/security/SignerUtilities.cs36
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));