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 | |
parent | Refactoring (diff) | |
download | BouncyCastle.NET-ed25519-fbae27fb1edcea6b0924dba977a6d94f0a3655db.tar.xz |
Higher-level API support for Ed25519/Ed448/X25519/X448
49 files changed, 2259 insertions, 91 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index 3c34c5e1b..c5eb8e6f5 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -258,6 +258,7 @@ <Compile Include="src\asn1\cryptopro\GOST3410ParamSetParameters.cs" /> <Compile Include="src\asn1\cryptopro\GOST3410PublicKeyAlgParameters.cs" /> <Compile Include="src\asn1\eac\EACObjectIdentifiers.cs" /> + <Compile Include="src\asn1\edec\EdECObjectIdentifiers.cs" /> <Compile Include="src\asn1\esf\CertificateValues.cs" /> <Compile Include="src\asn1\esf\CommitmentTypeIdentifier.cs" /> <Compile Include="src\asn1\esf\CommitmentTypeIndication.cs" /> @@ -659,6 +660,7 @@ <Compile Include="src\crypto\IEntropySource.cs" /> <Compile Include="src\crypto\IEntropySourceProvider.cs" /> <Compile Include="src\crypto\IMac.cs" /> + <Compile Include="src\crypto\IRawAgreement.cs" /> <Compile Include="src\crypto\ISignatureFactory.cs" /> <Compile Include="src\crypto\IStreamCalculator.cs" /> <Compile Include="src\crypto\ISigner.cs" /> @@ -699,6 +701,8 @@ <Compile Include="src\crypto\agreement\ECMqvBasicAgreement.cs" /> <Compile Include="src\crypto\agreement\ECMqvWithKdfBasicAgreement.cs" /> <Compile Include="src\crypto\agreement\SM2KeyExchange.cs" /> + <Compile Include="src\crypto\agreement\X25519Agreement.cs" /> + <Compile Include="src\crypto\agreement\X448Agreement.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakeParticipant.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakePrimeOrderGroup.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakePrimeOrderGroups.cs" /> @@ -815,6 +819,8 @@ <Compile Include="src\crypto\generators\DsaKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\DsaParametersGenerator.cs" /> <Compile Include="src\crypto\generators\ECKeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\Ed25519KeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\Ed448KeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\ElGamalKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\ElGamalParametersGenerator.cs" /> <Compile Include="src\crypto\generators\GOST3410KeyPairGenerator.cs" /> @@ -831,6 +837,8 @@ <Compile Include="src\crypto\generators\RSABlindingFactorGenerator.cs" /> <Compile Include="src\crypto\generators\RsaKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\SCrypt.cs" /> + <Compile Include="src\crypto\generators\X25519KeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\X448KeyPairGenerator.cs" /> <Compile Include="src\crypto\io\CipherStream.cs" /> <Compile Include="src\crypto\io\DigestStream.cs" /> <Compile Include="src\crypto\io\MacStream.cs" /> @@ -901,6 +909,12 @@ <Compile Include="src\crypto\parameters\ECKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ECPrivateKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ECPublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519PublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448PublicKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalKeyGenerationParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalParameters.cs" /> @@ -939,6 +953,12 @@ <Compile Include="src\crypto\parameters\SM2KeyExchangePublicParameters.cs" /> <Compile Include="src\crypto\parameters\Srp6GroupParameters.cs" /> <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519PublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X448KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\X448PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X448PublicKeyParameters.cs" /> <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" /> <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" /> <Compile Include="src\crypto\prng\IRandomGenerator.cs" /> @@ -950,6 +970,11 @@ <Compile Include="src\crypto\signers\ECDsaSigner.cs" /> <Compile Include="src\crypto\signers\ECGOST3410Signer.cs" /> <Compile Include="src\crypto\signers\ECNRSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519ctxSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519phSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519Signer.cs" /> + <Compile Include="src\crypto\signers\Ed448phSigner.cs" /> + <Compile Include="src\crypto\signers\Ed448Signer.cs" /> <Compile Include="src\crypto\signers\GOST3410DigestSigner.cs" /> <Compile Include="src\crypto\signers\GOST3410Signer.cs" /> <Compile Include="src\crypto\signers\GenericSigner.cs" /> diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index 95d42bc8b..76da30095 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -252,6 +252,7 @@ <Compile Include="src\asn1\cryptopro\GOST3410ParamSetParameters.cs" /> <Compile Include="src\asn1\cryptopro\GOST3410PublicKeyAlgParameters.cs" /> <Compile Include="src\asn1\eac\EACObjectIdentifiers.cs" /> + <Compile Include="src\asn1\edec\EdECObjectIdentifiers.cs" /> <Compile Include="src\asn1\esf\CertificateValues.cs" /> <Compile Include="src\asn1\esf\CommitmentTypeIdentifier.cs" /> <Compile Include="src\asn1\esf\CommitmentTypeIndication.cs" /> @@ -653,6 +654,7 @@ <Compile Include="src\crypto\IEntropySource.cs" /> <Compile Include="src\crypto\IEntropySourceProvider.cs" /> <Compile Include="src\crypto\IMac.cs" /> + <Compile Include="src\crypto\IRawAgreement.cs" /> <Compile Include="src\crypto\ISignatureFactory.cs" /> <Compile Include="src\crypto\IStreamCalculator.cs" /> <Compile Include="src\crypto\ISigner.cs" /> @@ -693,6 +695,8 @@ <Compile Include="src\crypto\agreement\ECMqvBasicAgreement.cs" /> <Compile Include="src\crypto\agreement\ECMqvWithKdfBasicAgreement.cs" /> <Compile Include="src\crypto\agreement\SM2KeyExchange.cs" /> + <Compile Include="src\crypto\agreement\X25519Agreement.cs" /> + <Compile Include="src\crypto\agreement\X448Agreement.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakeParticipant.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakePrimeOrderGroup.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakePrimeOrderGroups.cs" /> @@ -809,6 +813,8 @@ <Compile Include="src\crypto\generators\DsaKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\DsaParametersGenerator.cs" /> <Compile Include="src\crypto\generators\ECKeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\Ed25519KeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\Ed448KeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\ElGamalKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\ElGamalParametersGenerator.cs" /> <Compile Include="src\crypto\generators\GOST3410KeyPairGenerator.cs" /> @@ -825,6 +831,8 @@ <Compile Include="src\crypto\generators\RSABlindingFactorGenerator.cs" /> <Compile Include="src\crypto\generators\RsaKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\SCrypt.cs" /> + <Compile Include="src\crypto\generators\X25519KeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\X448KeyPairGenerator.cs" /> <Compile Include="src\crypto\io\CipherStream.cs" /> <Compile Include="src\crypto\io\DigestStream.cs" /> <Compile Include="src\crypto\io\MacStream.cs" /> @@ -895,6 +903,12 @@ <Compile Include="src\crypto\parameters\ECKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ECPrivateKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ECPublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519PublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448PublicKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalKeyGenerationParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalParameters.cs" /> @@ -933,6 +947,12 @@ <Compile Include="src\crypto\parameters\SM2KeyExchangePublicParameters.cs" /> <Compile Include="src\crypto\parameters\Srp6GroupParameters.cs" /> <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519PublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X448KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\X448PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X448PublicKeyParameters.cs" /> <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" /> <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" /> <Compile Include="src\crypto\prng\IRandomGenerator.cs" /> @@ -944,6 +964,11 @@ <Compile Include="src\crypto\signers\ECDsaSigner.cs" /> <Compile Include="src\crypto\signers\ECGOST3410Signer.cs" /> <Compile Include="src\crypto\signers\ECNRSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519ctxSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519phSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519Signer.cs" /> + <Compile Include="src\crypto\signers\Ed448phSigner.cs" /> + <Compile Include="src\crypto\signers\Ed448Signer.cs" /> <Compile Include="src\crypto\signers\GOST3410DigestSigner.cs" /> <Compile Include="src\crypto\signers\GOST3410Signer.cs" /> <Compile Include="src\crypto\signers\GenericSigner.cs" /> diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index f9cebdc86..52dae0f4f 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -253,6 +253,7 @@ <Compile Include="src\asn1\cryptopro\GOST3410ParamSetParameters.cs" /> <Compile Include="src\asn1\cryptopro\GOST3410PublicKeyAlgParameters.cs" /> <Compile Include="src\asn1\eac\EACObjectIdentifiers.cs" /> + <Compile Include="src\asn1\edec\EdECObjectIdentifiers.cs" /> <Compile Include="src\asn1\esf\CertificateValues.cs" /> <Compile Include="src\asn1\esf\CommitmentTypeIdentifier.cs" /> <Compile Include="src\asn1\esf\CommitmentTypeIndication.cs" /> @@ -654,6 +655,7 @@ <Compile Include="src\crypto\IEntropySource.cs" /> <Compile Include="src\crypto\IEntropySourceProvider.cs" /> <Compile Include="src\crypto\IMac.cs" /> + <Compile Include="src\crypto\IRawAgreement.cs" /> <Compile Include="src\crypto\ISignatureFactory.cs" /> <Compile Include="src\crypto\IStreamCalculator.cs" /> <Compile Include="src\crypto\ISigner.cs" /> @@ -694,6 +696,8 @@ <Compile Include="src\crypto\agreement\ECMqvBasicAgreement.cs" /> <Compile Include="src\crypto\agreement\ECMqvWithKdfBasicAgreement.cs" /> <Compile Include="src\crypto\agreement\SM2KeyExchange.cs" /> + <Compile Include="src\crypto\agreement\X25519Agreement.cs" /> + <Compile Include="src\crypto\agreement\X448Agreement.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakeParticipant.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakePrimeOrderGroup.cs" /> <Compile Include="src\crypto\agreement\jpake\JPakePrimeOrderGroups.cs" /> @@ -810,6 +814,8 @@ <Compile Include="src\crypto\generators\DsaKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\DsaParametersGenerator.cs" /> <Compile Include="src\crypto\generators\ECKeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\Ed25519KeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\Ed448KeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\ElGamalKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\ElGamalParametersGenerator.cs" /> <Compile Include="src\crypto\generators\GOST3410KeyPairGenerator.cs" /> @@ -826,6 +832,8 @@ <Compile Include="src\crypto\generators\RSABlindingFactorGenerator.cs" /> <Compile Include="src\crypto\generators\RsaKeyPairGenerator.cs" /> <Compile Include="src\crypto\generators\SCrypt.cs" /> + <Compile Include="src\crypto\generators\X25519KeyPairGenerator.cs" /> + <Compile Include="src\crypto\generators\X448KeyPairGenerator.cs" /> <Compile Include="src\crypto\io\CipherStream.cs" /> <Compile Include="src\crypto\io\DigestStream.cs" /> <Compile Include="src\crypto\io\MacStream.cs" /> @@ -896,6 +904,12 @@ <Compile Include="src\crypto\parameters\ECKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ECPrivateKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ECPublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed25519PublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\Ed448PublicKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalKeyGenerationParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalKeyParameters.cs" /> <Compile Include="src\crypto\parameters\ElGamalParameters.cs" /> @@ -934,6 +948,12 @@ <Compile Include="src\crypto\parameters\SM2KeyExchangePublicParameters.cs" /> <Compile Include="src\crypto\parameters\Srp6GroupParameters.cs" /> <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X25519PublicKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X448KeyGenerationParameters.cs" /> + <Compile Include="src\crypto\parameters\X448PrivateKeyParameters.cs" /> + <Compile Include="src\crypto\parameters\X448PublicKeyParameters.cs" /> <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" /> <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" /> <Compile Include="src\crypto\prng\IRandomGenerator.cs" /> @@ -945,6 +965,11 @@ <Compile Include="src\crypto\signers\ECDsaSigner.cs" /> <Compile Include="src\crypto\signers\ECGOST3410Signer.cs" /> <Compile Include="src\crypto\signers\ECNRSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519ctxSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519phSigner.cs" /> + <Compile Include="src\crypto\signers\Ed25519Signer.cs" /> + <Compile Include="src\crypto\signers\Ed448phSigner.cs" /> + <Compile Include="src\crypto\signers\Ed448Signer.cs" /> <Compile Include="src\crypto\signers\GOST3410DigestSigner.cs" /> <Compile Include="src\crypto\signers\GOST3410Signer.cs" /> <Compile Include="src\crypto\signers\GenericSigner.cs" /> diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index b6dfb3963..2ffb66d8c 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -1149,6 +1149,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\asn1\edec\EdECObjectIdentifiers.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\asn1\esf\CertificateValues.cs" SubType = "Code" BuildAction = "Compile" @@ -3129,6 +3134,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\IRawAgreement.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\ISignatureFactory.cs" SubType = "Code" BuildAction = "Compile" @@ -3249,6 +3259,16 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\agreement\X25519Agreement.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\agreement\X448Agreement.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\agreement\jpake\JPakeParticipant.cs" SubType = "Code" BuildAction = "Compile" @@ -3849,6 +3869,16 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\generators\Ed25519KeyPairGenerator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\generators\Ed448KeyPairGenerator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\generators\ElGamalKeyPairGenerator.cs" SubType = "Code" BuildAction = "Compile" @@ -3939,6 +3969,16 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\generators\X25519KeyPairGenerator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\generators\X448KeyPairGenerator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\io\CipherStream.cs" SubType = "Code" BuildAction = "Compile" @@ -4289,6 +4329,36 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\parameters\Ed25519KeyGenerationParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\Ed25519PrivateKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\Ed25519PublicKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\Ed448KeyGenerationParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\Ed448PrivateKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\Ed448PublicKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\parameters\ElGamalKeyGenerationParameters.cs" SubType = "Code" BuildAction = "Compile" @@ -4484,6 +4554,36 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\parameters\X25519KeyGenerationParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\X25519PrivateKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\X25519PublicKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\X448KeyGenerationParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\X448PrivateKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\parameters\X448PublicKeyParameters.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\prng\BasicEntropySourceProvider.cs" SubType = "Code" BuildAction = "Compile" @@ -4609,6 +4709,31 @@ BuildAction = "Compile" /> <File + RelPath = "src\crypto\signers\Ed25519ctxSigner.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\signers\Ed25519phSigner.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\signers\Ed25519Signer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\signers\Ed448phSigner.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "src\crypto\signers\Ed448Signer.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\crypto\signers\GenericSigner.cs" SubType = "Code" BuildAction = "Compile" @@ -11230,6 +11355,11 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\asn1\test\PrivateKeyInfoTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\asn1\test\PKCS10Test.cs" SubType = "Code" BuildAction = "Compile" @@ -11670,6 +11800,16 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\test\Ed25519Test.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\test\Ed448Test.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\test\ElGamalTest.cs" SubType = "Code" BuildAction = "Compile" @@ -12160,6 +12300,16 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\crypto\test\X25519Test.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File + RelPath = "test\src\crypto\test\X448Test.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\crypto\test\X931SignerTest.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/asn1/edec/EdECObjectIdentifiers.cs b/crypto/src/asn1/edec/EdECObjectIdentifiers.cs new file mode 100644 index 000000000..f8c5713d8 --- /dev/null +++ b/crypto/src/asn1/edec/EdECObjectIdentifiers.cs @@ -0,0 +1,17 @@ +using System; + +namespace Org.BouncyCastle.Asn1.EdEC +{ + /** + * Edwards Elliptic Curve Object Identifiers (RFC 8410) + */ + public abstract class EdECObjectIdentifiers + { + public static readonly DerObjectIdentifier id_edwards_curve_algs = new DerObjectIdentifier("1.3.101"); + + public static readonly DerObjectIdentifier id_X25519 = id_edwards_curve_algs.Branch("110"); + public static readonly DerObjectIdentifier id_X448 = id_edwards_curve_algs.Branch("111"); + public static readonly DerObjectIdentifier id_Ed25519 = id_edwards_curve_algs.Branch("112"); + public static readonly DerObjectIdentifier id_Ed448 = id_edwards_curve_algs.Branch("113"); + } +} diff --git a/crypto/src/crypto/IRawAgreement.cs b/crypto/src/crypto/IRawAgreement.cs new file mode 100644 index 000000000..63e664888 --- /dev/null +++ b/crypto/src/crypto/IRawAgreement.cs @@ -0,0 +1,13 @@ +using System; + +namespace Org.BouncyCastle.Crypto +{ + public interface IRawAgreement + { + void Init(ICipherParameters parameters); + + int AgreementSize { get; } + + void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off); + } +} diff --git a/crypto/src/crypto/agreement/X25519Agreement.cs b/crypto/src/crypto/agreement/X25519Agreement.cs new file mode 100644 index 000000000..7e5890c16 --- /dev/null +++ b/crypto/src/crypto/agreement/X25519Agreement.cs @@ -0,0 +1,27 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + public sealed class X25519Agreement + : IRawAgreement + { + private X25519PrivateKeyParameters privateKey; + + public void Init(ICipherParameters parameters) + { + this.privateKey = (X25519PrivateKeyParameters)parameters; + } + + public int AgreementSize + { + get { return X25519PrivateKeyParameters.SecretSize; } + } + + public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off) + { + privateKey.GenerateSecret((X25519PublicKeyParameters)publicKey, buf, off); + } + } +} diff --git a/crypto/src/crypto/agreement/X448Agreement.cs b/crypto/src/crypto/agreement/X448Agreement.cs new file mode 100644 index 000000000..26f608c26 --- /dev/null +++ b/crypto/src/crypto/agreement/X448Agreement.cs @@ -0,0 +1,27 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; + +namespace Org.BouncyCastle.Crypto.Agreement +{ + public sealed class X448Agreement + : IRawAgreement + { + private X448PrivateKeyParameters privateKey; + + public void Init(ICipherParameters parameters) + { + this.privateKey = (X448PrivateKeyParameters)parameters; + } + + public int AgreementSize + { + get { return X448PrivateKeyParameters.SecretSize; } + } + + public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off) + { + privateKey.GenerateSecret((X448PublicKeyParameters)publicKey, buf, off); + } + } +} diff --git a/crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs b/crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs new file mode 100644 index 000000000..266d111cf --- /dev/null +++ b/crypto/src/crypto/generators/Ed25519KeyPairGenerator.cs @@ -0,0 +1,25 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class Ed25519KeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private SecureRandom random; + + public virtual void Init(KeyGenerationParameters parameters) + { + this.random = parameters.Random; + } + + public virtual AsymmetricCipherKeyPair GenerateKeyPair() + { + Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters(random); + Ed25519PublicKeyParameters publicKey = privateKey.GeneratePublicKey(); + return new AsymmetricCipherKeyPair(publicKey, privateKey); + } + } +} diff --git a/crypto/src/crypto/generators/Ed448KeyPairGenerator.cs b/crypto/src/crypto/generators/Ed448KeyPairGenerator.cs new file mode 100644 index 000000000..50aee631e --- /dev/null +++ b/crypto/src/crypto/generators/Ed448KeyPairGenerator.cs @@ -0,0 +1,25 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class Ed448KeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private SecureRandom random; + + public virtual void Init(KeyGenerationParameters parameters) + { + this.random = parameters.Random; + } + + public virtual AsymmetricCipherKeyPair GenerateKeyPair() + { + Ed448PrivateKeyParameters privateKey = new Ed448PrivateKeyParameters(random); + Ed448PublicKeyParameters publicKey = privateKey.GeneratePublicKey(); + return new AsymmetricCipherKeyPair(publicKey, privateKey); + } + } +} diff --git a/crypto/src/crypto/generators/X25519KeyPairGenerator.cs b/crypto/src/crypto/generators/X25519KeyPairGenerator.cs new file mode 100644 index 000000000..94378448b --- /dev/null +++ b/crypto/src/crypto/generators/X25519KeyPairGenerator.cs @@ -0,0 +1,25 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class X25519KeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private SecureRandom random; + + public virtual void Init(KeyGenerationParameters parameters) + { + this.random = parameters.Random; + } + + public virtual AsymmetricCipherKeyPair GenerateKeyPair() + { + X25519PrivateKeyParameters privateKey = new X25519PrivateKeyParameters(random); + X25519PublicKeyParameters publicKey = privateKey.GeneratePublicKey(); + return new AsymmetricCipherKeyPair(publicKey, privateKey); + } + } +} diff --git a/crypto/src/crypto/generators/X448KeyPairGenerator.cs b/crypto/src/crypto/generators/X448KeyPairGenerator.cs new file mode 100644 index 000000000..4a203e4f1 --- /dev/null +++ b/crypto/src/crypto/generators/X448KeyPairGenerator.cs @@ -0,0 +1,25 @@ +using System; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Generators +{ + public class X448KeyPairGenerator + : IAsymmetricCipherKeyPairGenerator + { + private SecureRandom random; + + public virtual void Init(KeyGenerationParameters parameters) + { + this.random = parameters.Random; + } + + public virtual AsymmetricCipherKeyPair GenerateKeyPair() + { + X448PrivateKeyParameters privateKey = new X448PrivateKeyParameters(random); + X448PublicKeyParameters publicKey = privateKey.GeneratePublicKey(); + return new AsymmetricCipherKeyPair(publicKey, privateKey); + } + } +} diff --git a/crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs b/crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs new file mode 100644 index 000000000..daf3856c3 --- /dev/null +++ b/crypto/src/crypto/parameters/Ed25519KeyGenerationParameters.cs @@ -0,0 +1,15 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class Ed25519KeyGenerationParameters + : KeyGenerationParameters + { + public Ed25519KeyGenerationParameters(SecureRandom random) + : base(random, 256) + { + } + } +} diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs new file mode 100644 index 000000000..97902e093 --- /dev/null +++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs @@ -0,0 +1,98 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class Ed25519PrivateKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = Ed25519.SecretKeySize; + public static readonly int SignatureSize = Ed25519.SignatureSize; + + private readonly byte[] data = new byte[KeySize]; + + public Ed25519PrivateKeyParameters(SecureRandom random) + : base(true) + { + random.NextBytes(data); + } + + public Ed25519PrivateKeyParameters(byte[] buf, int off) + : base(true) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public Ed25519PrivateKeyParameters(Stream input) + : base(true) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of Ed25519 private key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + + public Ed25519PublicKeyParameters GeneratePublicKey() + { + byte[] publicKey = new byte[Ed25519.PublicKeySize]; + Ed25519.GeneratePublicKey(data, 0, publicKey, 0); + return new Ed25519PublicKeyParameters(publicKey, 0); + } + + public void Sign(Ed25519.Algorithm algorithm, Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen, + byte[] sig, int sigOff) + { + byte[] pk = new byte[Ed25519.PublicKeySize]; + if (null == publicKey) + { + Ed25519.GeneratePublicKey(data, 0, pk, 0); + } + else + { + publicKey.Encode(pk, 0); + } + + switch (algorithm) + { + case Ed25519.Algorithm.Ed25519: + { + if (null != ctx) + throw new ArgumentException("ctx"); + + Ed25519.Sign(data, 0, pk, 0, msg, msgOff, msgLen, sig, sigOff); + break; + } + case Ed25519.Algorithm.Ed25519ctx: + { + Ed25519.Sign(data, 0, pk, 0, ctx, msg, msgOff, msgLen, sig, sigOff); + break; + } + case Ed25519.Algorithm.Ed25519ph: + { + if (Ed25519.PrehashSize != msgLen) + throw new ArgumentException("msgLen"); + + Ed25519.SignPrehash(data, 0, pk, 0, ctx, msg, msgOff, sig, sigOff); + break; + } + default: + { + throw new ArgumentException("algorithm"); + } + } + } + } +} diff --git a/crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs new file mode 100644 index 000000000..96e9ec21f --- /dev/null +++ b/crypto/src/crypto/parameters/Ed25519PublicKeyParameters.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class Ed25519PublicKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = Ed25519.PublicKeySize; + + private readonly byte[] data = new byte[KeySize]; + + public Ed25519PublicKeyParameters(byte[] buf, int off) + : base(false) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public Ed25519PublicKeyParameters(Stream input) + : base(false) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of Ed25519 public key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + } +} diff --git a/crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs b/crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs new file mode 100644 index 000000000..830d15a04 --- /dev/null +++ b/crypto/src/crypto/parameters/Ed448KeyGenerationParameters.cs @@ -0,0 +1,15 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class Ed448KeyGenerationParameters + : KeyGenerationParameters + { + public Ed448KeyGenerationParameters(SecureRandom random) + : base(random, 448) + { + } + } +} diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs new file mode 100644 index 000000000..74b5d63f3 --- /dev/null +++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs @@ -0,0 +1,90 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class Ed448PrivateKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = Ed448.SecretKeySize; + public static readonly int SignatureSize = Ed448.SignatureSize; + + private readonly byte[] data = new byte[KeySize]; + + public Ed448PrivateKeyParameters(SecureRandom random) + : base(true) + { + random.NextBytes(data); + } + + public Ed448PrivateKeyParameters(byte[] buf, int off) + : base(true) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public Ed448PrivateKeyParameters(Stream input) + : base(true) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of Ed448 private key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + + public Ed448PublicKeyParameters GeneratePublicKey() + { + byte[] publicKey = new byte[Ed448.PublicKeySize]; + Ed448.GeneratePublicKey(data, 0, publicKey, 0); + return new Ed448PublicKeyParameters(publicKey, 0); + } + + public void Sign(Ed448.Algorithm algorithm, Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen, + byte[] sig, int sigOff) + { + byte[] pk = new byte[Ed448.PublicKeySize]; + if (null == publicKey) + { + Ed448.GeneratePublicKey(data, 0, pk, 0); + } + else + { + publicKey.Encode(pk, 0); + } + + switch (algorithm) + { + case Ed448.Algorithm.Ed448: + { + Ed448.Sign(data, 0, pk, 0, ctx, msg, msgOff, msgLen, sig, sigOff); + break; + } + case Ed448.Algorithm.Ed448ph: + { + if (Ed448.PrehashSize != msgLen) + throw new ArgumentException("msgLen"); + + Ed448.SignPrehash(data, 0, pk, 0, ctx, msg, msgOff, sig, sigOff); + break; + } + default: + { + throw new ArgumentException("algorithm"); + } + } + } + } +} diff --git a/crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs new file mode 100644 index 000000000..d7faac246 --- /dev/null +++ b/crypto/src/crypto/parameters/Ed448PublicKeyParameters.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class Ed448PublicKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = Ed448.PublicKeySize; + + private readonly byte[] data = new byte[KeySize]; + + public Ed448PublicKeyParameters(byte[] buf, int off) + : base(false) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public Ed448PublicKeyParameters(Stream input) + : base(false) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of Ed448 public key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + } +} diff --git a/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs new file mode 100644 index 000000000..09972c7a2 --- /dev/null +++ b/crypto/src/crypto/parameters/X25519KeyGenerationParameters.cs @@ -0,0 +1,15 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class X25519KeyGenerationParameters + : KeyGenerationParameters + { + public X25519KeyGenerationParameters(SecureRandom random) + : base(random, 256) + { + } + } +} diff --git a/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs new file mode 100644 index 000000000..c25ab9364 --- /dev/null +++ b/crypto/src/crypto/parameters/X25519PrivateKeyParameters.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc7748; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class X25519PrivateKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = X25519.ScalarSize; + public static readonly int SecretSize = X25519.PointSize; + + private readonly byte[] data = new byte[KeySize]; + + public X25519PrivateKeyParameters(SecureRandom random) + : base(true) + { + random.NextBytes(data); + } + + public X25519PrivateKeyParameters(byte[] buf, int off) + : base(true) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public X25519PrivateKeyParameters(Stream input) + : base(true) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of X25519 private key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + + public X25519PublicKeyParameters GeneratePublicKey() + { + byte[] publicKey = new byte[X25519.PointSize]; + X25519.ScalarMultBase(data, 0, publicKey, 0); + return new X25519PublicKeyParameters(publicKey, 0); + } + + public void GenerateSecret(X25519PublicKeyParameters publicKey, byte[] buf, int off) + { + byte[] encoded = new byte[X25519.PointSize]; + publicKey.Encode(encoded, 0); + X25519.ScalarMult(data, 0, encoded, 0, buf, off); + } + } +} diff --git a/crypto/src/crypto/parameters/X25519PublicKeyParameters.cs b/crypto/src/crypto/parameters/X25519PublicKeyParameters.cs new file mode 100644 index 000000000..7df5f624d --- /dev/null +++ b/crypto/src/crypto/parameters/X25519PublicKeyParameters.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc7748; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class X25519PublicKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = X25519.PointSize; + + private readonly byte[] data = new byte[KeySize]; + + public X25519PublicKeyParameters(byte[] buf, int off) + : base(false) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public X25519PublicKeyParameters(Stream input) + : base(false) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of X25519 public key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + } +} diff --git a/crypto/src/crypto/parameters/X448KeyGenerationParameters.cs b/crypto/src/crypto/parameters/X448KeyGenerationParameters.cs new file mode 100644 index 000000000..a7cb55844 --- /dev/null +++ b/crypto/src/crypto/parameters/X448KeyGenerationParameters.cs @@ -0,0 +1,15 @@ +using System; + +using Org.BouncyCastle.Security; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public class X448KeyGenerationParameters + : KeyGenerationParameters + { + public X448KeyGenerationParameters(SecureRandom random) + : base(random, 448) + { + } + } +} diff --git a/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs new file mode 100644 index 000000000..291eac10f --- /dev/null +++ b/crypto/src/crypto/parameters/X448PrivateKeyParameters.cs @@ -0,0 +1,62 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc7748; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class X448PrivateKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = X448.ScalarSize; + public static readonly int SecretSize = X448.PointSize; + + private readonly byte[] data = new byte[KeySize]; + + public X448PrivateKeyParameters(SecureRandom random) + : base(true) + { + random.NextBytes(data); + } + + public X448PrivateKeyParameters(byte[] buf, int off) + : base(true) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public X448PrivateKeyParameters(Stream input) + : base(true) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of X448 private key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + + public X448PublicKeyParameters GeneratePublicKey() + { + byte[] publicKey = new byte[X448.PointSize]; + X448.ScalarMultBase(data, 0, publicKey, 0); + return new X448PublicKeyParameters(publicKey, 0); + } + + public void GenerateSecret(X448PublicKeyParameters publicKey, byte[] buf, int off) + { + byte[] encoded = new byte[X448.PointSize]; + publicKey.Encode(encoded, 0); + X448.ScalarMult(data, 0, encoded, 0, buf, off); + } + } +} diff --git a/crypto/src/crypto/parameters/X448PublicKeyParameters.cs b/crypto/src/crypto/parameters/X448PublicKeyParameters.cs new file mode 100644 index 000000000..6c566ddf2 --- /dev/null +++ b/crypto/src/crypto/parameters/X448PublicKeyParameters.cs @@ -0,0 +1,40 @@ +using System; +using System.IO; + +using Org.BouncyCastle.Math.EC.Rfc7748; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.Utilities.IO; + +namespace Org.BouncyCastle.Crypto.Parameters +{ + public sealed class X448PublicKeyParameters + : AsymmetricKeyParameter + { + public static readonly int KeySize = X448.PointSize; + + private readonly byte[] data = new byte[KeySize]; + + public X448PublicKeyParameters(byte[] buf, int off) + : base(false) + { + Array.Copy(buf, off, data, 0, KeySize); + } + + public X448PublicKeyParameters(Stream input) + : base(false) + { + if (KeySize != Streams.ReadFully(input, data)) + throw new EndOfStreamException("EOF encountered in middle of X448 public key"); + } + + public void Encode(byte[] buf, int off) + { + Array.Copy(data, 0, buf, off, KeySize); + } + + public byte[] GetEncoded() + { + return Arrays.Clone(data); + } + } +} diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs new file mode 100644 index 000000000..904450ed1 --- /dev/null +++ b/crypto/src/crypto/signers/Ed25519Signer.cs @@ -0,0 +1,128 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class Ed25519Signer + : ISigner + { + private readonly Buffer buffer = new Buffer(); + + private bool forSigning; + private Ed25519PrivateKeyParameters privateKey; + private Ed25519PublicKeyParameters publicKey; + + public Ed25519Signer() + { + } + + public virtual string AlgorithmName + { + get { return "Ed25519"; } + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + this.forSigning = forSigning; + + if (forSigning) + { + // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters? + + this.privateKey = (Ed25519PrivateKeyParameters)parameters; + this.publicKey = privateKey.GeneratePublicKey(); + } + else + { + this.privateKey = null; + this.publicKey = (Ed25519PublicKeyParameters)parameters; + } + + Reset(); + } + + public virtual void Update(byte b) + { + buffer.WriteByte(b); + } + + public virtual void BlockUpdate(byte[] buf, int off, int len) + { + buffer.Write(buf, off, len); + } + + public virtual byte[] GenerateSignature() + { + if (!forSigning) + throw new InvalidOperationException("Ed25519Signer not initialised for signature generation."); + + return buffer.GenerateSignature(privateKey, publicKey); + } + + public virtual bool VerifySignature(byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("Ed25519Signer not initialised for verification"); + + return buffer.VerifySignature(publicKey, signature); + } + + public virtual void Reset() + { + buffer.Reset(); + } + + private class Buffer : MemoryStream + { + [MethodImpl(MethodImplOptions.Synchronized)] + internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey) + { +#if PORTABLE + byte[] buf = ToArray(); + int count = buf.Length; +#else + byte[] buf = GetBuffer(); + int count = (int)Position; +#endif + byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize]; + privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0); + Reset(); + return signature; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] signature) + { +#if PORTABLE + byte[] buf = ToArray(); + int count = buf.Length; +#else + byte[] buf = GetBuffer(); + int count = (int)Position; +#endif + byte[] pk = publicKey.GetEncoded(); + bool result = Ed25519.Verify(signature, 0, pk, 0, buf, 0, count); + Reset(); + return result; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal void Reset() + { +#if PORTABLE + this.Position = 0L; + + // TODO Clear using Write method +#else + Array.Clear(GetBuffer(), 0, (int)Position); +#endif + this.Position = 0L; + } + } + } +} diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs new file mode 100644 index 000000000..e9c2eca44 --- /dev/null +++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs @@ -0,0 +1,130 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class Ed25519ctxSigner + : ISigner + { + private readonly Buffer buffer = new Buffer(); + private readonly byte[] context; + + private bool forSigning; + private Ed25519PrivateKeyParameters privateKey; + private Ed25519PublicKeyParameters publicKey; + + public Ed25519ctxSigner(byte[] context) + { + this.context = Arrays.Clone(context); + } + + public virtual string AlgorithmName + { + get { return "Ed25519ctx"; } + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + this.forSigning = forSigning; + + if (forSigning) + { + // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters? + + this.privateKey = (Ed25519PrivateKeyParameters)parameters; + this.publicKey = privateKey.GeneratePublicKey(); + } + else + { + this.privateKey = null; + this.publicKey = (Ed25519PublicKeyParameters)parameters; + } + + Reset(); + } + + public virtual void Update(byte b) + { + buffer.WriteByte(b); + } + + public virtual void BlockUpdate(byte[] buf, int off, int len) + { + buffer.Write(buf, off, len); + } + + public virtual byte[] GenerateSignature() + { + if (!forSigning) + throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation."); + + return buffer.GenerateSignature(privateKey, publicKey, context); + } + + public virtual bool VerifySignature(byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("Ed25519ctxSigner not initialised for verification"); + + return buffer.VerifySignature(publicKey, context, signature); + } + + public virtual void Reset() + { + buffer.Reset(); + } + + private class Buffer : MemoryStream + { + [MethodImpl(MethodImplOptions.Synchronized)] + internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx) + { +#if PORTABLE + byte[] buf = ToArray(); + int count = buf.Length; +#else + byte[] buf = GetBuffer(); + int count = (int)Position; +#endif + byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize]; + privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0); + Reset(); + return signature; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal bool VerifySignature(Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] signature) + { +#if PORTABLE + byte[] buf = ToArray(); + int count = buf.Length; +#else + byte[] buf = GetBuffer(); + int count = (int)Position; +#endif + byte[] pk = publicKey.GetEncoded(); + bool result = Ed25519.Verify(signature, 0, pk, 0, ctx, buf, 0, count); + Reset(); + return result; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal void Reset() + { +#if PORTABLE + this.Position = 0L; + + // TODO Clear using Write method +#else + Array.Clear(GetBuffer(), 0, (int)Position); +#endif + this.Position = 0L; + } + } + } +} diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs new file mode 100644 index 000000000..0d3de96f3 --- /dev/null +++ b/crypto/src/crypto/signers/Ed25519phSigner.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class Ed25519phSigner + : ISigner + { + private readonly IDigest prehash = Ed25519.CreatePrehash(); + private readonly byte[] context; + + private bool forSigning; + private Ed25519PrivateKeyParameters privateKey; + private Ed25519PublicKeyParameters publicKey; + + public Ed25519phSigner(byte[] context) + { + this.context = Arrays.Clone(context); + } + + public virtual string AlgorithmName + { + get { return "Ed25519ph"; } + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + this.forSigning = forSigning; + + if (forSigning) + { + // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters? + + this.privateKey = (Ed25519PrivateKeyParameters)parameters; + this.publicKey = privateKey.GeneratePublicKey(); + } + else + { + this.privateKey = null; + this.publicKey = (Ed25519PublicKeyParameters)parameters; + } + + Reset(); + } + + public virtual void Update(byte b) + { + prehash.Update(b); + } + + public virtual void BlockUpdate(byte[] buf, int off, int len) + { + prehash.BlockUpdate(buf, off, len); + } + + public virtual byte[] GenerateSignature() + { + if (!forSigning) + throw new InvalidOperationException("Ed25519phSigner not initialised for signature generation."); + + byte[] msg = new byte[Ed25519.PrehashSize]; + if (Ed25519.PrehashSize != prehash.DoFinal(msg, 0)) + throw new InvalidOperationException("Prehash digest failed"); + + byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize]; + privateKey.Sign(Ed25519.Algorithm.Ed25519ph, publicKey, context, msg, 0, Ed25519.PrehashSize, signature, 0); + return signature; + } + + public virtual bool VerifySignature(byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("Ed25519phSigner not initialised for verification"); + + byte[] pk = publicKey.GetEncoded(); + return Ed25519.VerifyPrehash(signature, 0, pk, 0, context, prehash); + } + + public void Reset() + { + prehash.Reset(); + } + } +} diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs new file mode 100644 index 000000000..c01d84b4d --- /dev/null +++ b/crypto/src/crypto/signers/Ed448Signer.cs @@ -0,0 +1,130 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class Ed448Signer + : ISigner + { + private readonly Buffer buffer = new Buffer(); + private readonly byte[] context; + + private bool forSigning; + private Ed448PrivateKeyParameters privateKey; + private Ed448PublicKeyParameters publicKey; + + public Ed448Signer(byte[] context) + { + this.context = Arrays.Clone(context); + } + + public virtual string AlgorithmName + { + get { return "Ed448"; } + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + this.forSigning = forSigning; + + if (forSigning) + { + // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters? + + this.privateKey = (Ed448PrivateKeyParameters)parameters; + this.publicKey = privateKey.GeneratePublicKey(); + } + else + { + this.privateKey = null; + this.publicKey = (Ed448PublicKeyParameters)parameters; + } + + Reset(); + } + + public virtual void Update(byte b) + { + buffer.WriteByte(b); + } + + public virtual void BlockUpdate(byte[] buf, int off, int len) + { + buffer.Write(buf, off, len); + } + + public virtual byte[] GenerateSignature() + { + if (!forSigning) + throw new InvalidOperationException("Ed448Signer not initialised for signature generation."); + + return buffer.GenerateSignature(privateKey, publicKey, context); + } + + public virtual bool VerifySignature(byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("Ed448Signer not initialised for verification"); + + return buffer.VerifySignature(publicKey, context, signature); + } + + public virtual void Reset() + { + buffer.Reset(); + } + + private class Buffer : MemoryStream + { + [MethodImpl(MethodImplOptions.Synchronized)] + internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx) + { +#if PORTABLE + byte[] buf = ToArray(); + int count = buf.Length; +#else + byte[] buf = GetBuffer(); + int count = (int)Position; +#endif + byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize]; + privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0); + Reset(); + return signature; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal bool VerifySignature(Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] signature) + { +#if PORTABLE + byte[] buf = ToArray(); + int count = buf.Length; +#else + byte[] buf = GetBuffer(); + int count = (int)Position; +#endif + byte[] pk = publicKey.GetEncoded(); + bool result = Ed448.Verify(signature, 0, pk, 0, ctx, buf, 0, count); + Reset(); + return result; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal void Reset() + { +#if PORTABLE + this.Position = 0L; + + // TODO Clear using Write method +#else + Array.Clear(GetBuffer(), 0, (int)Position); +#endif + this.Position = 0L; + } + } + } +} diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs new file mode 100644 index 000000000..50d0a0154 --- /dev/null +++ b/crypto/src/crypto/signers/Ed448phSigner.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; + +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Signers +{ + public class Ed448phSigner + : ISigner + { + private readonly IXof prehash = Ed448.CreatePrehash(); + private readonly byte[] context; + + private bool forSigning; + private Ed448PrivateKeyParameters privateKey; + private Ed448PublicKeyParameters publicKey; + + public Ed448phSigner(byte[] context) + { + this.context = Arrays.Clone(context); + } + + public virtual string AlgorithmName + { + get { return "Ed448ph"; } + } + + public virtual void Init(bool forSigning, ICipherParameters parameters) + { + this.forSigning = forSigning; + + if (forSigning) + { + // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters? + + this.privateKey = (Ed448PrivateKeyParameters)parameters; + this.publicKey = privateKey.GeneratePublicKey(); + } + else + { + this.privateKey = null; + this.publicKey = (Ed448PublicKeyParameters)parameters; + } + + Reset(); + } + + public virtual void Update(byte b) + { + prehash.Update(b); + } + + public virtual void BlockUpdate(byte[] buf, int off, int len) + { + prehash.BlockUpdate(buf, off, len); + } + + public virtual byte[] GenerateSignature() + { + if (!forSigning) + throw new InvalidOperationException("Ed448phSigner not initialised for signature generation."); + + byte[] msg = new byte[Ed448.PrehashSize]; + if (Ed448.PrehashSize != prehash.DoFinal(msg, 0, Ed448.PrehashSize)) + throw new InvalidOperationException("Prehash digest failed"); + + byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize]; + privateKey.Sign(Ed448.Algorithm.Ed448ph, publicKey, context, msg, 0, Ed448.PrehashSize, signature, 0); + return signature; + } + + public virtual bool VerifySignature(byte[] signature) + { + if (forSigning) + throw new InvalidOperationException("Ed448phSigner not initialised for verification"); + + byte[] pk = publicKey.GetEncoded(); + return Ed448.VerifyPrehash(signature, 0, pk, 0, context, prehash); + } + + public void Reset() + { + prehash.Reset(); + } + } +} diff --git a/crypto/src/math/ec/rfc8032/Ed25519.cs b/crypto/src/math/ec/rfc8032/Ed25519.cs index adb56ca9b..0b0e649d7 100644 --- a/crypto/src/math/ec/rfc8032/Ed25519.cs +++ b/crypto/src/math/ec/rfc8032/Ed25519.cs @@ -12,6 +12,13 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 { public abstract class Ed25519 { + public enum Algorithm + { + Ed25519 = 0, + Ed25519ctx = 1, + Ed25519ph = 2, + } + private const long M28L = 0x0FFFFFFFL; private const long M32L = 0xFFFFFFFFL; diff --git a/crypto/src/math/ec/rfc8032/Ed448.cs b/crypto/src/math/ec/rfc8032/Ed448.cs index c1c0788a7..f12aa0807 100644 --- a/crypto/src/math/ec/rfc8032/Ed448.cs +++ b/crypto/src/math/ec/rfc8032/Ed448.cs @@ -12,6 +12,12 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032 { public abstract class Ed448 { + public enum Algorithm + { + Ed448 = 0, + Ed448ph = 1, + } + private const ulong M26UL = 0x03FFFFFFUL; private const ulong M28UL = 0x0FFFFFFFUL; diff --git a/crypto/src/pkcs/PrivateKeyInfoFactory.cs b/crypto/src/pkcs/PrivateKeyInfoFactory.cs index a349a11d2..69eb3fa67 100644 --- a/crypto/src/pkcs/PrivateKeyInfoFactory.cs +++ b/crypto/src/pkcs/PrivateKeyInfoFactory.cs @@ -2,6 +2,7 @@ using System; 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; @@ -22,59 +23,68 @@ namespace Org.BouncyCastle.Pkcs } public static PrivateKeyInfo CreatePrivateKeyInfo( - AsymmetricKeyParameter key) + AsymmetricKeyParameter privateKey) { - if (key == null) - throw new ArgumentNullException("key"); - if (!key.IsPrivate) - throw new ArgumentException("Public key passed - private key expected", "key"); + return CreatePrivateKeyInfo(privateKey, null); + } + + /** + * Create a PrivateKeyInfo representation of a private key with attributes. + * + * @param privateKey the key to be encoded into the info object. + * @param attributes the set of attributes to be included. + * @return the appropriate PrivateKeyInfo + * @throws java.io.IOException on an error encoding the key + */ + public static PrivateKeyInfo CreatePrivateKeyInfo(AsymmetricKeyParameter privateKey, Asn1Set attributes) + { + if (privateKey == null) + throw new ArgumentNullException("privateKey"); + if (!privateKey.IsPrivate) + throw new ArgumentException("Public key passed - private key expected", "privateKey"); - if (key is ElGamalPrivateKeyParameters) + if (privateKey is ElGamalPrivateKeyParameters) { - ElGamalPrivateKeyParameters _key = (ElGamalPrivateKeyParameters)key; + ElGamalPrivateKeyParameters _key = (ElGamalPrivateKeyParameters)privateKey; + ElGamalParameters egp = _key.Parameters; return new PrivateKeyInfo( - new AlgorithmIdentifier( - OiwObjectIdentifiers.ElGamalAlgorithm, - new ElGamalParameter( - _key.Parameters.P, - _key.Parameters.G).ToAsn1Object()), - new DerInteger(_key.X)); + new AlgorithmIdentifier(OiwObjectIdentifiers.ElGamalAlgorithm, new ElGamalParameter(egp.P, egp.G).ToAsn1Object()), + new DerInteger(_key.X), + attributes); } - if (key is DsaPrivateKeyParameters) + if (privateKey is DsaPrivateKeyParameters) { - DsaPrivateKeyParameters _key = (DsaPrivateKeyParameters)key; + DsaPrivateKeyParameters _key = (DsaPrivateKeyParameters)privateKey; + DsaParameters dp = _key.Parameters; return new PrivateKeyInfo( - new AlgorithmIdentifier( - X9ObjectIdentifiers.IdDsa, - new DsaParameter( - _key.Parameters.P, - _key.Parameters.Q, - _key.Parameters.G).ToAsn1Object()), - new DerInteger(_key.X)); + new AlgorithmIdentifier(X9ObjectIdentifiers.IdDsa, new DsaParameter(dp.P, dp.Q, dp.G).ToAsn1Object()), + new DerInteger(_key.X), + attributes); } - if (key is DHPrivateKeyParameters) + if (privateKey is DHPrivateKeyParameters) { - DHPrivateKeyParameters _key = (DHPrivateKeyParameters)key; + DHPrivateKeyParameters _key = (DHPrivateKeyParameters)privateKey; DHParameter p = new DHParameter( _key.Parameters.P, _key.Parameters.G, _key.Parameters.L); return new PrivateKeyInfo( new AlgorithmIdentifier(_key.AlgorithmOid, p.ToAsn1Object()), - new DerInteger(_key.X)); + new DerInteger(_key.X), + attributes); } - if (key is RsaKeyParameters) + if (privateKey is RsaKeyParameters) { AlgorithmIdentifier algID = new AlgorithmIdentifier( PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance); RsaPrivateKeyStructure keyStruct; - if (key is RsaPrivateCrtKeyParameters) + if (privateKey is RsaPrivateCrtKeyParameters) { - RsaPrivateCrtKeyParameters _key = (RsaPrivateCrtKeyParameters)key; + RsaPrivateCrtKeyParameters _key = (RsaPrivateCrtKeyParameters)privateKey; keyStruct = new RsaPrivateKeyStructure( _key.Modulus, @@ -88,7 +98,7 @@ namespace Org.BouncyCastle.Pkcs } else { - RsaKeyParameters _key = (RsaKeyParameters) key; + RsaKeyParameters _key = (RsaKeyParameters) privateKey; keyStruct = new RsaPrivateKeyStructure( _key.Modulus, @@ -101,12 +111,12 @@ namespace Org.BouncyCastle.Pkcs BigInteger.Zero); } - return new PrivateKeyInfo(algID, keyStruct.ToAsn1Object()); + return new PrivateKeyInfo(algID, keyStruct.ToAsn1Object(), attributes); } - if (key is ECPrivateKeyParameters) + if (privateKey is ECPrivateKeyParameters) { - ECPrivateKeyParameters priv = (ECPrivateKeyParameters)key; + ECPrivateKeyParameters priv = (ECPrivateKeyParameters)privateKey; ECDomainParameters dp = priv.Parameters; int orderBitLength = dp.N.BitLength; @@ -145,12 +155,12 @@ namespace Org.BouncyCastle.Pkcs algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962); } - return new PrivateKeyInfo(algID, ec); + return new PrivateKeyInfo(algID, ec, attributes); } - if (key is Gost3410PrivateKeyParameters) + if (privateKey is Gost3410PrivateKeyParameters) { - Gost3410PrivateKeyParameters _key = (Gost3410PrivateKeyParameters)key; + Gost3410PrivateKeyParameters _key = (Gost3410PrivateKeyParameters)privateKey; if (_key.PublicKeyParamSet == null) throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); @@ -170,10 +180,42 @@ namespace Org.BouncyCastle.Pkcs CryptoProObjectIdentifiers.GostR3410x94, algParams.ToAsn1Object()); - return new PrivateKeyInfo(algID, new DerOctetString(keyBytes)); + return new PrivateKeyInfo(algID, new DerOctetString(keyBytes), attributes); + } + + if (privateKey is X448PrivateKeyParameters) + { + X448PrivateKeyParameters key = (X448PrivateKeyParameters)privateKey; + + return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448), + new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded()); + } + + if (privateKey is X25519PrivateKeyParameters) + { + X25519PrivateKeyParameters key = (X25519PrivateKeyParameters)privateKey; + + return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519), + new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded()); + } + + if (privateKey is Ed448PrivateKeyParameters) + { + Ed448PrivateKeyParameters key = (Ed448PrivateKeyParameters)privateKey; + + return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448), + new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded()); + } + + if (privateKey is Ed25519PrivateKeyParameters) + { + Ed25519PrivateKeyParameters key = (Ed25519PrivateKeyParameters)privateKey; + + return new PrivateKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), + new DerOctetString(key.GetEncoded()), attributes, key.GeneratePublicKey().GetEncoded()); } - throw new ArgumentException("Class provided is not convertible: " + Platform.GetTypeName(key)); + throw new ArgumentException("Class provided is not convertible: " + Platform.GetTypeName(privateKey)); } public static PrivateKeyInfo CreatePrivateKeyInfo( 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)); diff --git a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs index 7614321d4..fca5da3f5 100644 --- a/crypto/src/x509/SubjectPublicKeyInfoFactory.cs +++ b/crypto/src/x509/SubjectPublicKeyInfoFactory.cs @@ -3,6 +3,7 @@ using System; using Org.BouncyCastle.Crypto.Parameters; 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.X509; @@ -26,20 +27,20 @@ namespace Org.BouncyCastle.X509 /// <summary> /// Create a Subject Public Key Info object for a given public key. /// </summary> - /// <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param> + /// <param name="publicKey">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param> /// <returns>A subject public key info object.</returns> /// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception> public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo( - AsymmetricKeyParameter key) + AsymmetricKeyParameter publicKey) { - if (key == null) - throw new ArgumentNullException("key"); - if (key.IsPrivate) - throw new ArgumentException("Private key passed - public key expected.", "key"); + if (publicKey == null) + throw new ArgumentNullException("publicKey"); + if (publicKey.IsPrivate) + throw new ArgumentException("Private key passed - public key expected.", "publicKey"); - if (key is ElGamalPublicKeyParameters) + if (publicKey is ElGamalPublicKeyParameters) { - ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key; + ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)publicKey; ElGamalParameters kp = _key.Parameters; SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( @@ -51,9 +52,9 @@ namespace Org.BouncyCastle.X509 return info; } - if (key is DsaPublicKeyParameters) + if (publicKey is DsaPublicKeyParameters) { - DsaPublicKeyParameters _key = (DsaPublicKeyParameters) key; + DsaPublicKeyParameters _key = (DsaPublicKeyParameters) publicKey; DsaParameters kp = _key.Parameters; Asn1Encodable ae = kp == null ? null @@ -64,9 +65,9 @@ namespace Org.BouncyCastle.X509 new DerInteger(_key.Y)); } - if (key is DHPublicKeyParameters) + if (publicKey is DHPublicKeyParameters) { - DHPublicKeyParameters _key = (DHPublicKeyParameters) key; + DHPublicKeyParameters _key = (DHPublicKeyParameters) publicKey; DHParameters kp = _key.Parameters; SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( @@ -78,9 +79,9 @@ namespace Org.BouncyCastle.X509 return info; } // End of DH - if (key is RsaKeyParameters) + if (publicKey is RsaKeyParameters) { - RsaKeyParameters _key = (RsaKeyParameters) key; + RsaKeyParameters _key = (RsaKeyParameters) publicKey; SubjectPublicKeyInfo info = new SubjectPublicKeyInfo( new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance), @@ -89,9 +90,9 @@ namespace Org.BouncyCastle.X509 return info; } // End of RSA. - if (key is ECPublicKeyParameters) + if (publicKey is ECPublicKeyParameters) { - ECPublicKeyParameters _key = (ECPublicKeyParameters) key; + ECPublicKeyParameters _key = (ECPublicKeyParameters) publicKey; if (_key.AlgorithmName == "ECGOST3410") { @@ -139,9 +140,9 @@ namespace Org.BouncyCastle.X509 } } // End of EC - if (key is Gost3410PublicKeyParameters) + if (publicKey is Gost3410PublicKeyParameters) { - Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) key; + Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) publicKey; if (_key.PublicKeyParamSet == null) throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set"); @@ -164,7 +165,35 @@ namespace Org.BouncyCastle.X509 return new SubjectPublicKeyInfo(algID, new DerOctetString(keyBytes)); } - throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(key)); + if (publicKey is X448PublicKeyParameters) + { + X448PublicKeyParameters key = (X448PublicKeyParameters)publicKey; + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X448), key.GetEncoded()); + } + + if (publicKey is X25519PublicKeyParameters) + { + X25519PublicKeyParameters key = (X25519PublicKeyParameters)publicKey; + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_X25519), key.GetEncoded()); + } + + if (publicKey is Ed448PublicKeyParameters) + { + Ed448PublicKeyParameters key = (Ed448PublicKeyParameters)publicKey; + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed448), key.GetEncoded()); + } + + if (publicKey is Ed25519PublicKeyParameters) + { + Ed25519PublicKeyParameters key = (Ed25519PublicKeyParameters)publicKey; + + return new SubjectPublicKeyInfo(new AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519), key.GetEncoded()); + } + + throw new ArgumentException("Class provided no convertible: " + Platform.GetTypeName(publicKey)); } private static void ExtractBytes( diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj index 5f0e7af57..bb046c2b6 100644 --- a/crypto/test/UnitTests.csproj +++ b/crypto/test/UnitTests.csproj @@ -101,6 +101,7 @@ <Compile Include="src\asn1\test\ParseTest.cs" /> <Compile Include="src\asn1\test\ParsingTest.cs" /> <Compile Include="src\asn1\test\PersonalDataUnitTest.cs" /> + <Compile Include="src\asn1\test\PrivateKeyInfoTest.cs" /> <Compile Include="src\asn1\test\ProcurationSyntaxUnitTest.cs" /> <Compile Include="src\asn1\test\ProfessionInfoUnitTest.cs" /> <Compile Include="src\asn1\test\QCStatementUnitTest.cs" /> @@ -186,6 +187,8 @@ <Compile Include="src\crypto\test\ECIESTest.cs" /> <Compile Include="src\crypto\test\ECNRTest.cs" /> <Compile Include="src\crypto\test\ECTest.cs" /> + <Compile Include="src\crypto\test\Ed25519Test.cs" /> + <Compile Include="src\crypto\test\Ed448Test.cs" /> <Compile Include="src\crypto\test\ElGamalTest.cs" /> <Compile Include="src\crypto\test\EqualsHashCodeTest.cs" /> <Compile Include="src\crypto\test\GCMTest.cs" /> @@ -284,6 +287,8 @@ <Compile Include="src\crypto\test\VMPCMacTest.cs" /> <Compile Include="src\crypto\test\VMPCTest.cs" /> <Compile Include="src\crypto\test\WhirlpoolDigestTest.cs" /> + <Compile Include="src\crypto\test\X25519Test.cs" /> + <Compile Include="src\crypto\test\X448Test.cs" /> <Compile Include="src\crypto\test\X931SignerTest.cs" /> <Compile Include="src\crypto\test\XSalsa20Test.cs" /> <Compile Include="src\crypto\test\XTEATest.cs" /> diff --git a/crypto/test/src/asn1/test/PrivateKeyInfoTest.cs b/crypto/test/src/asn1/test/PrivateKeyInfoTest.cs new file mode 100644 index 000000000..eb17a54c3 --- /dev/null +++ b/crypto/test/src/asn1/test/PrivateKeyInfoTest.cs @@ -0,0 +1,60 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.Pkcs; +using Org.BouncyCastle.Utilities.Encoders; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class PrivateKeyInfoTest + : SimpleTest + { + private static readonly byte[] priv = Base64.Decode( + "MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC"); + + private static readonly byte[] privWithPub = Base64.Decode( + "MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC" + + "oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB" + + "Z9w7lshQhqowtrbLDFw4rXAxZuE="); + + public override string Name + { + get { return "PrivateKeyInfoTest"; } + } + + public override void PerformTest() + { + PrivateKeyInfo privInfo1 = PrivateKeyInfo.GetInstance(priv); + + IsTrue(!privInfo1.HasPublicKey); + + PrivateKeyInfo privInfo2 = new PrivateKeyInfo(privInfo1.PrivateKeyAlgorithm, privInfo1.ParsePrivateKey()); + + IsTrue("enc 1 failed", AreEqual(priv, privInfo2.GetEncoded())); + + privInfo1 = PrivateKeyInfo.GetInstance(privWithPub); + + IsTrue(privInfo1.HasPublicKey); + + privInfo2 = new PrivateKeyInfo(privInfo1.PrivateKeyAlgorithm, privInfo1.ParsePrivateKey(), privInfo1.Attributes, privInfo1.PublicKeyData.GetOctets()); + + IsTrue("enc 2 failed", AreEqual(privWithPub, privInfo2.GetEncoded())); + } + + public static void Main(string[] args) + { + RunTest(new PrivateKeyInfoTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/RegressionTest.cs b/crypto/test/src/asn1/test/RegressionTest.cs index 873ab4396..eeca9ccd0 100644 --- a/crypto/test/src/asn1/test/RegressionTest.cs +++ b/crypto/test/src/asn1/test/RegressionTest.cs @@ -51,6 +51,7 @@ namespace Org.BouncyCastle.Asn1.Tests new Pkcs10Test(), new Pkcs12Test(), new PkiFailureInfoTest(), + new PrivateKeyInfoTest(), new ProcurationSyntaxUnitTest(), new ProfessionInfoUnitTest(), new QCStatementUnitTest(), diff --git a/crypto/test/src/crypto/test/Ed25519Test.cs b/crypto/test/src/crypto/test/Ed25519Test.cs new file mode 100644 index 000000000..82e36d991 --- /dev/null +++ b/crypto/test/src/crypto/test/Ed25519Test.cs @@ -0,0 +1,111 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Ed25519Test + : SimpleTest + { + private static readonly SecureRandom Random = new SecureRandom(); + + public override string Name + { + get { return "Ed25519"; } + } + + public static void Main(string[] args) + { + RunTest(new Ed25519Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public override void PerformTest() + { + for (int i = 0; i < 10; ++i) + { + DoTestConsistency(Ed25519.Algorithm.Ed25519, null); + + byte[] context = RandomContext(Random.NextInt() & 255); + DoTestConsistency(Ed25519.Algorithm.Ed25519ctx, context); + DoTestConsistency(Ed25519.Algorithm.Ed25519ph, context); + } + } + + private ISigner CreateSigner(Ed25519.Algorithm algorithm, byte[] context) + { + switch (algorithm) + { + case Ed25519.Algorithm.Ed25519: + return new Ed25519Signer(); + case Ed25519.Algorithm.Ed25519ctx: + return new Ed25519ctxSigner(context); + case Ed25519.Algorithm.Ed25519ph: + return new Ed25519phSigner(context); + default: + throw new ArgumentException("algorithm"); + } + } + + private byte[] RandomContext(int length) + { + byte[] context = new byte[length]; + Random.NextBytes(context); + return context; + } + + private void DoTestConsistency(Ed25519.Algorithm algorithm, byte[] context) + { + Ed25519KeyPairGenerator kpg = new Ed25519KeyPairGenerator(); + kpg.Init(new Ed25519KeyGenerationParameters(Random)); + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + Ed25519PrivateKeyParameters privateKey = (Ed25519PrivateKeyParameters)kp.Private; + Ed25519PublicKeyParameters publicKey = (Ed25519PublicKeyParameters)kp.Public; + + byte[] msg = new byte[Random.NextInt() & 255]; + Random.NextBytes(msg); + + ISigner signer = CreateSigner(algorithm, context); + signer.Init(true, privateKey); + signer.BlockUpdate(msg, 0, msg.Length); + byte[] signature = signer.GenerateSignature(); + + ISigner verifier = CreateSigner(algorithm, context); + verifier.Init(false, publicKey); + verifier.BlockUpdate(msg, 0, msg.Length); + bool shouldVerify = verifier.VerifySignature(signature); + + if (!shouldVerify) + { + Fail("Ed25519(" + algorithm + ") signature failed to verify"); + } + + signature[Random.Next() % signature.Length] ^= (byte)(1 << (Random.NextInt() & 7)); + + verifier.Init(false, publicKey); + verifier.BlockUpdate(msg, 0, msg.Length); + bool shouldNotVerify = verifier.VerifySignature(signature); + + if (shouldNotVerify) + { + Fail("Ed25519(" + algorithm + ") bad signature incorrectly verified"); + } + } + } +} diff --git a/crypto/test/src/crypto/test/Ed448Test.cs b/crypto/test/src/crypto/test/Ed448Test.cs new file mode 100644 index 000000000..b035f554e --- /dev/null +++ b/crypto/test/src/crypto/test/Ed448Test.cs @@ -0,0 +1,107 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.Math.EC.Rfc8032; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class Ed448Test + : SimpleTest + { + private static readonly SecureRandom Random = new SecureRandom(); + + public override string Name + { + get { return "Ed448"; } + } + + public static void Main(string[] args) + { + RunTest(new Ed448Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public override void PerformTest() + { + for (int i = 0; i < 10; ++i) + { + byte[] context = RandomContext(Random.NextInt() & 255); + DoTestConsistency(Ed448.Algorithm.Ed448, context); + DoTestConsistency(Ed448.Algorithm.Ed448ph, context); + } + } + + private ISigner CreateSigner(Ed448.Algorithm algorithm, byte[] context) + { + switch (algorithm) + { + case Ed448.Algorithm.Ed448: + return new Ed448Signer(context); + case Ed448.Algorithm.Ed448ph: + return new Ed448phSigner(context); + default: + throw new ArgumentException("algorithm"); + } + } + + private byte[] RandomContext(int length) + { + byte[] context = new byte[length]; + Random.NextBytes(context); + return context; + } + + private void DoTestConsistency(Ed448.Algorithm algorithm, byte[] context) + { + Ed448KeyPairGenerator kpg = new Ed448KeyPairGenerator(); + kpg.Init(new Ed448KeyGenerationParameters(Random)); + + AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair(); + Ed448PrivateKeyParameters privateKey = (Ed448PrivateKeyParameters)kp.Private; + Ed448PublicKeyParameters publicKey = (Ed448PublicKeyParameters)kp.Public; + + byte[] msg = new byte[Random.NextInt() & 255]; + Random.NextBytes(msg); + + ISigner signer = CreateSigner(algorithm, context); + signer.Init(true, privateKey); + signer.BlockUpdate(msg, 0, msg.Length); + byte[] signature = signer.GenerateSignature(); + + ISigner verifier = CreateSigner(algorithm, context); + verifier.Init(false, publicKey); + verifier.BlockUpdate(msg, 0, msg.Length); + bool shouldVerify = verifier.VerifySignature(signature); + + if (!shouldVerify) + { + Fail("Ed448(" + algorithm + ") signature failed to verify"); + } + + signature[Random.Next() % signature.Length] ^= (byte)(1 << (Random.NextInt() & 7)); + + verifier.Init(false, publicKey); + verifier.BlockUpdate(msg, 0, msg.Length); + bool shouldNotVerify = verifier.VerifySignature(signature); + + if (shouldNotVerify) + { + Fail("Ed448(" + algorithm + ") bad signature incorrectly verified"); + } + } + } +} diff --git a/crypto/test/src/crypto/test/RegressionTest.cs b/crypto/test/src/crypto/test/RegressionTest.cs index 13fe23ecc..18aa62d97 100644 --- a/crypto/test/src/crypto/test/RegressionTest.cs +++ b/crypto/test/src/crypto/test/RegressionTest.cs @@ -133,6 +133,10 @@ namespace Org.BouncyCastle.Crypto.Tests new SM2EngineTest(), new SM2KeyExchangeTest(), new SM2SignerTest(), + new X25519Test(), + new X448Test(), + new Ed25519Test(), + new Ed448Test(), }; public static void Main(string[] args) diff --git a/crypto/test/src/crypto/test/X25519Test.cs b/crypto/test/src/crypto/test/X25519Test.cs new file mode 100644 index 000000000..29466e0c6 --- /dev/null +++ b/crypto/test/src/crypto/test/X25519Test.cs @@ -0,0 +1,69 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class X25519Test + : SimpleTest + { + private static readonly SecureRandom Random = new SecureRandom(); + + public override string Name + { + get { return "X25519"; } + } + + public static void Main(string[] args) + { + RunTest(new X25519Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public override void PerformTest() + { + for (int i = 0; i < 10; ++i) + { + DoTestAgreement(); + } + } + + private void DoTestAgreement() + { + IAsymmetricCipherKeyPairGenerator kpGen = new X25519KeyPairGenerator(); + kpGen.Init(new X25519KeyGenerationParameters(Random)); + + AsymmetricCipherKeyPair kpA = kpGen.GenerateKeyPair(); + AsymmetricCipherKeyPair kpB = kpGen.GenerateKeyPair(); + + X25519Agreement agreeA = new X25519Agreement(); + agreeA.Init(kpA.Private); + byte[] secretA = new byte[agreeA.AgreementSize]; + agreeA.CalculateAgreement(kpB.Public, secretA, 0); + + X25519Agreement agreeB = new X25519Agreement(); + agreeB.Init(kpB.Private); + byte[] secretB = new byte[agreeB.AgreementSize]; + agreeB.CalculateAgreement(kpA.Public, secretB, 0); + + if (!AreEqual(secretA, secretB)) + { + Fail("X25519 agreement failed"); + } + } + } +} diff --git a/crypto/test/src/crypto/test/X448Test.cs b/crypto/test/src/crypto/test/X448Test.cs new file mode 100644 index 000000000..5d4b14b63 --- /dev/null +++ b/crypto/test/src/crypto/test/X448Test.cs @@ -0,0 +1,69 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Crypto.Agreement; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities.Test; + +namespace Org.BouncyCastle.Crypto.Tests +{ + [TestFixture] + public class X448Test + : SimpleTest + { + private static readonly SecureRandom Random = new SecureRandom(); + + public override string Name + { + get { return "X448"; } + } + + public static void Main(string[] args) + { + RunTest(new X448Test()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + + public override void PerformTest() + { + for (int i = 0; i < 10; ++i) + { + DoTestAgreement(); + } + } + + private void DoTestAgreement() + { + IAsymmetricCipherKeyPairGenerator kpGen = new X448KeyPairGenerator(); + kpGen.Init(new X448KeyGenerationParameters(Random)); + + AsymmetricCipherKeyPair kpA = kpGen.GenerateKeyPair(); + AsymmetricCipherKeyPair kpB = kpGen.GenerateKeyPair(); + + X448Agreement agreeA = new X448Agreement(); + agreeA.Init(kpA.Private); + byte[] secretA = new byte[agreeA.AgreementSize]; + agreeA.CalculateAgreement(kpB.Public, secretA, 0); + + X448Agreement agreeB = new X448Agreement(); + agreeB.Init(kpB.Private); + byte[] secretB = new byte[agreeB.AgreementSize]; + agreeB.CalculateAgreement(kpA.Public, secretB, 0); + + if (!AreEqual(secretA, secretB)) + { + Fail("X448 agreement failed"); + } + } + } +} diff --git a/crypto/test/src/math/ec/rfc8032/test/Ed25519Test.cs b/crypto/test/src/math/ec/rfc8032/test/Ed25519Test.cs index 5a42daeae..8a61609af 100644 --- a/crypto/test/src/math/ec/rfc8032/test/Ed25519Test.cs +++ b/crypto/test/src/math/ec/rfc8032/test/Ed25519Test.cs @@ -36,7 +36,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests Random.NextBytes(sk); Ed25519.GeneratePublicKey(sk, 0, pk, 0); - int mLen = Random.Next() & 255; + int mLen = Random.NextInt() & 255; Ed25519.Sign(sk, 0, m, 0, mLen, sig1, 0); Ed25519.Sign(sk, 0, pk, 0, m, 0, mLen, sig2, 0); @@ -59,7 +59,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests { byte[] sk = new byte[Ed25519.SecretKeySize]; byte[] pk = new byte[Ed25519.PublicKeySize]; - byte[] ctx = new byte[Random.Next() & 7]; + byte[] ctx = new byte[Random.NextInt() & 7]; byte[] m = new byte[255]; byte[] sig1 = new byte[Ed25519.SignatureSize]; byte[] sig2 = new byte[Ed25519.SignatureSize]; @@ -72,7 +72,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests Random.NextBytes(sk); Ed25519.GeneratePublicKey(sk, 0, pk, 0); - int mLen = Random.Next() & 255; + int mLen = Random.NextInt() & 255; Ed25519.Sign(sk, 0, ctx, m, 0, mLen, sig1, 0); Ed25519.Sign(sk, 0, pk, 0, ctx, m, 0, mLen, sig2, 0); @@ -95,7 +95,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests { byte[] sk = new byte[Ed25519.SecretKeySize]; byte[] pk = new byte[Ed25519.PublicKeySize]; - byte[] ctx = new byte[Random.Next() & 7]; + byte[] ctx = new byte[Random.NextInt() & 7]; byte[] m = new byte[255]; byte[] ph = new byte[Ed25519.PrehashSize]; byte[] sig1 = new byte[Ed25519.SignatureSize]; @@ -109,7 +109,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests Random.NextBytes(sk); Ed25519.GeneratePublicKey(sk, 0, pk, 0); - int mLen = Random.Next() & 255; + int mLen = Random.NextInt() & 255; IDigest prehash = Ed25519.CreatePrehash(); prehash.BlockUpdate(m, 0, mLen); diff --git a/crypto/test/src/math/ec/rfc8032/test/Ed448Test.cs b/crypto/test/src/math/ec/rfc8032/test/Ed448Test.cs index 826f76345..cc8e82de0 100644 --- a/crypto/test/src/math/ec/rfc8032/test/Ed448Test.cs +++ b/crypto/test/src/math/ec/rfc8032/test/Ed448Test.cs @@ -25,7 +25,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests { byte[] sk = new byte[Ed448.SecretKeySize]; byte[] pk = new byte[Ed448.PublicKeySize]; - byte[] ctx = new byte[Random.Next() & 7]; + byte[] ctx = new byte[Random.NextInt() & 7]; byte[] m = new byte[255]; byte[] sig1 = new byte[Ed448.SignatureSize]; byte[] sig2 = new byte[Ed448.SignatureSize]; @@ -38,7 +38,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests Random.NextBytes(sk); Ed448.GeneratePublicKey(sk, 0, pk, 0); - int mLen = Random.Next() & 255; + int mLen = Random.NextInt() & 255; Ed448.Sign(sk, 0, ctx, m, 0, mLen, sig1, 0); Ed448.Sign(sk, 0, pk, 0, ctx, m, 0, mLen, sig2, 0); @@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests { byte[] sk = new byte[Ed448.SecretKeySize]; byte[] pk = new byte[Ed448.PublicKeySize]; - byte[] ctx = new byte[Random.Next() & 7]; + byte[] ctx = new byte[Random.NextInt() & 7]; byte[] m = new byte[255]; byte[] ph = new byte[Ed448.PrehashSize]; byte[] sig1 = new byte[Ed448.SignatureSize]; @@ -75,7 +75,7 @@ namespace Org.BouncyCastle.Math.EC.Rfc8032.Tests Random.NextBytes(sk); Ed448.GeneratePublicKey(sk, 0, pk, 0); - int mLen = Random.Next() & 255; + int mLen = Random.NextInt() & 255; IXof prehash = Ed448.CreatePrehash(); prehash.BlockUpdate(m, 0, mLen); diff --git a/crypto/test/src/security/test/TestSignerUtil.cs b/crypto/test/src/security/test/TestSignerUtil.cs index f2ee4b048..dc3c1c81b 100644 --- a/crypto/test/src/security/test/TestSignerUtil.cs +++ b/crypto/test/src/security/test/TestSignerUtil.cs @@ -94,6 +94,14 @@ namespace Org.BouncyCastle.Security.Tests AsymmetricCipherKeyPair ecGostPair = ecGostKpg.GenerateKeyPair(); + IAsymmetricCipherKeyPairGenerator ed25519Kpg = GeneratorUtilities.GetKeyPairGenerator("Ed25519"); + ed25519Kpg.Init(new Ed25519KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair ed25519Pair = ed25519Kpg.GenerateKeyPair(); + + IAsymmetricCipherKeyPairGenerator ed448Kpg = GeneratorUtilities.GetKeyPairGenerator("Ed448"); + ed448Kpg.Init(new Ed448KeyGenerationParameters(new SecureRandom())); + AsymmetricCipherKeyPair ed448Pair = ed448Kpg.GenerateKeyPair(); + // // GOST3410 parameters // @@ -147,6 +155,16 @@ namespace Org.BouncyCastle.Security.Tests signParams = ecGostPair.Private; verifyParams = ecGostPair.Public; } + else if (cipherName == "ED25519") + { + signParams = ed25519Pair.Private; + verifyParams = ed25519Pair.Public; + } + else if (cipherName == "ED448") + { + signParams = ed448Pair.Private; + verifyParams = ed448Pair.Public; + } else if (cipherName == "GOST3410") { signParams = gostPair.Private; |