From 8d778d2518245946a0103d91a4e5df6365f74c6f Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 1 Sep 2021 15:45:57 +0800 Subject: [PATCH 01/18] add ecc encrypt&dencrypt --- src/neo/Cryptography/Helper.cs | 84 +++++++++++++++++++ .../Cryptography/UT_Cryptography_Helper.cs | 18 ++++ 2 files changed, 102 insertions(+) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 370f69f611..f9cac34e43 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -4,10 +4,12 @@ using System.Buffers.Binary; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; using System.Text; +using ECPoint = Neo.Cryptography.ECC.ECPoint; namespace Neo.Cryptography { @@ -109,6 +111,88 @@ public static byte[] Sha256(this Span value) return Sha256((ReadOnlySpan)value); } + public static byte[] AES256Decrypt(this byte[] data, byte[] key) + { + using Aes aes = Aes.Create(); + aes.Key = key; + aes.Mode = CipherMode.ECB; + aes.Padding = PaddingMode.PKCS7; + using ICryptoTransform decryptor = aes.CreateDecryptor(); + return decryptor.TransformFinalBlock(data, 0, data.Length); + } + + public static byte[] AES256Encrypt(this byte[] data, byte[] key) + { + using Aes aes = Aes.Create(); + aes.Key = key; + aes.Mode = CipherMode.ECB; + aes.Padding = PaddingMode.PKCS7; + using ICryptoTransform encryptor = aes.CreateEncryptor(); + return encryptor.TransformFinalBlock(data, 0, data.Length); + } + + public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) + { + // P=kG,R=rG =>{R,M+rP} + BigInteger r, rx; + ECPoint R; + var curve = pubKey.Curve; + //r > N + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + do + { + do + { + r = rng.NextBigInteger((int)curve.N.GetBitLength()); + } + while (r.Sign == 0 || r.CompareTo(curve.N) >= 0); + R = ECPoint.Multiply(curve.G, r); + BigInteger x = R.X.Value; + rx = x.Mod(curve.N); + } + while (rx.Sign == 0); + } + byte[] RBar = R.EncodePoint(true); + var z = ECPoint.Multiply(pubKey, r).X; // z = r * P = r* k * G + var Z = z.ToByteArray(); + var EK = Z.Sha256(); + var EM = message.AES256Encrypt(EK); + return RBar.Concat(EM).ToArray(); + } + public static byte[] ECDecrypt(byte[] cypher, byte[] priKey, ECPoint pubKey) + { + // {R,M+rP}={rG, M+rP}=> M + rP - kR = M + r(kG) - k(rG) = M + if (cypher is null || cypher.Length < 33) + throw new ArgumentException(); + if (cypher[0] != 0x02 && cypher[0] != 0x03) + throw new ArgumentException(); + var RBar = cypher.Take(33).ToArray(); + var EM = cypher.Skip(33).ToArray(); + var R = ECPoint.FromBytes(RBar, pubKey.Curve); + var k = new BigInteger(priKey.Reverse().Concat(new byte[1]).ToArray()); + var z = ECPoint.Multiply(R, k).X; // z = k * R = k * r * G + var EK = z.ToByteArray().Sha256(); + var M = EM.AES256Decrypt(EK); + return M; + } + + internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int sizeInBits) + { + if (sizeInBits < 0) + throw new ArgumentException("sizeInBits must be non-negative"); + if (sizeInBits == 0) + return 0; + byte[] b = new byte[sizeInBits / 8 + 1]; + rng.GetBytes(b); + if (sizeInBits % 8 == 0) + b[b.Length - 1] = 0; + else + b[b.Length - 1] &= (byte)((1 << sizeInBits % 8) - 1); + return new BigInteger(b); + } + + internal static bool Test(this BloomFilter filter, Transaction tx) { if (filter.Check(tx.Hash.ToArray())) return true; diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index cd32a5dbfc..e04574ad65 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -4,7 +4,10 @@ using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.Wallets; +using Neo.Wallets.NEP6; using System; +using System.Linq; using System.Security; using System.Text; @@ -48,6 +51,21 @@ public void TestRIPEMD160() resultStr.Should().Be("98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f"); } + [TestMethod] + public void TestECEncryptAndDecrypt() + { + NEP6Wallet wallet = new NEP6Wallet("", ProtocolSettings.Default); + wallet.Unlock("1"); + wallet.CreateAccount(); + WalletAccount account = wallet.GetAccounts().ToArray()[0]; + KeyPair key = account.GetKey(); + var message = Encoding.ASCII.GetBytes("hello world"); + var cypher = Neo.Cryptography.Helper.ECEncrypt(message, key.PublicKey); + var m = Neo.Cryptography.Helper.ECDecrypt(cypher, key.PrivateKey, key.PublicKey); + var message2 = Encoding.ASCII.GetString(m); + Assert.AreEqual("hello world", message2); + } + [TestMethod] public void TestTest() { From 306e95844a63006d4a7c58c54ef0c4d98339d899 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 1 Sep 2021 16:30:27 +0800 Subject: [PATCH 02/18] change to keypair --- src/neo/Cryptography/Helper.cs | 7 ++++--- tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index f9cac34e43..6a3b2152f4 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -1,5 +1,6 @@ using Neo.IO; using Neo.Network.P2P.Payloads; +using Neo.Wallets; using System; using System.Buffers.Binary; using System.Collections.Generic; @@ -160,7 +161,7 @@ public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) var EM = message.AES256Encrypt(EK); return RBar.Concat(EM).ToArray(); } - public static byte[] ECDecrypt(byte[] cypher, byte[] priKey, ECPoint pubKey) + public static byte[] ECDecrypt(byte[] cypher, KeyPair key) { // {R,M+rP}={rG, M+rP}=> M + rP - kR = M + r(kG) - k(rG) = M if (cypher is null || cypher.Length < 33) @@ -169,8 +170,8 @@ public static byte[] ECDecrypt(byte[] cypher, byte[] priKey, ECPoint pubKey) throw new ArgumentException(); var RBar = cypher.Take(33).ToArray(); var EM = cypher.Skip(33).ToArray(); - var R = ECPoint.FromBytes(RBar, pubKey.Curve); - var k = new BigInteger(priKey.Reverse().Concat(new byte[1]).ToArray()); + var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); + var k = new BigInteger(key.PrivateKey.Reverse().Concat(new byte[1]).ToArray()); var z = ECPoint.Multiply(R, k).X; // z = k * R = k * r * G var EK = z.ToByteArray().Sha256(); var M = EM.AES256Decrypt(EK); diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index e04574ad65..2289027291 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -61,7 +61,7 @@ public void TestECEncryptAndDecrypt() KeyPair key = account.GetKey(); var message = Encoding.ASCII.GetBytes("hello world"); var cypher = Neo.Cryptography.Helper.ECEncrypt(message, key.PublicKey); - var m = Neo.Cryptography.Helper.ECDecrypt(cypher, key.PrivateKey, key.PublicKey); + var m = Neo.Cryptography.Helper.ECDecrypt(cypher, key); var message2 = Encoding.ASCII.GetString(m); Assert.AreEqual("hello world", message2); } From 3f464ae40e33d81b2daf18192c035540f599c9a2 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 1 Sep 2021 16:39:04 +0800 Subject: [PATCH 03/18] check IsInfinity --- src/neo/Cryptography/Helper.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 6a3b2152f4..397013b629 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -135,6 +135,7 @@ public static byte[] AES256Encrypt(this byte[] data, byte[] key) public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) { // P=kG,R=rG =>{R,M+rP} + if (pubKey.IsInfinity) throw new ArgumentException(); BigInteger r, rx; ECPoint R; var curve = pubKey.Curve; @@ -168,6 +169,7 @@ public static byte[] ECDecrypt(byte[] cypher, KeyPair key) throw new ArgumentException(); if (cypher[0] != 0x02 && cypher[0] != 0x03) throw new ArgumentException(); + if(key.PublicKey.IsInfinity) throw new ArgumentException(); var RBar = cypher.Take(33).ToArray(); var EM = cypher.Skip(33).ToArray(); var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); From 4b3ecc7a5ca9734ffa634e40898f16089c6722d9 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 1 Sep 2021 11:26:19 +0200 Subject: [PATCH 04/18] Clean format --- src/neo/Cryptography/Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 397013b629..728f098fc1 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -162,6 +162,7 @@ public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) var EM = message.AES256Encrypt(EK); return RBar.Concat(EM).ToArray(); } + public static byte[] ECDecrypt(byte[] cypher, KeyPair key) { // {R,M+rP}={rG, M+rP}=> M + rP - kR = M + r(kG) - k(rG) = M @@ -195,7 +196,6 @@ internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int si return new BigInteger(b); } - internal static bool Test(this BloomFilter filter, Transaction tx) { if (filter.Check(tx.Hash.ToArray())) return true; From 80d26ca2f33a0eebdf73c1fe5fd3d91c18c1bd5b Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 1 Sep 2021 19:23:42 +0800 Subject: [PATCH 05/18] format --- src/neo/Cryptography/Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 397013b629..d52dd09078 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -169,7 +169,7 @@ public static byte[] ECDecrypt(byte[] cypher, KeyPair key) throw new ArgumentException(); if (cypher[0] != 0x02 && cypher[0] != 0x03) throw new ArgumentException(); - if(key.PublicKey.IsInfinity) throw new ArgumentException(); + if (key.PublicKey.IsInfinity) throw new ArgumentException(); var RBar = cypher.Take(33).ToArray(); var EM = cypher.Skip(33).ToArray(); var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); From b15ca6fd5a4d0b88165484f3488873de34cd25b4 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Wed, 1 Sep 2021 19:24:58 +0800 Subject: [PATCH 06/18] Revert "format" This reverts commit 80d26ca2f33a0eebdf73c1fe5fd3d91c18c1bd5b. --- src/neo/Cryptography/Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index d52dd09078..397013b629 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -169,7 +169,7 @@ public static byte[] ECDecrypt(byte[] cypher, KeyPair key) throw new ArgumentException(); if (cypher[0] != 0x02 && cypher[0] != 0x03) throw new ArgumentException(); - if (key.PublicKey.IsInfinity) throw new ArgumentException(); + if(key.PublicKey.IsInfinity) throw new ArgumentException(); var RBar = cypher.Take(33).ToArray(); var EM = cypher.Skip(33).ToArray(); var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); From 39bb5d01d6d54c50ab7ec7afad6485ab32b41920 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 2 Sep 2021 16:38:39 +0800 Subject: [PATCH 07/18] change to GCM --- src/neo/Cryptography/Helper.cs | 60 ++++++++++++------- .../Cryptography/UT_Cryptography_Helper.cs | 14 +++++ 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 728f098fc1..52e193accf 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -1,6 +1,9 @@ using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.Wallets; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; using System; using System.Buffers.Binary; using System.Collections.Generic; @@ -112,24 +115,38 @@ public static byte[] Sha256(this Span value) return Sha256((ReadOnlySpan)value); } - public static byte[] AES256Decrypt(this byte[] data, byte[] key) + public static string AES256Encrypt(this string plainData, string key, string nonce, string associatedData = null) { - using Aes aes = Aes.Create(); - aes.Key = key; - aes.Mode = CipherMode.ECB; - aes.Padding = PaddingMode.PKCS7; - using ICryptoTransform decryptor = aes.CreateDecryptor(); - return decryptor.TransformFinalBlock(data, 0, data.Length); + var keyBytes = Encoding.UTF8.GetBytes(key); + var nonceBytes = Encoding.UTF8.GetBytes(nonce); + var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); + var plainBytes = Encoding.UTF8.GetBytes(plainData); + var cipherBytes = new byte[plainBytes.Length]; + //tag size is 16 + var tag = new byte[16]; + using var cipher = new AesGcm(keyBytes); + cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes); + var cipherWithTag = new byte[nonceBytes.Length + cipherBytes.Length + tag.Length]; + Buffer.BlockCopy(nonceBytes, 0, cipherWithTag, 0, nonceBytes.Length); + Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, nonceBytes.Length, cipherBytes.Length); + Buffer.BlockCopy(tag, 0, cipherWithTag, nonceBytes.Length + cipherBytes.Length, tag.Length); + return Convert.ToBase64String(cipherWithTag); } - - public static byte[] AES256Encrypt(this byte[] data, byte[] key) + public static string AES256Decrypt(this string encryptedData, string key, string associatedData = null) { - using Aes aes = Aes.Create(); - aes.Key = key; - aes.Mode = CipherMode.ECB; - aes.Padding = PaddingMode.PKCS7; - using ICryptoTransform encryptor = aes.CreateEncryptor(); - return encryptor.TransformFinalBlock(data, 0, data.Length); + var keyBytes = Encoding.UTF8.GetBytes(key); + //var nonceBytes = Encoding.UTF8.GetBytes(nonce); + var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); + + var encryptedBytes = Convert.FromBase64String(encryptedData); + //tag size is 16 + var nonceBytes = encryptedBytes.Take(12).ToArray(); + var cipherBytes = encryptedBytes.Skip(12).Take(encryptedBytes.Length - 28).ToArray(); + var tag = encryptedBytes[^16..]; + var decryptedData = new byte[cipherBytes.Length]; + using var cipher = new AesGcm(keyBytes); + cipher.Decrypt(nonceBytes, cipherBytes, tag, decryptedData, associatedBytes); + return Encoding.UTF8.GetString(decryptedData); } public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) @@ -159,8 +176,11 @@ public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) var z = ECPoint.Multiply(pubKey, r).X; // z = r * P = r* k * G var Z = z.ToByteArray(); var EK = Z.Sha256(); - var EM = message.AES256Encrypt(EK); - return RBar.Concat(EM).ToArray(); + Random random = new Random(); + byte[] Nonce = new byte[12]; + random.NextBytes(Nonce); + var EM = Convert.ToBase64String(message).AES256Encrypt(Encoding.ASCII.GetString(EK), Encoding.ASCII.GetString(Nonce)); + return RBar.Concat(Convert.FromBase64String(EM)).ToArray(); } public static byte[] ECDecrypt(byte[] cypher, KeyPair key) @@ -170,15 +190,15 @@ public static byte[] ECDecrypt(byte[] cypher, KeyPair key) throw new ArgumentException(); if (cypher[0] != 0x02 && cypher[0] != 0x03) throw new ArgumentException(); - if(key.PublicKey.IsInfinity) throw new ArgumentException(); + if (key.PublicKey.IsInfinity) throw new ArgumentException(); var RBar = cypher.Take(33).ToArray(); var EM = cypher.Skip(33).ToArray(); var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); var k = new BigInteger(key.PrivateKey.Reverse().Concat(new byte[1]).ToArray()); var z = ECPoint.Multiply(R, k).X; // z = k * R = k * r * G var EK = z.ToByteArray().Sha256(); - var M = EM.AES256Decrypt(EK); - return M; + var M = Convert.ToBase64String(EM).AES256Decrypt(Encoding.ASCII.GetString(EK)); + return Convert.FromBase64String(M); } internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int sizeInBits) diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index 2289027291..9b9823c517 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -51,6 +51,20 @@ public void TestRIPEMD160() resultStr.Should().Be("98c615784ccb5fe5936fbc0cbe9dfdb408d92f0f"); } + [TestMethod] + public void TestAESEncryptAndDecrypt() + { + NEP6Wallet wallet = new NEP6Wallet("", ProtocolSettings.Default); + wallet.Unlock("1"); + wallet.CreateAccount(); + WalletAccount account = wallet.GetAccounts().ToArray()[0]; + KeyPair key = account.GetKey(); + var cypher = Neo.Cryptography.Helper.AES256Encrypt(Convert.ToBase64String(Encoding.UTF8.GetBytes("hello world")), Encoding.ASCII.GetString(key.PrivateKey), "77d0a5ff3937"); + var m = Neo.Cryptography.Helper.AES256Decrypt(cypher, Encoding.ASCII.GetString(key.PrivateKey)); + var message2 = Encoding.UTF8.GetString(Convert.FromBase64String(m)); + Assert.AreEqual("hello world", message2); + } + [TestMethod] public void TestECEncryptAndDecrypt() { From 72fadce5926d4eff1b04df75c9426a900152213a Mon Sep 17 00:00:00 2001 From: doubiliu Date: Thu, 2 Sep 2021 16:40:18 +0800 Subject: [PATCH 08/18] format --- src/neo/Cryptography/Helper.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 52e193accf..cf3926405b 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -122,7 +122,6 @@ public static string AES256Encrypt(this string plainData, string key, string non var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); var plainBytes = Encoding.UTF8.GetBytes(plainData); var cipherBytes = new byte[plainBytes.Length]; - //tag size is 16 var tag = new byte[16]; using var cipher = new AesGcm(keyBytes); cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes); @@ -132,14 +131,12 @@ public static string AES256Encrypt(this string plainData, string key, string non Buffer.BlockCopy(tag, 0, cipherWithTag, nonceBytes.Length + cipherBytes.Length, tag.Length); return Convert.ToBase64String(cipherWithTag); } + public static string AES256Decrypt(this string encryptedData, string key, string associatedData = null) { var keyBytes = Encoding.UTF8.GetBytes(key); - //var nonceBytes = Encoding.UTF8.GetBytes(nonce); var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); - var encryptedBytes = Convert.FromBase64String(encryptedData); - //tag size is 16 var nonceBytes = encryptedBytes.Take(12).ToArray(); var cipherBytes = encryptedBytes.Skip(12).Take(encryptedBytes.Length - 28).ToArray(); var tag = encryptedBytes[^16..]; From 32fd454075aca8e1805e80b7895714f130797858 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sat, 4 Sep 2021 16:26:56 +0800 Subject: [PATCH 09/18] Update src/neo/Cryptography/Helper.cs Co-authored-by: Jinghui Liao --- src/neo/Cryptography/Helper.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index cf3926405b..94f5b4d416 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -170,9 +170,7 @@ public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) while (rx.Sign == 0); } byte[] RBar = R.EncodePoint(true); - var z = ECPoint.Multiply(pubKey, r).X; // z = r * P = r* k * G - var Z = z.ToByteArray(); - var EK = Z.Sha256(); + var EK = ECPoint.Multiply(pubKey, r).X.ToByteArray().Sha256(); // z = r * P = r* k * G Random random = new Random(); byte[] Nonce = new byte[12]; random.NextBytes(Nonce); From 7b9b0386b51b4c7004c14fd0f45752847c0453e8 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 6 Sep 2021 15:26:41 +0800 Subject: [PATCH 10/18] improve --- src/neo/Cryptography/Helper.cs | 63 ++++++++----------- .../Cryptography/UT_Cryptography_Helper.cs | 9 ++- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 94f5b4d416..9cc21f543c 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -115,35 +115,31 @@ public static byte[] Sha256(this Span value) return Sha256((ReadOnlySpan)value); } - public static string AES256Encrypt(this string plainData, string key, string nonce, string associatedData = null) + public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[] associatedData = null) { - var keyBytes = Encoding.UTF8.GetBytes(key); - var nonceBytes = Encoding.UTF8.GetBytes(nonce); - var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); - var plainBytes = Encoding.UTF8.GetBytes(plainData); - var cipherBytes = new byte[plainBytes.Length]; + if (key.Length != 32) throw new ArgumentException(); + if (nonce.Length != 12) throw new ArgumentException(); + var cipherBytes = new byte[plainData.Length]; var tag = new byte[16]; - using var cipher = new AesGcm(keyBytes); - cipher.Encrypt(nonceBytes, plainBytes, cipherBytes, tag, associatedBytes); - var cipherWithTag = new byte[nonceBytes.Length + cipherBytes.Length + tag.Length]; - Buffer.BlockCopy(nonceBytes, 0, cipherWithTag, 0, nonceBytes.Length); - Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, nonceBytes.Length, cipherBytes.Length); - Buffer.BlockCopy(tag, 0, cipherWithTag, nonceBytes.Length + cipherBytes.Length, tag.Length); - return Convert.ToBase64String(cipherWithTag); + using var cipher = new AesGcm(key); + cipher.Encrypt(nonce, plainData, cipherBytes, tag, associatedData); + var cipherWithTag = new byte[nonce.Length + cipherBytes.Length + tag.Length]; + Buffer.BlockCopy(nonce, 0, cipherWithTag, 0, nonce.Length); + Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, nonce.Length, cipherBytes.Length); + Buffer.BlockCopy(tag, 0, cipherWithTag, nonce.Length + cipherBytes.Length, tag.Length); + return cipherWithTag; } - public static string AES256Decrypt(this string encryptedData, string key, string associatedData = null) + public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] associatedData = null) { - var keyBytes = Encoding.UTF8.GetBytes(key); - var associatedBytes = associatedData == null ? null : Encoding.UTF8.GetBytes(associatedData); - var encryptedBytes = Convert.FromBase64String(encryptedData); - var nonceBytes = encryptedBytes.Take(12).ToArray(); - var cipherBytes = encryptedBytes.Skip(12).Take(encryptedBytes.Length - 28).ToArray(); - var tag = encryptedBytes[^16..]; + if (key.Length != 32) throw new ArgumentException(); + var nonce = encryptedData.Take(12).ToArray(); + var cipherBytes = encryptedData.Skip(12).Take(encryptedData.Length - 28).ToArray(); + var tag = encryptedData[^16..]; var decryptedData = new byte[cipherBytes.Length]; - using var cipher = new AesGcm(keyBytes); - cipher.Decrypt(nonceBytes, cipherBytes, tag, decryptedData, associatedBytes); - return Encoding.UTF8.GetString(decryptedData); + using var cipher = new AesGcm(key); + cipher.Decrypt(nonce, cipherBytes, tag, decryptedData, associatedData); + return decryptedData; } public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) @@ -161,39 +157,32 @@ public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) do { r = rng.NextBigInteger((int)curve.N.GetBitLength()); - } - while (r.Sign == 0 || r.CompareTo(curve.N) >= 0); + } while (r.Sign == 0 || r.CompareTo(curve.N) >= 0); R = ECPoint.Multiply(curve.G, r); BigInteger x = R.X.Value; rx = x.Mod(curve.N); - } - while (rx.Sign == 0); + } while (rx.Sign == 0); } byte[] RBar = R.EncodePoint(true); var EK = ECPoint.Multiply(pubKey, r).X.ToByteArray().Sha256(); // z = r * P = r* k * G Random random = new Random(); byte[] Nonce = new byte[12]; random.NextBytes(Nonce); - var EM = Convert.ToBase64String(message).AES256Encrypt(Encoding.ASCII.GetString(EK), Encoding.ASCII.GetString(Nonce)); - return RBar.Concat(Convert.FromBase64String(EM)).ToArray(); + return RBar.Concat(message.AES256Encrypt(EK, Nonce)).ToArray(); } public static byte[] ECDecrypt(byte[] cypher, KeyPair key) { // {R,M+rP}={rG, M+rP}=> M + rP - kR = M + r(kG) - k(rG) = M - if (cypher is null || cypher.Length < 33) - throw new ArgumentException(); - if (cypher[0] != 0x02 && cypher[0] != 0x03) - throw new ArgumentException(); + if (cypher is null || cypher.Length < 33) throw new ArgumentException(); + if (cypher[0] != 0x02 && cypher[0] != 0x03) throw new ArgumentException(); if (key.PublicKey.IsInfinity) throw new ArgumentException(); var RBar = cypher.Take(33).ToArray(); var EM = cypher.Skip(33).ToArray(); var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); var k = new BigInteger(key.PrivateKey.Reverse().Concat(new byte[1]).ToArray()); - var z = ECPoint.Multiply(R, k).X; // z = k * R = k * r * G - var EK = z.ToByteArray().Sha256(); - var M = Convert.ToBase64String(EM).AES256Decrypt(Encoding.ASCII.GetString(EK)); - return Convert.FromBase64String(M); + var EK = ECPoint.Multiply(R, k).X.ToByteArray().Sha256(); // z = k * R = k * r * G + return EM.AES256Decrypt(EK); } internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int sizeInBits) diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index 9b9823c517..e5496ad6c0 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -59,9 +59,12 @@ public void TestAESEncryptAndDecrypt() wallet.CreateAccount(); WalletAccount account = wallet.GetAccounts().ToArray()[0]; KeyPair key = account.GetKey(); - var cypher = Neo.Cryptography.Helper.AES256Encrypt(Convert.ToBase64String(Encoding.UTF8.GetBytes("hello world")), Encoding.ASCII.GetString(key.PrivateKey), "77d0a5ff3937"); - var m = Neo.Cryptography.Helper.AES256Decrypt(cypher, Encoding.ASCII.GetString(key.PrivateKey)); - var message2 = Encoding.UTF8.GetString(Convert.FromBase64String(m)); + Random random = new Random(); + byte[] nonce = new byte[12]; + random.NextBytes(nonce); + var cypher = Neo.Cryptography.Helper.AES256Encrypt(Encoding.UTF8.GetBytes("hello world"), key.PrivateKey, nonce); + var m = Neo.Cryptography.Helper.AES256Decrypt(cypher, key.PrivateKey); + var message2 = Encoding.UTF8.GetString(m); Assert.AreEqual("hello world", message2); } From 47a9138f0a2627825eafcf20c0d5e2f3f9f973a4 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 6 Sep 2021 19:49:29 +0800 Subject: [PATCH 11/18] Update src/neo/Cryptography/Helper.cs Co-authored-by: Jinghui Liao --- src/neo/Cryptography/Helper.cs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 9cc21f543c..f58020ea0a 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -117,16 +117,23 @@ public static byte[] Sha256(this Span value) public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[] associatedData = null) { - if (key.Length != 32) throw new ArgumentException(); - if (nonce.Length != 12) throw new ArgumentException(); - var cipherBytes = new byte[plainData.Length]; - var tag = new byte[16]; + var keyLen = key is null ? 0 : key.Length; + var nonceLen = nonce is null ? 0 : nonce.Length; + + if (keyLen != 32) throw new ArgumentException(); + if (nonceLen != 12) throw new ArgumentException(); + + var msgLen = plainData is null ? 0 : plainData.Length; + var tagLen = 16; + + var cipherBytes = new byte[msgLen]; + var tag = new byte[tagLen]; using var cipher = new AesGcm(key); cipher.Encrypt(nonce, plainData, cipherBytes, tag, associatedData); - var cipherWithTag = new byte[nonce.Length + cipherBytes.Length + tag.Length]; - Buffer.BlockCopy(nonce, 0, cipherWithTag, 0, nonce.Length); - Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, nonce.Length, cipherBytes.Length); - Buffer.BlockCopy(tag, 0, cipherWithTag, nonce.Length + cipherBytes.Length, tag.Length); + var cipherWithTag = new byte[nonceLen + msgLen + tagLen]; + Buffer.BlockCopy(nonce, 0, cipherWithTag, 0, nonceLen); + Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, nonceLen, msgLen); + Buffer.BlockCopy(tag, 0, cipherWithTag, nonceLen + msgLen, tagLen); return cipherWithTag; } From b013bf6f81ef455d4f6bab372f542918a163eb7c Mon Sep 17 00:00:00 2001 From: doubiliu Date: Mon, 6 Sep 2021 19:49:37 +0800 Subject: [PATCH 12/18] Update src/neo/Cryptography/Helper.cs Co-authored-by: Jinghui Liao --- src/neo/Cryptography/Helper.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index f58020ea0a..3f728f2f44 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -1,9 +1,6 @@ using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.Wallets; -using Org.BouncyCastle.Crypto.Engines; -using Org.BouncyCastle.Crypto.Modes; -using Org.BouncyCastle.Crypto.Parameters; using System; using System.Buffers.Binary; using System.Collections.Generic; From 0ce29772c6e3ddbaf7d6fd3bdb697768ef32ac93 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Fri, 10 Sep 2021 20:13:25 +0800 Subject: [PATCH 13/18] change to ecdh --- src/neo/Cryptography/Helper.cs | 95 +++++++++---------- .../Cryptography/UT_Cryptography_Helper.cs | 18 ++-- 2 files changed, 55 insertions(+), 58 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 95819801c6..b1c584970f 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -129,10 +129,8 @@ public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] non if (keyLen != 32) throw new ArgumentException(); if (nonceLen != 12) throw new ArgumentException(); - var msgLen = plainData is null ? 0 : plainData.Length; var tagLen = 16; - var cipherBytes = new byte[msgLen]; var tag = new byte[tagLen]; using var cipher = new AesGcm(key); @@ -156,62 +154,57 @@ public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] return decryptedData; } - public static byte[] ECEncrypt(byte[] message, ECPoint pubKey) + public static byte[] EcdhEncrypt(byte[] message, KeyPair local, ECPoint remote) { - // P=kG,R=rG =>{R,M+rP} - if (pubKey.IsInfinity) throw new ArgumentException(); - BigInteger r, rx; - ECPoint R; - var curve = pubKey.Curve; - //r > N - using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + ECDiffieHellman ecdh1 = ECDiffieHellmanCng.Create(new ECParameters { - do + Curve = ECCurve.NamedCurves.nistP256, + D = local.PrivateKey, + Q = new System.Security.Cryptography.ECPoint { - do - { - r = rng.NextBigInteger((int)curve.N.GetBitLength()); - } while (r.Sign == 0 || r.CompareTo(curve.N) >= 0); - R = ECPoint.Multiply(curve.G, r); - BigInteger x = R.X.Value; - rx = x.Mod(curve.N); - } while (rx.Sign == 0); - } - byte[] RBar = R.EncodePoint(true); - var EK = ECPoint.Multiply(pubKey, r).X.ToByteArray().Sha256(); // z = r * P = r* k * G + X = local.PublicKey.EncodePoint(false)[1..][..32], + Y = local.PublicKey.EncodePoint(false)[1..][32..] + } + }); + ECDiffieHellman ecdh2 = ECDiffieHellmanCng.Create(new ECParameters + { + Curve = ECCurve.NamedCurves.nistP256, + Q = new System.Security.Cryptography.ECPoint + { + X = remote.EncodePoint(false)[1..][..32], + Y = remote.EncodePoint(false)[1..][32..] + } + }); + byte[] secret = ecdh1.DeriveKeyMaterial(ecdh2.PublicKey).Sha256();//z = r * P = r* k * G Random random = new Random(); - byte[] Nonce = new byte[12]; - random.NextBytes(Nonce); - return RBar.Concat(message.AES256Encrypt(EK, Nonce)).ToArray(); + byte[] nonce = new byte[12]; + random.NextBytes(nonce); + return message.AES256Encrypt(secret, nonce); } - public static byte[] ECDecrypt(byte[] cypher, KeyPair key) + public static byte[] EcdhDecrypt(byte[] cypher, KeyPair local, ECPoint remote) { - // {R,M+rP}={rG, M+rP}=> M + rP - kR = M + r(kG) - k(rG) = M - if (cypher is null || cypher.Length < 33) throw new ArgumentException(); - if (cypher[0] != 0x02 && cypher[0] != 0x03) throw new ArgumentException(); - if (key.PublicKey.IsInfinity) throw new ArgumentException(); - var RBar = cypher.Take(33).ToArray(); - var EM = cypher.Skip(33).ToArray(); - var R = ECPoint.FromBytes(RBar, key.PublicKey.Curve); - var k = new BigInteger(key.PrivateKey.Reverse().Concat(new byte[1]).ToArray()); - var EK = ECPoint.Multiply(R, k).X.ToByteArray().Sha256(); // z = k * R = k * r * G - return EM.AES256Decrypt(EK); - } - - internal static BigInteger NextBigInteger(this RandomNumberGenerator rng, int sizeInBits) - { - if (sizeInBits < 0) - throw new ArgumentException("sizeInBits must be non-negative"); - if (sizeInBits == 0) - return 0; - byte[] b = new byte[sizeInBits / 8 + 1]; - rng.GetBytes(b); - if (sizeInBits % 8 == 0) - b[b.Length - 1] = 0; - else - b[b.Length - 1] &= (byte)((1 << sizeInBits % 8) - 1); - return new BigInteger(b); + ECDiffieHellman ecdh1 = ECDiffieHellmanCng.Create(new ECParameters + { + Curve = ECCurve.NamedCurves.nistP256, + D = local.PrivateKey, + Q = new System.Security.Cryptography.ECPoint + { + X = local.PublicKey.EncodePoint(false)[1..][..32], + Y = local.PublicKey.EncodePoint(false)[1..][32..] + } + }); + ECDiffieHellman ecdh2 = ECDiffieHellmanCng.Create(new ECParameters + { + Curve = ECCurve.NamedCurves.nistP256, + Q = new System.Security.Cryptography.ECPoint + { + X = remote.EncodePoint(false)[1..][..32], + Y = remote.EncodePoint(false)[1..][32..] + } + }); + byte[] secret = ecdh1.DeriveKeyMaterial(ecdh2.PublicKey).Sha256();//z = r * P = r* k * G + return cypher.AES256Decrypt(secret); } internal static bool Test(this BloomFilter filter, Transaction tx) diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index e5496ad6c0..34567f3105 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -69,18 +69,22 @@ public void TestAESEncryptAndDecrypt() } [TestMethod] - public void TestECEncryptAndDecrypt() + public void TestEcdhEncryptAndDecrypt() { NEP6Wallet wallet = new NEP6Wallet("", ProtocolSettings.Default); wallet.Unlock("1"); wallet.CreateAccount(); - WalletAccount account = wallet.GetAccounts().ToArray()[0]; - KeyPair key = account.GetKey(); + wallet.CreateAccount(); + WalletAccount account1 = wallet.GetAccounts().ToArray()[0]; + KeyPair key1 = account1.GetKey(); + WalletAccount account2 = wallet.GetAccounts().ToArray()[1]; + KeyPair key2 = account2.GetKey(); + Console.WriteLine($"Account:{1},privatekey:{key1.PrivateKey.ToHexString()},publicKey:{key1.PublicKey.ToArray().ToHexString()}"); + Console.WriteLine($"Account:{2},privatekey:{key2.PrivateKey.ToHexString()},publicKey:{key2.PublicKey.ToArray().ToHexString()}"); var message = Encoding.ASCII.GetBytes("hello world"); - var cypher = Neo.Cryptography.Helper.ECEncrypt(message, key.PublicKey); - var m = Neo.Cryptography.Helper.ECDecrypt(cypher, key); - var message2 = Encoding.ASCII.GetString(m); - Assert.AreEqual("hello world", message2); + var cypher1 = Neo.Cryptography.Helper.EcdhEncrypt(message, key1, key2.PublicKey); + var cypher2 = Neo.Cryptography.Helper.EcdhDecrypt(cypher1, key2, key1.PublicKey); + Assert.AreEqual("hello world", Encoding.ASCII.GetString(cypher2)); } [TestMethod] From 65b58ee490724812334938e0d2d92a6fa5a85c59 Mon Sep 17 00:00:00 2001 From: doubiliu Date: Sat, 11 Sep 2021 18:33:54 +0800 Subject: [PATCH 14/18] improve --- src/neo/Cryptography/Helper.cs | 34 ++----------------- .../Cryptography/UT_Cryptography_Helper.cs | 12 +++++-- 2 files changed, 11 insertions(+), 35 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index b1c584970f..0743915499 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -126,7 +126,6 @@ public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] non { var keyLen = key is null ? 0 : key.Length; var nonceLen = nonce is null ? 0 : nonce.Length; - if (keyLen != 32) throw new ArgumentException(); if (nonceLen != 12) throw new ArgumentException(); var msgLen = plainData is null ? 0 : plainData.Length; @@ -154,35 +153,7 @@ public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] return decryptedData; } - public static byte[] EcdhEncrypt(byte[] message, KeyPair local, ECPoint remote) - { - ECDiffieHellman ecdh1 = ECDiffieHellmanCng.Create(new ECParameters - { - Curve = ECCurve.NamedCurves.nistP256, - D = local.PrivateKey, - Q = new System.Security.Cryptography.ECPoint - { - X = local.PublicKey.EncodePoint(false)[1..][..32], - Y = local.PublicKey.EncodePoint(false)[1..][32..] - } - }); - ECDiffieHellman ecdh2 = ECDiffieHellmanCng.Create(new ECParameters - { - Curve = ECCurve.NamedCurves.nistP256, - Q = new System.Security.Cryptography.ECPoint - { - X = remote.EncodePoint(false)[1..][..32], - Y = remote.EncodePoint(false)[1..][32..] - } - }); - byte[] secret = ecdh1.DeriveKeyMaterial(ecdh2.PublicKey).Sha256();//z = r * P = r* k * G - Random random = new Random(); - byte[] nonce = new byte[12]; - random.NextBytes(nonce); - return message.AES256Encrypt(secret, nonce); - } - - public static byte[] EcdhDecrypt(byte[] cypher, KeyPair local, ECPoint remote) + public static byte[] ECDHDeriveKey(KeyPair local, ECPoint remote) { ECDiffieHellman ecdh1 = ECDiffieHellmanCng.Create(new ECParameters { @@ -203,8 +174,7 @@ public static byte[] EcdhDecrypt(byte[] cypher, KeyPair local, ECPoint remote) Y = remote.EncodePoint(false)[1..][32..] } }); - byte[] secret = ecdh1.DeriveKeyMaterial(ecdh2.PublicKey).Sha256();//z = r * P = r* k * G - return cypher.AES256Decrypt(secret); + return ecdh1.DeriveKeyMaterial(ecdh2.PublicKey).Sha256();//z = r * P = r* k * G } internal static bool Test(this BloomFilter filter, Transaction tx) diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index 34567f3105..6dc101c787 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -81,10 +81,16 @@ public void TestEcdhEncryptAndDecrypt() KeyPair key2 = account2.GetKey(); Console.WriteLine($"Account:{1},privatekey:{key1.PrivateKey.ToHexString()},publicKey:{key1.PublicKey.ToArray().ToHexString()}"); Console.WriteLine($"Account:{2},privatekey:{key2.PrivateKey.ToHexString()},publicKey:{key2.PublicKey.ToArray().ToHexString()}"); + var secret1 = Neo.Cryptography.Helper.ECDHDeriveKey(key1, key2.PublicKey); + var secret2 = Neo.Cryptography.Helper.ECDHDeriveKey(key1, key2.PublicKey); + Assert.AreEqual(secret1.ToHexString(), secret2.ToHexString()); var message = Encoding.ASCII.GetBytes("hello world"); - var cypher1 = Neo.Cryptography.Helper.EcdhEncrypt(message, key1, key2.PublicKey); - var cypher2 = Neo.Cryptography.Helper.EcdhDecrypt(cypher1, key2, key1.PublicKey); - Assert.AreEqual("hello world", Encoding.ASCII.GetString(cypher2)); + Random random = new Random(); + byte[] nonce = new byte[12]; + random.NextBytes(nonce); + var cypher = message.AES256Encrypt(secret1, nonce); + cypher.AES256Decrypt(secret2); + Assert.AreEqual("hello world", Encoding.ASCII.GetString(cypher.AES256Decrypt(secret2))); } [TestMethod] From 453f76cf7dc16a578f452f9dbc2263911226e78a Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 13 Sep 2021 16:59:18 +0800 Subject: [PATCH 15/18] Update tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs Co-authored-by: Nicole <43694095+nicolegys@users.noreply.github.com> --- tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs index 6dc101c787..eebe1c9802 100644 --- a/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs +++ b/tests/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs @@ -82,7 +82,7 @@ public void TestEcdhEncryptAndDecrypt() Console.WriteLine($"Account:{1},privatekey:{key1.PrivateKey.ToHexString()},publicKey:{key1.PublicKey.ToArray().ToHexString()}"); Console.WriteLine($"Account:{2},privatekey:{key2.PrivateKey.ToHexString()},publicKey:{key2.PublicKey.ToArray().ToHexString()}"); var secret1 = Neo.Cryptography.Helper.ECDHDeriveKey(key1, key2.PublicKey); - var secret2 = Neo.Cryptography.Helper.ECDHDeriveKey(key1, key2.PublicKey); + var secret2 = Neo.Cryptography.Helper.ECDHDeriveKey(key2, key1.PublicKey); Assert.AreEqual(secret1.ToHexString(), secret2.ToHexString()); var message = Encoding.ASCII.GetBytes("hello world"); Random random = new Random(); From b5bb887f42fb70b12ead248d4315f012bb88a471 Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 13 Sep 2021 17:25:38 +0800 Subject: [PATCH 16/18] Add using --- src/neo/Cryptography/Helper.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index 0743915499..f3aef3ecea 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -15,7 +15,6 @@ using System.Buffers.Binary; using System.Collections.Generic; using System.Linq; -using System.Numerics; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; @@ -155,7 +154,7 @@ public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] public static byte[] ECDHDeriveKey(KeyPair local, ECPoint remote) { - ECDiffieHellman ecdh1 = ECDiffieHellmanCng.Create(new ECParameters + using ECDiffieHellman ecdh1 = ECDiffieHellman.Create(new ECParameters { Curve = ECCurve.NamedCurves.nistP256, D = local.PrivateKey, @@ -165,7 +164,7 @@ public static byte[] ECDHDeriveKey(KeyPair local, ECPoint remote) Y = local.PublicKey.EncodePoint(false)[1..][32..] } }); - ECDiffieHellman ecdh2 = ECDiffieHellmanCng.Create(new ECParameters + using ECDiffieHellman ecdh2 = ECDiffieHellman.Create(new ECParameters { Curve = ECCurve.NamedCurves.nistP256, Q = new System.Security.Cryptography.ECPoint From bb5be4bd5e6562ec0560db6b97a2888e5d049adf Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Mon, 13 Sep 2021 17:28:43 +0800 Subject: [PATCH 17/18] Optimize --- src/neo/Cryptography/Helper.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index f3aef3ecea..b56a4a57be 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -154,14 +154,16 @@ public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] public static byte[] ECDHDeriveKey(KeyPair local, ECPoint remote) { + ReadOnlySpan pubkey_local = local.PublicKey.EncodePoint(false); + ReadOnlySpan pubkey_remote = remote.EncodePoint(false); using ECDiffieHellman ecdh1 = ECDiffieHellman.Create(new ECParameters { Curve = ECCurve.NamedCurves.nistP256, D = local.PrivateKey, Q = new System.Security.Cryptography.ECPoint { - X = local.PublicKey.EncodePoint(false)[1..][..32], - Y = local.PublicKey.EncodePoint(false)[1..][32..] + X = pubkey_local[1..][..32].ToArray(), + Y = pubkey_local[1..][32..].ToArray() } }); using ECDiffieHellman ecdh2 = ECDiffieHellman.Create(new ECParameters @@ -169,8 +171,8 @@ public static byte[] ECDHDeriveKey(KeyPair local, ECPoint remote) Curve = ECCurve.NamedCurves.nistP256, Q = new System.Security.Cryptography.ECPoint { - X = remote.EncodePoint(false)[1..][..32], - Y = remote.EncodePoint(false)[1..][32..] + X = pubkey_remote[1..][..32].ToArray(), + Y = pubkey_remote[1..][32..].ToArray() } }); return ecdh1.DeriveKeyMaterial(ecdh2.PublicKey).Sha256();//z = r * P = r* k * G From 47f109bf30a158fdbf8627816b282d1258e87d1a Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Tue, 14 Sep 2021 18:01:23 +0800 Subject: [PATCH 18/18] Optimize --- src/neo/Cryptography/Helper.cs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/neo/Cryptography/Helper.cs b/src/neo/Cryptography/Helper.cs index b56a4a57be..6fccfcf81b 100644 --- a/src/neo/Cryptography/Helper.cs +++ b/src/neo/Cryptography/Helper.cs @@ -19,6 +19,7 @@ using System.Security; using System.Security.Cryptography; using System.Text; +using static Neo.Helper; using ECPoint = Neo.Cryptography.ECC.ECPoint; namespace Neo.Cryptography @@ -123,29 +124,20 @@ public static byte[] Sha256(this Span value) public static byte[] AES256Encrypt(this byte[] plainData, byte[] key, byte[] nonce, byte[] associatedData = null) { - var keyLen = key is null ? 0 : key.Length; - var nonceLen = nonce is null ? 0 : nonce.Length; - if (keyLen != 32) throw new ArgumentException(); - if (nonceLen != 12) throw new ArgumentException(); - var msgLen = plainData is null ? 0 : plainData.Length; - var tagLen = 16; - var cipherBytes = new byte[msgLen]; - var tag = new byte[tagLen]; + if (nonce.Length != 12) throw new ArgumentOutOfRangeException(nameof(nonce)); + var cipherBytes = new byte[plainData.Length]; + var tag = new byte[16]; using var cipher = new AesGcm(key); cipher.Encrypt(nonce, plainData, cipherBytes, tag, associatedData); - var cipherWithTag = new byte[nonceLen + msgLen + tagLen]; - Buffer.BlockCopy(nonce, 0, cipherWithTag, 0, nonceLen); - Buffer.BlockCopy(cipherBytes, 0, cipherWithTag, nonceLen, msgLen); - Buffer.BlockCopy(tag, 0, cipherWithTag, nonceLen + msgLen, tagLen); - return cipherWithTag; + return Concat(nonce, cipherBytes, tag); } public static byte[] AES256Decrypt(this byte[] encryptedData, byte[] key, byte[] associatedData = null) { - if (key.Length != 32) throw new ArgumentException(); - var nonce = encryptedData.Take(12).ToArray(); - var cipherBytes = encryptedData.Skip(12).Take(encryptedData.Length - 28).ToArray(); - var tag = encryptedData[^16..]; + ReadOnlySpan encrypted = encryptedData; + var nonce = encrypted[..12]; + var cipherBytes = encrypted[12..^16]; + var tag = encrypted[^16..]; var decryptedData = new byte[cipherBytes.Length]; using var cipher = new AesGcm(key); cipher.Decrypt(nonce, cipherBytes, tag, decryptedData, associatedData);