From c6325a99259fe5df8d0e934e4a3d8623f97cd337 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Mon, 25 May 2020 03:52:39 -0500 Subject: [PATCH] added symmetric encrypt/decrypt support --- cli/ui/interfaces/encrypt.cs | 9 +- tests/kdf/symmetricKDFTest.cs | 0 tests/testSymmetric.cs | 85 +++++++++++++++++++ .../key-derivation/deriveSymmetric.cs | 26 ------ .../symmetric-crypto/encryptwithpassphrase.cs | 19 ----- .../chestcrypto/symmetric/exceptions.cs | 23 +++++ .../symmetric/symmetric-encryption.cs | 45 ++++++++++ treasurechest/simplepack/Packed.cs | 16 ++++ treasurechest/treasurechest.csproj | 1 + 9 files changed, 175 insertions(+), 49 deletions(-) delete mode 100644 tests/kdf/symmetricKDFTest.cs create mode 100644 tests/testSymmetric.cs delete mode 100644 treasurechest/chestcrypto/key-derivation/deriveSymmetric.cs delete mode 100644 treasurechest/chestcrypto/symmetric-crypto/encryptwithpassphrase.cs create mode 100644 treasurechest/chestcrypto/symmetric/exceptions.cs create mode 100644 treasurechest/chestcrypto/symmetric/symmetric-encryption.cs create mode 100644 treasurechest/simplepack/Packed.cs diff --git a/cli/ui/interfaces/encrypt.cs b/cli/ui/interfaces/encrypt.cs index a58c199..4cdd399 100644 --- a/cli/ui/interfaces/encrypt.cs +++ b/cli/ui/interfaces/encrypt.cs @@ -1,8 +1,8 @@ using System.IO; using System; +using Sodium; using treasurechest.STDIOWrapper; using getpass; -using ShannonEntropyCal; namespace treasurechestCLI{ @@ -10,8 +10,8 @@ namespace treasurechestCLI{ public static void EncryptMessage(){ int choice = 0; int counter = 1; + byte[] key = new byte[32]; string message; - string passphrase; string encrypted; translations.Strings strings = new translations.Strings(); @@ -53,8 +53,9 @@ namespace treasurechestCLI{ catch(System.NullReferenceException){ continue; } - passphrase = GetPass.getPass(strings.PASSPHRASE); - encrypted = + key = SecretBox.GenerateKey(); + //encrypted = + } else if (choice == encryptMenuOptions.Length){ break; diff --git a/tests/kdf/symmetricKDFTest.cs b/tests/kdf/symmetricKDFTest.cs deleted file mode 100644 index e69de29..0000000 diff --git a/tests/testSymmetric.cs b/tests/testSymmetric.cs new file mode 100644 index 0000000..3d43a8a --- /dev/null +++ b/tests/testSymmetric.cs @@ -0,0 +1,85 @@ +using NUnit.Framework; +using chestcrypto.symmetric; +using System; +using System.Text; +using System.Linq; +using Sodium; + +namespace SymmetricTests +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void TestDecrypt() + { + byte[] message = UTF8Encoding.UTF8.GetBytes("Hello world"); + byte[] message2 = UTF8Encoding.UTF8.GetBytes("Hello worl2"); + int nonceSize = 24; + byte[] nonce = SecretBox.GenerateNonce(); + byte[] key = SecretBox.GenerateKey(); + byte[] encrypted = SecretBox.Create(message, nonce, key); + byte[] both = new byte[nonceSize + encrypted.Length]; + Buffer.BlockCopy(nonce, 0, both, 0, nonce.Length); + Buffer.BlockCopy(encrypted, 0, both, nonce.Length, encrypted.Length); + Assert.IsTrue(both.Length >= message.Length + 24); + Assert.IsTrue(Enumerable.SequenceEqual(Symmetric.decrypt(both, key), message)); + Assert.IsFalse(Enumerable.SequenceEqual(Symmetric.decrypt(both, key), message2)); + + } + + [Test] + public void TestEncryptBytesNoKey() + { + byte[] message = UTF8Encoding.UTF8.GetBytes("Hello world"); + byte[] message2 = UTF8Encoding.UTF8.GetBytes("Hello worl2"); + (byte[] encrypted, byte[] key) = Symmetric.encrypt(message); + int nonceSize = 24; + byte[] justCiphertext = new byte[encrypted.Length - nonceSize]; + + byte[] nonce = new byte[nonceSize]; + int counter = 0; + for (int i = 0; i < encrypted.Length; i++){ + if (i < nonceSize){ + nonce[i] = encrypted[i]; + continue; + } + justCiphertext[counter] = encrypted[i]; + counter += 1; + } + Assert.IsTrue(Enumerable.SequenceEqual(SecretBox.Open(justCiphertext, nonce, key), message)); + Assert.IsFalse(Enumerable.SequenceEqual(SecretBox.Open(justCiphertext, nonce, key), message2)); + } + + [Test] + public void TestEncryptBytes() + { + byte[] message = UTF8Encoding.UTF8.GetBytes("Hello world"); + byte[] message2 = UTF8Encoding.UTF8.GetBytes("Hello worl2"); + byte[] key = SecretBox.GenerateKey(); + byte[] encrypted = Symmetric.encrypt(message, key); + int nonceSize = 24; + byte[] justCiphertext = new byte[encrypted.Length - nonceSize]; + + byte[] nonce = new byte[nonceSize]; + int counter = 0; + for (int i = 0; i < encrypted.Length; i++){ + if (i < nonceSize){ + nonce[i] = encrypted[i]; + continue; + } + justCiphertext[counter] = encrypted[i]; + counter += 1; + + } + Assert.IsTrue(Enumerable.SequenceEqual(SecretBox.Open(justCiphertext, nonce, key), message)); + Assert.IsFalse(Enumerable.SequenceEqual(SecretBox.Open(justCiphertext, nonce, key), message2)); + + } + + } +} \ No newline at end of file diff --git a/treasurechest/chestcrypto/key-derivation/deriveSymmetric.cs b/treasurechest/chestcrypto/key-derivation/deriveSymmetric.cs deleted file mode 100644 index 1ae637c..0000000 --- a/treasurechest/chestcrypto/key-derivation/deriveSymmetric.cs +++ /dev/null @@ -1,26 +0,0 @@ - -using System.Text; -using Sodium; - -namespace chestcrypto{ - - namespace kdf{ - public class DeterministicSymmetricKey{ - // Test - public static byte[] generate(string passphrase, bool extraSensitive=false){ - var nonce = SecretBox.GenerateNonce(); - int strength = 2; - if (extraSensitive){ - strength = 3; - } - return PasswordHash.ArgonHashBinary(Encoding.UTF8.GetBytes(passphrase), // Passphrase converted to bytes - PasswordHash.ArgonGenerateSalt(), // Salt - strength, strength, - 32); - } - - } - - } - -} diff --git a/treasurechest/chestcrypto/symmetric-crypto/encryptwithpassphrase.cs b/treasurechest/chestcrypto/symmetric-crypto/encryptwithpassphrase.cs deleted file mode 100644 index 9b912ff..0000000 --- a/treasurechest/chestcrypto/symmetric-crypto/encryptwithpassphrase.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Sodium; -using System; -using chestcrypto.kdf; -namespace treasurechest{ - - namespace symmetric{ - - public class EncryptWithPassphrase{ - /* Class name is somewhat misleading as we actually derive a key from a string pass and use the key for secret key crypto*/ - public static byte[] encrypt(byte[] data, string passphrase, bool extraSensitive = false){ - byte[] key = DeterministicSymmetricKey.generate(passphrase, extraSensitive); - return SecretBox.Create(data, SecretBox.GenerateNonce(), key); - } - - } - - } - -} \ No newline at end of file diff --git a/treasurechest/chestcrypto/symmetric/exceptions.cs b/treasurechest/chestcrypto/symmetric/exceptions.cs new file mode 100644 index 0000000..207bea1 --- /dev/null +++ b/treasurechest/chestcrypto/symmetric/exceptions.cs @@ -0,0 +1,23 @@ +using System; +namespace chestcrypto{ + + namespace exceptions{ + public class InvalidKeyLength : Exception + { + public InvalidKeyLength() + { + } + + public InvalidKeyLength(string message) + : base(message) + { + } + + public InvalidKeyLength(string message, Exception inner) + : base(message, inner) + { + } + } + } + +} \ No newline at end of file diff --git a/treasurechest/chestcrypto/symmetric/symmetric-encryption.cs b/treasurechest/chestcrypto/symmetric/symmetric-encryption.cs new file mode 100644 index 0000000..f56b467 --- /dev/null +++ b/treasurechest/chestcrypto/symmetric/symmetric-encryption.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using Sodium; + +namespace chestcrypto{ + + namespace symmetric{ + + public class Symmetric{ + + public static byte[] encrypt(byte[] plaintext, byte[] key){ + if (key.Length != 32){ + throw new exceptions.InvalidKeyLength(); + } + List encrypted = new List(); + byte[] nonce = SecretBox.GenerateNonce(); + encrypted.AddRange(nonce); + byte[] ciphertext = SecretBox.Create(plaintext, nonce, key); + encrypted.AddRange(ciphertext); + return encrypted.ToArray(); + } + public static (byte[] ciphertext, byte[] key) encrypt(byte[] plaintext){ + byte[] key = SecretBox.GenerateKey(); + return (encrypt(plaintext, key), key); + } + + public static byte[] decrypt(byte[] ciphertext, byte[] key){ + // Nonce is first 24 bytes of ciphertext, unencrypted (this is safe according to libsodium docs) + int nonceSize = 24; + byte[] nonce = new byte[nonceSize]; + List message = new List(); + for (int i = 0; i < ciphertext.Length; i++){ + if (i < nonceSize){ + nonce[i] = ciphertext[i]; + continue; + } + message.Add(ciphertext[i]); + } + return SecretBox.Open(message.ToArray(), nonce, key); + } + + } + + } + +} \ No newline at end of file diff --git a/treasurechest/simplepack/Packed.cs b/treasurechest/simplepack/Packed.cs new file mode 100644 index 0000000..65afb64 --- /dev/null +++ b/treasurechest/simplepack/Packed.cs @@ -0,0 +1,16 @@ +namespace chestcrypto{ + + namespace simplepack{ + + public class Packed{ + //private string + //public override string ToString(){ + //} + public Packed(){ + + } + } + + } + +} \ No newline at end of file diff --git a/treasurechest/treasurechest.csproj b/treasurechest/treasurechest.csproj index e9003db..29b365b 100644 --- a/treasurechest/treasurechest.csproj +++ b/treasurechest/treasurechest.csproj @@ -7,6 +7,7 @@ +