summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2020-01-31 17:57:10 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2020-01-31 17:57:10 +0700
commit2ccd54b85c8157c146b96a751b8c2c08483d345e (patch)
tree4e30dc4ca5a34dcefa52e7c6e7cedd24eb99c90f
parentPort of X25519/X448 field updates from bc-java (diff)
downloadBouncyCastle.NET-ed25519-2ccd54b85c8157c146b96a751b8c2c08483d345e.tar.xz
EdDSA: guard against pub key mismatch
-rw-r--r--crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs34
-rw-r--r--crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs34
-rw-r--r--crypto/src/crypto/signers/Ed25519Signer.cs10
-rw-r--r--crypto/src/crypto/signers/Ed25519ctxSigner.cs10
-rw-r--r--crypto/src/crypto/signers/Ed25519phSigner.cs6
-rw-r--r--crypto/src/crypto/signers/Ed448Signer.cs10
-rw-r--r--crypto/src/crypto/signers/Ed448phSigner.cs6
7 files changed, 62 insertions, 48 deletions
diff --git a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
index 8046a0b1b..531bca0e9 100644
--- a/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed25519PrivateKeyParameters.cs
@@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         private readonly byte[] data = new byte[KeySize];
 
+        private Ed25519PublicKeyParameters cachedPublicKey;
+
         public Ed25519PrivateKeyParameters(SecureRandom random)
             : base(true)
         {
@@ -47,23 +49,33 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         public Ed25519PublicKeyParameters GeneratePublicKey()
         {
-            byte[] publicKey = new byte[Ed25519.PublicKeySize];
-            Ed25519.GeneratePublicKey(data, 0, publicKey, 0);
-            return new Ed25519PublicKeyParameters(publicKey, 0);
+            lock (data)
+            {
+                if (null == cachedPublicKey)
+                {
+                    byte[] publicKey = new byte[Ed25519.PublicKeySize];
+                    Ed25519.GeneratePublicKey(data, 0, publicKey, 0);
+                    cachedPublicKey = new Ed25519PublicKeyParameters(publicKey, 0);
+                }
+
+                return cachedPublicKey;
+            }
         }
 
+        [Obsolete("Use overload that doesn't take a public key")]
         public void Sign(Ed25519.Algorithm algorithm, Ed25519PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen,
             byte[] sig, int sigOff)
         {
+            Sign(algorithm, ctx, msg, msgOff, msgLen, sig, sigOff);
+        }
+
+        public void Sign(Ed25519.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen,
+            byte[] sig, int sigOff)
+        {
+            Ed25519PublicKeyParameters publicKey = GeneratePublicKey();
+
             byte[] pk = new byte[Ed25519.PublicKeySize];
-            if (null == publicKey)
-            {
-                Ed25519.GeneratePublicKey(data, 0, pk, 0);
-            }
-            else
-            {
-                publicKey.Encode(pk, 0);
-            }
+            publicKey.Encode(pk, 0);
 
             switch (algorithm)
             {
diff --git a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
index f2fc4d533..1b38143fa 100644
--- a/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
+++ b/crypto/src/crypto/parameters/Ed448PrivateKeyParameters.cs
@@ -16,6 +16,8 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         private readonly byte[] data = new byte[KeySize];
 
+        private Ed448PublicKeyParameters cachedPublicKey;
+
         public Ed448PrivateKeyParameters(SecureRandom random)
             : base(true)
         {
@@ -47,23 +49,33 @@ namespace Org.BouncyCastle.Crypto.Parameters
 
         public Ed448PublicKeyParameters GeneratePublicKey()
         {
-            byte[] publicKey = new byte[Ed448.PublicKeySize];
-            Ed448.GeneratePublicKey(data, 0, publicKey, 0);
-            return new Ed448PublicKeyParameters(publicKey, 0);
+            lock (data)
+            {
+                if (null == cachedPublicKey)
+                {
+                    byte[] publicKey = new byte[Ed448.PublicKeySize];
+                    Ed448.GeneratePublicKey(data, 0, publicKey, 0);
+                    cachedPublicKey = new Ed448PublicKeyParameters(publicKey, 0);
+                }
+
+                return cachedPublicKey;
+            }
         }
 
+        [Obsolete("Use overload that doesn't take a public key")]
         public void Sign(Ed448.Algorithm algorithm, Ed448PublicKeyParameters publicKey, byte[] ctx, byte[] msg, int msgOff, int msgLen,
             byte[] sig, int sigOff)
         {
+            Sign(algorithm, ctx, msg, msgOff, msgLen, sig, sigOff);
+        }
+
+        public void Sign(Ed448.Algorithm algorithm, byte[] ctx, byte[] msg, int msgOff, int msgLen,
+            byte[] sig, int sigOff)
+        {
+            Ed448PublicKeyParameters publicKey = GeneratePublicKey();
+
             byte[] pk = new byte[Ed448.PublicKeySize];
-            if (null == publicKey)
-            {
-                Ed448.GeneratePublicKey(data, 0, pk, 0);
-            }
-            else
-            {
-                publicKey.Encode(pk, 0);
-            }
+            publicKey.Encode(pk, 0);
 
             switch (algorithm)
             {
diff --git a/crypto/src/crypto/signers/Ed25519Signer.cs b/crypto/src/crypto/signers/Ed25519Signer.cs
index a916601e6..e58d14ea4 100644
--- a/crypto/src/crypto/signers/Ed25519Signer.cs
+++ b/crypto/src/crypto/signers/Ed25519Signer.cs
@@ -32,10 +32,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
-
                 this.privateKey = (Ed25519PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -61,7 +59,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519Signer not initialised for signature generation.");
 
-            return buffer.GenerateSignature(privateKey, publicKey);
+            return buffer.GenerateSignature(privateKey);
         }
 
         public virtual bool VerifySignature(byte[] signature)
@@ -79,7 +77,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey)
+            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey)
             {
                 lock (this)
                 {
@@ -91,7 +89,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     int count = (int)Position;
 #endif
                     byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-                    privateKey.Sign(Ed25519.Algorithm.Ed25519, publicKey, null, buf, 0, count, signature, 0);
+                    privateKey.Sign(Ed25519.Algorithm.Ed25519, null, buf, 0, count, signature, 0);
                     Reset();
                     return signature;
                 }
diff --git a/crypto/src/crypto/signers/Ed25519ctxSigner.cs b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
index ab7201b62..2b5296e96 100644
--- a/crypto/src/crypto/signers/Ed25519ctxSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519ctxSigner.cs
@@ -34,10 +34,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
-
                 this.privateKey = (Ed25519PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed25519ctxSigner not initialised for signature generation.");
 
-            return buffer.GenerateSignature(privateKey, publicKey, context);
+            return buffer.GenerateSignature(privateKey, context);
         }
 
         public virtual bool VerifySignature(byte[] signature)
@@ -81,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, Ed25519PublicKeyParameters publicKey, byte[] ctx)
+            internal byte[] GenerateSignature(Ed25519PrivateKeyParameters privateKey, byte[] ctx)
             {
                 lock (this)
                 {
@@ -93,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     int count = (int)Position;
 #endif
                     byte[] signature = new byte[Ed25519PrivateKeyParameters.SignatureSize];
-                    privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, publicKey, ctx, buf, 0, count, signature, 0);
+                    privateKey.Sign(Ed25519.Algorithm.Ed25519ctx, ctx, buf, 0, count, signature, 0);
                     Reset();
                     return signature;
                 }
diff --git a/crypto/src/crypto/signers/Ed25519phSigner.cs b/crypto/src/crypto/signers/Ed25519phSigner.cs
index 2538b16f5..cb3c3080a 100644
--- a/crypto/src/crypto/signers/Ed25519phSigner.cs
+++ b/crypto/src/crypto/signers/Ed25519phSigner.cs
@@ -33,10 +33,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters?
-
                 this.privateKey = (Ed25519PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                 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);
+            privateKey.Sign(Ed25519.Algorithm.Ed25519ph, context, msg, 0, Ed25519.PrehashSize, signature, 0);
             return signature;
         }
 
diff --git a/crypto/src/crypto/signers/Ed448Signer.cs b/crypto/src/crypto/signers/Ed448Signer.cs
index b0563d544..9d1495f2e 100644
--- a/crypto/src/crypto/signers/Ed448Signer.cs
+++ b/crypto/src/crypto/signers/Ed448Signer.cs
@@ -34,10 +34,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
-
                 this.privateKey = (Ed448PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -63,7 +61,7 @@ namespace Org.BouncyCastle.Crypto.Signers
             if (!forSigning || null == privateKey)
                 throw new InvalidOperationException("Ed448Signer not initialised for signature generation.");
 
-            return buffer.GenerateSignature(privateKey, publicKey, context);
+            return buffer.GenerateSignature(privateKey, context);
         }
 
         public virtual bool VerifySignature(byte[] signature)
@@ -81,7 +79,7 @@ namespace Org.BouncyCastle.Crypto.Signers
 
         private class Buffer : MemoryStream
         {
-            internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, Ed448PublicKeyParameters publicKey, byte[] ctx)
+            internal byte[] GenerateSignature(Ed448PrivateKeyParameters privateKey, byte[] ctx)
             {
                 lock (this)
                 {
@@ -93,7 +91,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                     int count = (int)Position;
 #endif
                     byte[] signature = new byte[Ed448PrivateKeyParameters.SignatureSize];
-                    privateKey.Sign(Ed448.Algorithm.Ed448, publicKey, ctx, buf, 0, count, signature, 0);
+                    privateKey.Sign(Ed448.Algorithm.Ed448, ctx, buf, 0, count, signature, 0);
                     Reset();
                     return signature;
                 }
diff --git a/crypto/src/crypto/signers/Ed448phSigner.cs b/crypto/src/crypto/signers/Ed448phSigner.cs
index d656c1392..f01b6bfd4 100644
--- a/crypto/src/crypto/signers/Ed448phSigner.cs
+++ b/crypto/src/crypto/signers/Ed448phSigner.cs
@@ -33,10 +33,8 @@ namespace Org.BouncyCastle.Crypto.Signers
 
             if (forSigning)
             {
-                // TODO Allow AsymmetricCipherKeyPair to be a CipherParameters?
-
                 this.privateKey = (Ed448PrivateKeyParameters)parameters;
-                this.publicKey = privateKey.GeneratePublicKey();
+                this.publicKey = null;
             }
             else
             {
@@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Signers
                 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);
+            privateKey.Sign(Ed448.Algorithm.Ed448ph, context, msg, 0, Ed448.PrehashSize, signature, 0);
             return signature;
         }