From b5f827890309e277bfede25ae477e1872a3f5069 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Thu, 21 May 2020 04:05:32 -0500 Subject: [PATCH] work on keyring and CLI menu driven GUI --- cli/Main.cs | 14 +++-- cli/Menu.cs | 60 +++++++++++++++++++ cli/translations/text.cs | 50 ++++++++++++++++ tests/doublekeyPrivateTest.cs | 17 ++++++ tests/keyring/deletePublic.cs | 2 +- .../chestcrypto/identity/ephemeralkey.cs | 6 +- .../chestcrypto/identity/identity.cs | 4 +- .../chestcrypto/keys/doublekey/private.cs | 17 +++++- treasurechest/keyring/keyring.cs | 28 ++++----- 9 files changed, 169 insertions(+), 29 deletions(-) create mode 100644 cli/Menu.cs create mode 100644 cli/translations/text.cs diff --git a/cli/Main.cs b/cli/Main.cs index 3b6806b..f0ff071 100644 --- a/cli/Main.cs +++ b/cli/Main.cs @@ -1,8 +1,9 @@ using System; using CommandLine; using treasurechest.STDIOWrapper; +using treasurechest; -namespace treasurechest +namespace treasurechestCLI { class Program { @@ -17,15 +18,18 @@ namespace treasurechest bool command = true; if (opts.Version){ - STDIO.O(Version.NAME + " - " + Version.VERSION); + STDIO.O(treasurechest.Version.NAME + " - " + treasurechest.Version.VERSION); + } + else if (opts.Menu){ + new TreasureChestMenu().showMenu(); } else{ command = false; } if (! command){ - STDIO.O(Version.NAME + " - " + Version.VERSION); - STDIO.O("Run with help for more options"); + STDIO.O(treasurechest.Version.NAME + " - " + treasurechest.Version.VERSION); + STDIO.O(new translations.Strings().HELP_TEXT); } } @@ -36,6 +40,8 @@ namespace treasurechest public bool Interactive { get; set; } [Option('v', "version", Required = false, HelpText="Show current version")] public bool Version {get; set;} + [Option('m', "menu", Required = false, HelpText="Interactive CLI menu")] + public bool Menu {get;set;} } } diff --git a/cli/Menu.cs b/cli/Menu.cs new file mode 100644 index 0000000..a5fb48e --- /dev/null +++ b/cli/Menu.cs @@ -0,0 +1,60 @@ +using System; +using CommandLine; +using treasurechest.STDIOWrapper; +using treasurechest; + +namespace treasurechestCLI +{ + + internal class TreasureChestMenu{ + + private string language; + + public TreasureChestMenu(){ + language = translations.GetLanguage.language; + } + + internal void showMenu(){ + translations.Strings strings = new translations.Strings(); + string[] mainMenuOptions = {strings.MAIN_MENU_ENCRYPT, strings.MAIN_MENU_DECRYPT, strings.EXIT}; + STDIO.O(strings.WELCOME); + int counter = 1; + int choice = 0; + int mainMenuOptionsSize = mainMenuOptions.Length; + + while (choice != mainMenuOptions.Length){ + foreach (string option in mainMenuOptions){ + STDIO.O(counter.ToString() + ". " + option); + counter += 1; + } + try{ + choice = Int32.Parse(System.Console.ReadLine()); + } + catch (System.OverflowException){ + // User being silly with input + STDIO.O(strings.MAIN_MENU_SELECT_INTEGER); + counter = 1; + } + catch(System.FormatException){ + // Too lazy to check strings, force them to use int from menu which is faster anyway + STDIO.O(strings.MAIN_MENU_SELECT_INTEGER); + counter = 1; + } + catch(System.ArgumentNullException){ + // Can happen when stream closes (e.g. ctrl-d) + // since menu is intended to be directly human interfaced, user probably wants to exit + choice = mainMenuOptionsSize; + } + if (choice == mainMenuOptionsSize){ + break; + } + else{ + STDIO.O(strings.INVALID_OPTION); + } + counter = 1; + } + } + + } + +} \ No newline at end of file diff --git a/cli/translations/text.cs b/cli/translations/text.cs new file mode 100644 index 0000000..a877fb0 --- /dev/null +++ b/cli/translations/text.cs @@ -0,0 +1,50 @@ +using System.Globalization; +using treasurechest; +namespace treasurechestCLI { + namespace translations { + + internal class GetLanguage{ + internal static string language = CultureInfo.CurrentCulture.TwoLetterISOLanguageName; + } + + public class Strings{ + public string WELCOME; + public string HELP_TEXT; + public string EXIT; + public string MAIN_MENU_ENCRYPT; + public string MAIN_MENU_DECRYPT; + public string INVALID_OPTION; + public string MAIN_MENU_SELECT_INTEGER; + + + public Strings(){ + + switch (GetLanguage.language){ + case "es": + WELCOME = treasurechest.Version.NAME + " - Protege tu valiosa información"; + HELP_TEXT = "Ejecuta help para más opciones"; + EXIT = "Salida"; + MAIN_MENU_ENCRYPT = "Encriptar"; + MAIN_MENU_DECRYPT = "Desencriptar"; + INVALID_OPTION = "Opción inválida"; + MAIN_MENU_SELECT_INTEGER = "Ingrese un número entero desde el menú"; + + break; + case "en": + default: + WELCOME = treasurechest.Version.NAME + " - Protect your treasured information"; + HELP_TEXT = "Run with help for more options"; + EXIT = "Exit"; + MAIN_MENU_ENCRYPT = "Encrypt"; + MAIN_MENU_DECRYPT = "Decrypt"; + INVALID_OPTION = "Invalid option"; + MAIN_MENU_SELECT_INTEGER = "Enter an integer from the menu"; + break; + } + + } + + } + + } +} \ No newline at end of file diff --git a/tests/doublekeyPrivateTest.cs b/tests/doublekeyPrivateTest.cs index 2d34615..0e0fba1 100644 --- a/tests/doublekeyPrivateTest.cs +++ b/tests/doublekeyPrivateTest.cs @@ -12,6 +12,23 @@ namespace DoubleKeyPrivateTests { } + [Test] + public void TestDoublePrivateKeyGetters() + { + byte[] signingKey = PublicKeyAuth.GenerateKeyPair().PrivateKey; + byte[] encryptionKey = PublicKeyBox.GenerateKeyPair().PrivateKey; + + byte[] combinedKey = new byte[signingKey.Length + encryptionKey.Length]; + Buffer.BlockCopy(signingKey, 0, combinedKey, 0, signingKey.Length); + Buffer.BlockCopy(encryptionKey, 0, combinedKey, signingKey.Length, encryptionKey.Length); + + DoublePrivateKey combinedLoad = new chestcrypto.DoublePrivateKey(combinedKey); + + Assert.AreEqual(combinedLoad.getEd25519PrivateKey(), signingKey); + Assert.AreEqual(combinedLoad.getCurve25519PrivateKey(), encryptionKey); + + } + [Test] public void TestDoublePrivateKeyThrowsOnBadLoad() { diff --git a/tests/keyring/deletePublic.cs b/tests/keyring/deletePublic.cs index 1ebb8ce..bcaf643 100644 --- a/tests/keyring/deletePublic.cs +++ b/tests/keyring/deletePublic.cs @@ -7,7 +7,7 @@ using keyring; using chestcrypto; using chestcrypto.exceptions; -namespace KeyRingTests +namespace KeyRingDeletePublicTests { public class Tests { diff --git a/treasurechest/chestcrypto/identity/ephemeralkey.cs b/treasurechest/chestcrypto/identity/ephemeralkey.cs index c6e2452..0194027 100644 --- a/treasurechest/chestcrypto/identity/ephemeralkey.cs +++ b/treasurechest/chestcrypto/identity/ephemeralkey.cs @@ -9,12 +9,8 @@ namespace chestcrypto{ private bool isPrivate; private Identity identity; - - public EphemeralKey(Identity user){ - identity = user; - } public EphemeralKey(Identity identity, byte[] key, int secondsToExpire){ - + } diff --git a/treasurechest/chestcrypto/identity/identity.cs b/treasurechest/chestcrypto/identity/identity.cs index bd26579..c69a20a 100644 --- a/treasurechest/chestcrypto/identity/identity.cs +++ b/treasurechest/chestcrypto/identity/identity.cs @@ -6,10 +6,12 @@ namespace chestcrypto{ internal class Identity { private DoublePrivateKey privateKey; private DoublePublicKey publicKey; + private bool hasPrivate = false; private List ephemeralKeys = new List(); public DoublePublicKey getDoublePublicKey(){return publicKey;} + public DoublePrivateKey getDoublePrivateKey(){return privateKey;} public Identity(){} @@ -20,7 +22,7 @@ namespace chestcrypto{ this.publicKey = publicKey; } public Identity(DoublePrivateKey privateKey){ - + this.privateKey = privateKey; } public Identity(DoublePrivateKey privateKey, List ephemeralKeys){ diff --git a/treasurechest/chestcrypto/keys/doublekey/private.cs b/treasurechest/chestcrypto/keys/doublekey/private.cs index a6d20d6..44846bc 100644 --- a/treasurechest/chestcrypto/keys/doublekey/private.cs +++ b/treasurechest/chestcrypto/keys/doublekey/private.cs @@ -1,3 +1,5 @@ +using Sodium; + namespace chestcrypto{ public class DoublePrivateKey{ @@ -8,10 +10,23 @@ namespace chestcrypto{ private string signingPrivateKeyString; private string encryptPrivateKeyString; + // Test DoubleKeyPrivateTests.Tests.TestDoublePrivateKeyGetters + public byte[] getCurve25519PrivateKey(){return encryptPrivateKey;} + // Test DoubleKeyPrivateTests.Tests.TestDoublePrivateKeyGetters + public byte[] getEd25519PrivateKey(){return signingPrivateKey;} + + public byte[] getCurve25519PublicKey(){ + return PublicKeyBox.GenerateKeyPair(getCurve25519PrivateKey()).PublicKey; + } + public byte[] getEd25519PublicKey(){ + return PublicKeyAuth.GenerateKeyPair(getEd25519PrivateKey()).PublicKey; + } + // Test DoubleKeyPrivateTests.TestDoubleKeyLoad public byte[] getRawDouble(){ return ByteCombiner.Combine(signingPrivateKey, encryptPrivateKey); } + // Test DoubleKeyPrivateTests.TestDoubleKeyLoad public DoublePrivateKey(byte[] sign, byte[] encrypt){ if (sign.Length != 64){ throw new exceptions.InvalidDoubleKeyException("Signing private key must be 64 bytes in length."); @@ -22,7 +37,7 @@ namespace chestcrypto{ signingPrivateKey = sign; encryptPrivateKey = encrypt; } - + // Test DoubleKeyPrivateTests.TestDoubleKeyLoad public DoublePrivateKey(byte[] combinedKey){ if (combinedKey.Length != 96){ throw new exceptions.InvalidDoubleKeyException("Invalid key length, must be 96 bytes in length"); diff --git a/treasurechest/keyring/keyring.cs b/treasurechest/keyring/keyring.cs index 704326b..5e9d4c5 100644 --- a/treasurechest/keyring/keyring.cs +++ b/treasurechest/keyring/keyring.cs @@ -22,19 +22,13 @@ namespace keyring{ return success; } - private int getIdentityListPosition(Identity iden){ - int counter = 0; - bool success = false; - identities.ForEach(delegate(Identity ident) - { - if (ident.getDoublePublicKey().Equals(iden.getDoublePublicKey())){ - success = true; - return; + internal void removeIdentity(Identity iden){identities.Remove(iden);} + + internal Identity getIdentityInstance(DoublePublicKey key){ + foreach (Identity iden in identities){ + if (iden.getDoublePublicKey().Equals(key)){ + return iden; } - counter += 1; - }); - if (success){ - return counter; } throw new NoIdentityException(); } @@ -46,9 +40,6 @@ namespace keyring{ public int getIdentityCount(){return identities.Count;} - public int getIdentityInstance(DoublePublicKey){ - - } public List getIdentityPublicKeys(){ List pubKeys = new List(); @@ -61,7 +52,6 @@ namespace keyring{ public void addPublicKey(DoublePublicKey key){ // Create an Identity with a public key if it does not exist already - Identity newIdentity = new Identity(key); if (identityExists(newIdentity)){ throw new DuplicateIdentityException("An identity with that public key already exists"); @@ -71,8 +61,12 @@ namespace keyring{ } - public void removeIdentityByPubkey(DoublePublicKey key){ + public void addPrivateKey(){ + + } + public void removeIdentityByPubkey(DoublePublicKey key){ + removeIdentity(getIdentityInstance(key)); } }