From 3cd6860527c1dcb399769ff890a5870b4300625f Mon Sep 17 00:00:00 2001 From: Jc Calayag <138150245+Jccqt@users.noreply.github.com> Date: Fri, 11 Jul 2025 22:09:22 +0800 Subject: [PATCH 1/2] Add Autokey encoder --- .../Encoders/AutokeyEncoderTests.cs | 26 +++++++ Algorithms/Encoders/AutokeyEncorder.cs | 68 +++++++++++++++++++ README.md | 1 + 3 files changed, 95 insertions(+) create mode 100644 Algorithms.Tests/Encoders/AutokeyEncoderTests.cs create mode 100644 Algorithms/Encoders/AutokeyEncorder.cs diff --git a/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs new file mode 100644 index 000000000..5ea399261 --- /dev/null +++ b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs @@ -0,0 +1,26 @@ +using System; +using Algorithms.Encoders; +using NUnit.Framework; +using NUnit.Framework.Internal; + +namespace Algorithms.Tests.Encoders +{ + public class AutokeyEncoderTests + { + [Test] + public static void DecodedStringIsTheSame() + { + // Arrange + var plainText = "PLAINTEXT"; + var keyword = "KEYWORD"; + var encoder = new AutokeyEncorder(); + + // Act + var encoded = encoder.Encode(plainText, keyword); + var decoded = encoder.Decode(encoded, keyword); + + // Assert + Assert.That(decoded, Is.EqualTo(plainText)); + } + } +} diff --git a/Algorithms/Encoders/AutokeyEncorder.cs b/Algorithms/Encoders/AutokeyEncorder.cs new file mode 100644 index 000000000..83818db3e --- /dev/null +++ b/Algorithms/Encoders/AutokeyEncorder.cs @@ -0,0 +1,68 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace Algorithms.Encoders +{ + /// + /// Class for AutoKey encoding strings. + /// + public class AutokeyEncorder + { + /// + /// Autokey Cipher is a type of polyalphabetic cipher. + /// This works by choosing a key (a word or short phrase), + /// then you append the plaintext to itself to form a longer key. + /// + /// The string to be appended to the key. + /// The string to be appended to the plaintext. + /// The Autokey encoded string (All Uppercase). + public string Encode(string plainText, string keyword) + { + plainText = Regex.Replace(plainText.ToUpper(), "[^A-Z]", string.Empty); + keyword = keyword.ToUpper(); + + keyword += plainText; + + StringBuilder cipherText = new StringBuilder(); + + for(int i = 0; i < plainText.Length; i++) + { + char plainCharacter = plainText[i]; + char keyCharacter = keyword[i]; + + int encryptedCharacter = (plainCharacter - 'A' + keyCharacter - 'A') % 26 + 'A'; + cipherText.Append((char)encryptedCharacter); + } + + return cipherText.ToString(); + } + + /// + /// Removed the key from the encoded string. + /// + /// The encoded string. + /// The key to be removed from the encoded string. + /// The plaintext (All Uppercase). + public string Decode(string cipherText, string keyword) + { + cipherText = Regex.Replace(cipherText.ToUpper(), "[^A-Z]", string.Empty); + keyword = keyword.ToUpper(); + + StringBuilder plainText = new StringBuilder(); + StringBuilder extendedKeyword = new StringBuilder(keyword); + + for(int i = 0; i < cipherText.Length; i++) + { + char cipherCharacter = cipherText[i]; + char keywordCharacter = extendedKeyword[i]; + + int decryptedCharacter = (cipherCharacter - 'A' - (keywordCharacter - 'A') + 26) % 26 + 'A'; + plainText.Append((char)decryptedCharacter); + extendedKeyword.Append((char)decryptedCharacter); + } + + return plainText.ToString(); + } + } +} diff --git a/README.md b/README.md index 198d2bd76..b9933f9fc 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ find more than one implementation for the same objective but using different alg * [Soundex](./Algorithms/Encoders/SoundexEncoder.cs) * [Feistel](./Algorithms/Encoders/FeistelCipher.cs) * [Blowfish](./Algorithms/Encoders/BlowfishEncoder.cs) + * [Autokey](./Algorithms/Encoders/AutokeyEncoder.cs) * [Graph](./Algorithms/Graph) * [Minimum Spanning Tree](./Algorithms/Graph/MinimumSpanningTree) * [Prim's Algorithm (Adjacency Matrix)](./Algorithms/Graph/MinimumSpanningTree/PrimMatrix.cs) From eca949603016654ef108216e5ba68de3d5c4ab4c Mon Sep 17 00:00:00 2001 From: Jc Calayag <138150245+Jccqt@users.noreply.github.com> Date: Fri, 11 Jul 2025 22:36:15 +0800 Subject: [PATCH 2/2] Added CurrentCulture.InvariantCulture for ToUpper on Autokey encoder --- Algorithms.Tests/Encoders/AutokeyEncoderTests.cs | 2 +- Algorithms/Encoders/AutokeyEncorder.cs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs index 5ea399261..0613e1c65 100644 --- a/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs +++ b/Algorithms.Tests/Encoders/AutokeyEncoderTests.cs @@ -5,7 +5,7 @@ namespace Algorithms.Tests.Encoders { - public class AutokeyEncoderTests + public static class AutokeyEncoderTests { [Test] public static void DecodedStringIsTheSame() diff --git a/Algorithms/Encoders/AutokeyEncorder.cs b/Algorithms/Encoders/AutokeyEncorder.cs index 83818db3e..8dc13d37e 100644 --- a/Algorithms/Encoders/AutokeyEncorder.cs +++ b/Algorithms/Encoders/AutokeyEncorder.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; using System.Text.RegularExpressions; @@ -19,8 +20,8 @@ public class AutokeyEncorder /// The Autokey encoded string (All Uppercase). public string Encode(string plainText, string keyword) { - plainText = Regex.Replace(plainText.ToUpper(), "[^A-Z]", string.Empty); - keyword = keyword.ToUpper(); + plainText = Regex.Replace(plainText.ToUpper(CultureInfo.InvariantCulture), "[^A-Z]", string.Empty); + keyword = keyword.ToUpper(CultureInfo.InvariantCulture); keyword += plainText; @@ -46,8 +47,8 @@ public string Encode(string plainText, string keyword) /// The plaintext (All Uppercase). public string Decode(string cipherText, string keyword) { - cipherText = Regex.Replace(cipherText.ToUpper(), "[^A-Z]", string.Empty); - keyword = keyword.ToUpper(); + cipherText = Regex.Replace(cipherText.ToUpper(CultureInfo.InvariantCulture), "[^A-Z]", string.Empty); + keyword = keyword.ToUpper(CultureInfo.InvariantCulture); StringBuilder plainText = new StringBuilder(); StringBuilder extendedKeyword = new StringBuilder(keyword);