From 9c1a8b1baea742979d385f6aed75b4de27ad286b Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 5 Oct 2023 20:07:11 +0300 Subject: [PATCH 01/24] Add the java source path. --- project.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/project.clj b/project.clj index b612dd7..ab703c5 100644 --- a/project.clj +++ b/project.clj @@ -8,6 +8,7 @@ [org.apache.tika/tika-core "1.28.5"] [org.apache.tika/tika-langdetect "1.28.5"]] :main ^:skip-aot cipher-analytical-machine.core + :java-source-paths ["src/main/java"] :target-path "target/%s" :profiles {:uberjar {:aot :all :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}}) From 0a87ab9e91c977293db75dc6ca761e19fce8dc3b Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 5 Oct 2023 20:07:43 +0300 Subject: [PATCH 02/24] Add the Caesar decrypted interface for Java. --- .../cipher_analytical_machine/ciphers/caesar/Decrypted.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/cipher_analytical_machine/ciphers/caesar/Decrypted.java diff --git a/src/main/java/cipher_analytical_machine/ciphers/caesar/Decrypted.java b/src/main/java/cipher_analytical_machine/ciphers/caesar/Decrypted.java new file mode 100644 index 0000000..1b86df2 --- /dev/null +++ b/src/main/java/cipher_analytical_machine/ciphers/caesar/Decrypted.java @@ -0,0 +1,6 @@ +package cipher_analytical_machine.ciphers.caesar; + +public interface Decrypted { + String decrypt(String message, int key, String symbols); +} + From 40af8401b20746ace5a53958c7d5c8d516fb71db Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 5 Oct 2023 20:08:41 +0300 Subject: [PATCH 03/24] Add a frequency analyzer as a stub. --- .../analizers/caesar/FrequencyAnalyzer.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java diff --git a/src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java b/src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java new file mode 100644 index 0000000..26c2cc5 --- /dev/null +++ b/src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java @@ -0,0 +1,23 @@ +package cipher_analytical_machine.analizers.caesar; + +import cipher_analytical_machine.ciphers.caesar.Decrypted; +import java.util.Map; + +public class FrequencyAnalyzer { + private String ciphertext; + private int key; + private String symbols; + private Decrypted decryptor; + + public FrequencyAnalyzer(String ciphertext, String symbols, Map symbol_frequences, Decrypted decryptor) { + this.ciphertext = ciphertext; + this.key = 1; + this.symbols = symbols; + this.decryptor = decryptor; + } + + public String crack() { + return decryptor.decrypt(ciphertext, key, symbols); + } +} + From 51609b1d27a52de21e498cafcde062e0a3f38bb0 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 5 Oct 2023 20:10:05 +0300 Subject: [PATCH 04/24] Add the clojure wrapper for the frequency analizer and its test. --- src/cipher_analytical_machine/caesar_analyzers.clj | 11 +++++++++++ .../caesar_analyzers_test.clj | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/cipher_analytical_machine/caesar_analyzers.clj b/src/cipher_analytical_machine/caesar_analyzers.clj index 4d71f06..8030d5a 100644 --- a/src/cipher_analytical_machine/caesar_analyzers.clj +++ b/src/cipher_analytical_machine/caesar_analyzers.clj @@ -2,6 +2,8 @@ (:require [cipher-analytical-machine.caesar :as caesar] [clojure.string :as cs] [cipher-analytical-machine.cipher-analyzers :as ca]) + (:import [cipher_analytical_machine.ciphers.caesar Decrypted] + [cipher_analytical_machine.analizers.caesar FrequencyAnalyzer]) (:gen-class)) (defn get-all-texts @@ -46,3 +48,12 @@ (get-key ciphertext symbols letter-frequences) symbols))) +(defn frequency-analizer-get-plaintext + "Return the plaintext from a ciphertext using simple analizer. The function is case-insensitive." + [ciphertext symbols letter-frequences] + (let [decrypt (reify Decrypted + (decrypt [this message key symbols] + (caesar/decrypt-message message key symbols)))] + (-> (new FrequencyAnalyzer ciphertext symbols letter-frequences decrypt) + .crack))) + diff --git a/test/cipher_analytical_machine/caesar_analyzers_test.clj b/test/cipher_analytical_machine/caesar_analyzers_test.clj index 2a06d97..1d26e0c 100644 --- a/test/cipher_analytical_machine/caesar_analyzers_test.clj +++ b/test/cipher_analytical_machine/caesar_analyzers_test.clj @@ -74,3 +74,13 @@ (is (= (cs/lower-case plaintext) (get-plaintext ciphertext symbols frequences)))))) +(deftest frequency-analizer-get-plaintext-test + (let [plaintext "abc" + ciphertext "bca" + key 1 + symbols "abc" + frequences sf/english-letter-frequences] + (testing "The ciphertext is 'bca' and key is 1." + (is (= plaintext + (frequency-analizer-get-plaintext ciphertext symbols frequences)))))) + From 77efa81c54a078dd228ba1fd0710d6ac04ba629b Mon Sep 17 00:00:00 2001 From: KKlochko Date: Mon, 9 Oct 2023 20:00:50 +0300 Subject: [PATCH 05/24] Add the Gitlab CI/CD configuration. --- .gitlab-ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..2e638c4 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,10 @@ +image: clojure:temurin-11-lein-2.10.0-alpine + +stages: + - test + +unit tests: + stage: test + script: + - lein test + From 4d7e9da1d1036fd0b5aacab0673dec83a2a71ffe Mon Sep 17 00:00:00 2001 From: KKlochko Date: Wed, 11 Oct 2023 21:08:18 +0300 Subject: [PATCH 06/24] Refactor the project structure. --- .../analyzers.clj} | 2 +- .../caesar.clj} | 8 +++--- .../language.clj} | 2 +- .../{ => ciphers}/caesar.clj | 2 +- .../{ => cli}/cli.clj | 12 ++++----- .../{ => cli}/file.clj | 2 +- src/cipher_analytical_machine/core.clj | 2 +- .../factories.clj} | 2 +- .../frequences.clj} | 2 +- .../caesar/FrequencyAnalyzer.java | 2 +- .../caesar_test.clj} | 8 +++--- .../language_test.clj} | 4 +-- .../cipher_analyzers_test.clj | 25 ------------------- .../{ => ciphers}/caesar_test.clj | 4 +-- .../factories_test.clj} | 4 +-- 15 files changed, 28 insertions(+), 53 deletions(-) rename src/cipher_analytical_machine/{cipher_analyzers.clj => analyzers/analyzers.clj} (96%) rename src/cipher_analytical_machine/{caesar_analyzers.clj => analyzers/caesar.clj} (88%) rename src/cipher_analytical_machine/{language_analyzer.clj => analyzers/language.clj} (90%) rename src/cipher_analytical_machine/{ => ciphers}/caesar.clj (96%) rename src/cipher_analytical_machine/{ => cli}/cli.clj (94%) rename src/cipher_analytical_machine/{ => cli}/file.clj (91%) rename src/cipher_analytical_machine/{symbol_factories.clj => symbols/factories.clj} (95%) rename src/cipher_analytical_machine/{symbol_frequences.clj => symbols/frequences.clj} (94%) rename src/main/java/cipher_analytical_machine/{analizers => analyzers}/caesar/FrequencyAnalyzer.java (91%) rename test/cipher_analytical_machine/{caesar_analyzers_test.clj => analyzers/caesar_test.clj} (94%) rename test/cipher_analytical_machine/{language_analyzer_test.clj => analyzers/language_test.clj} (93%) delete mode 100644 test/cipher_analytical_machine/cipher_analyzers_test.clj rename test/cipher_analytical_machine/{ => ciphers}/caesar_test.clj (95%) rename test/cipher_analytical_machine/{symbol_factories_test.clj => symbols/factories_test.clj} (94%) diff --git a/src/cipher_analytical_machine/cipher_analyzers.clj b/src/cipher_analytical_machine/analyzers/analyzers.clj similarity index 96% rename from src/cipher_analytical_machine/cipher_analyzers.clj rename to src/cipher_analytical_machine/analyzers/analyzers.clj index b0fb3e5..74ea2df 100644 --- a/src/cipher_analytical_machine/cipher_analyzers.clj +++ b/src/cipher_analytical_machine/analyzers/analyzers.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.cipher-analyzers +(ns cipher-analytical-machine.analyzers.analyzers (:require [clojure.string :as cs]) (:gen-class)) diff --git a/src/cipher_analytical_machine/caesar_analyzers.clj b/src/cipher_analytical_machine/analyzers/caesar.clj similarity index 88% rename from src/cipher_analytical_machine/caesar_analyzers.clj rename to src/cipher_analytical_machine/analyzers/caesar.clj index 8030d5a..aa16145 100644 --- a/src/cipher_analytical_machine/caesar_analyzers.clj +++ b/src/cipher_analytical_machine/analyzers/caesar.clj @@ -1,9 +1,9 @@ -(ns cipher-analytical-machine.caesar-analyzers - (:require [cipher-analytical-machine.caesar :as caesar] +(ns cipher-analytical-machine.analyzers.caesar + (:require [cipher-analytical-machine.ciphers.caesar :as caesar] [clojure.string :as cs] - [cipher-analytical-machine.cipher-analyzers :as ca]) + [cipher-analytical-machine.analyzers.analyzers :as ca]) (:import [cipher_analytical_machine.ciphers.caesar Decrypted] - [cipher_analytical_machine.analizers.caesar FrequencyAnalyzer]) + [cipher_analytical_machine.analyzers.caesar FrequencyAnalyzer]) (:gen-class)) (defn get-all-texts diff --git a/src/cipher_analytical_machine/language_analyzer.clj b/src/cipher_analytical_machine/analyzers/language.clj similarity index 90% rename from src/cipher_analytical_machine/language_analyzer.clj rename to src/cipher_analytical_machine/analyzers/language.clj index 867c17f..ddfc7ab 100644 --- a/src/cipher_analytical_machine/language_analyzer.clj +++ b/src/cipher_analytical_machine/analyzers/language.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.language-analyzer +(ns cipher-analytical-machine.analyzers.language (:import [org.apache.tika.language LanguageIdentifier]) (:gen-class)) diff --git a/src/cipher_analytical_machine/caesar.clj b/src/cipher_analytical_machine/ciphers/caesar.clj similarity index 96% rename from src/cipher_analytical_machine/caesar.clj rename to src/cipher_analytical_machine/ciphers/caesar.clj index cdaba11..6b8b897 100644 --- a/src/cipher_analytical_machine/caesar.clj +++ b/src/cipher_analytical_machine/ciphers/caesar.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.caesar +(ns cipher-analytical-machine.ciphers.caesar (:require [clojure.string :as cs]) (:gen-class)) diff --git a/src/cipher_analytical_machine/cli.clj b/src/cipher_analytical_machine/cli/cli.clj similarity index 94% rename from src/cipher_analytical_machine/cli.clj rename to src/cipher_analytical_machine/cli/cli.clj index 2b198c7..3568516 100644 --- a/src/cipher_analytical_machine/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -1,10 +1,10 @@ -(ns cipher-analytical-machine.cli +(ns cipher-analytical-machine.cli.cli (:require - [cipher-analytical-machine.file :as file] - [cipher-analytical-machine.caesar :as caesar] - [cipher-analytical-machine.caesar-analyzers :as caesar-analyzers] - [cipher-analytical-machine.symbol-factories :as sf] - [cipher-analytical-machine.symbol-frequences :as symbol-frequences] + [cipher-analytical-machine.cli.file :as file] + [cipher-analytical-machine.ciphers.caesar :as caesar] + [cipher-analytical-machine.analyzers.caesar :as caesar-analyzers] + [cipher-analytical-machine.symbols.factories :as sf] + [cipher-analytical-machine.symbols.frequences :as symbol-frequences] [clojure.string :as cs] [clojure.tools.cli :refer [parse-opts]]) (:gen-class)) diff --git a/src/cipher_analytical_machine/file.clj b/src/cipher_analytical_machine/cli/file.clj similarity index 91% rename from src/cipher_analytical_machine/file.clj rename to src/cipher_analytical_machine/cli/file.clj index bc58876..7de67e9 100644 --- a/src/cipher_analytical_machine/file.clj +++ b/src/cipher_analytical_machine/cli/file.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.file +(ns cipher-analytical-machine.cli.file (:require [clojure.java.io :as io]) (:gen-class)) diff --git a/src/cipher_analytical_machine/core.clj b/src/cipher_analytical_machine/core.clj index 5e7e992..e5106b4 100644 --- a/src/cipher_analytical_machine/core.clj +++ b/src/cipher_analytical_machine/core.clj @@ -1,6 +1,6 @@ (ns cipher-analytical-machine.core (:require - [cipher-analytical-machine.cli :as cli]) + [cipher-analytical-machine.cli.cli :as cli]) (:gen-class)) (defn -main diff --git a/src/cipher_analytical_machine/symbol_factories.clj b/src/cipher_analytical_machine/symbols/factories.clj similarity index 95% rename from src/cipher_analytical_machine/symbol_factories.clj rename to src/cipher_analytical_machine/symbols/factories.clj index 65ac2f5..7cbd8a3 100644 --- a/src/cipher_analytical_machine/symbol_factories.clj +++ b/src/cipher_analytical_machine/symbols/factories.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.symbol-factories +(ns cipher-analytical-machine.symbols.factories (:require [clojure.string :as cs]) (:gen-class)) diff --git a/src/cipher_analytical_machine/symbol_frequences.clj b/src/cipher_analytical_machine/symbols/frequences.clj similarity index 94% rename from src/cipher_analytical_machine/symbol_frequences.clj rename to src/cipher_analytical_machine/symbols/frequences.clj index 3878e31..491c475 100644 --- a/src/cipher_analytical_machine/symbol_frequences.clj +++ b/src/cipher_analytical_machine/symbols/frequences.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.symbol-frequences +(ns cipher-analytical-machine.symbols.frequences (:gen-class)) (def english-letter-frequences { diff --git a/src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java similarity index 91% rename from src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java rename to src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java index 26c2cc5..08c4e3b 100644 --- a/src/main/java/cipher_analytical_machine/analizers/caesar/FrequencyAnalyzer.java +++ b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java @@ -1,4 +1,4 @@ -package cipher_analytical_machine.analizers.caesar; +package cipher_analytical_machine.analyzers.caesar; import cipher_analytical_machine.ciphers.caesar.Decrypted; import java.util.Map; diff --git a/test/cipher_analytical_machine/caesar_analyzers_test.clj b/test/cipher_analytical_machine/analyzers/caesar_test.clj similarity index 94% rename from test/cipher_analytical_machine/caesar_analyzers_test.clj rename to test/cipher_analytical_machine/analyzers/caesar_test.clj index 1d26e0c..894755a 100644 --- a/test/cipher_analytical_machine/caesar_analyzers_test.clj +++ b/test/cipher_analytical_machine/analyzers/caesar_test.clj @@ -1,9 +1,9 @@ -(ns cipher-analytical-machine.caesar-analyzers-test +(ns cipher-analytical-machine.analyzers.caesar-test (:require [clojure.test :refer :all] - [cipher-analytical-machine.caesar-analyzers :refer :all] - [cipher-analytical-machine.symbol-frequences :as sf] - [cipher-analytical-machine.cipher-analyzers :as ca] + [cipher-analytical-machine.analyzers.caesar :refer :all] + [cipher-analytical-machine.symbols.frequences :as sf] + [cipher-analytical-machine.analyzers.analyzers :as ca] [clojure.string :as cs])) (deftest get-all-texts-test diff --git a/test/cipher_analytical_machine/language_analyzer_test.clj b/test/cipher_analytical_machine/analyzers/language_test.clj similarity index 93% rename from test/cipher_analytical_machine/language_analyzer_test.clj rename to test/cipher_analytical_machine/analyzers/language_test.clj index c380455..63317f6 100644 --- a/test/cipher_analytical_machine/language_analyzer_test.clj +++ b/test/cipher_analytical_machine/analyzers/language_test.clj @@ -1,7 +1,7 @@ -(ns cipher-analytical-machine.language-analyzer-test +(ns cipher-analytical-machine.analyzers.language-test (:require [clojure.test :refer :all] - [cipher-analytical-machine.language-analyzer :refer :all] + [cipher-analytical-machine.analyzers.language :refer :all] )) (deftest detect-language-test diff --git a/test/cipher_analytical_machine/cipher_analyzers_test.clj b/test/cipher_analytical_machine/cipher_analyzers_test.clj deleted file mode 100644 index 16991f2..0000000 --- a/test/cipher_analytical_machine/cipher_analyzers_test.clj +++ /dev/null @@ -1,25 +0,0 @@ -(ns cipher-analytical-machine.cipher-analyzers-test - (:require - [clojure.test :refer :all] - [cipher-analytical-machine.cipher-analyzers :refer :all])) - -(deftest count-characters-test - (testing "Count two dublicates and one uniq character from a string." - (is (= {\a 2 \b 1} - (count-characters "aba"))))) - -(deftest chi-squared-letter-statistic-test - (testing "If the frequence of A is 0.1, the text length is 100 and contains 20 times, then the chi-squared is 10." - (is (= 10.0 - (chi-squared-letter-statistic 20 0.1 100)))) - - (testing "If the frequence of A is 0.1, the text length is 10 and contains 5 times, then the chi-squared is 16.0." - (is (= 16.0 - (chi-squared-letter-statistic 5 0.1 10))))) - -(deftest chi-squared-statistic-test - (let [text "aaaaabbbbb"] - (testing "If the frequences of a and b is 0.1, the text length is 10 and contains them 5 times, then score is 32." - (is (= 32.0 - (chi-squared-statistic text {\a 0.1 \b 0.1})))))) - diff --git a/test/cipher_analytical_machine/caesar_test.clj b/test/cipher_analytical_machine/ciphers/caesar_test.clj similarity index 95% rename from test/cipher_analytical_machine/caesar_test.clj rename to test/cipher_analytical_machine/ciphers/caesar_test.clj index e1b773e..3611c86 100644 --- a/test/cipher_analytical_machine/caesar_test.clj +++ b/test/cipher_analytical_machine/ciphers/caesar_test.clj @@ -1,7 +1,7 @@ -(ns cipher-analytical-machine.caesar-test +(ns cipher-analytical-machine.ciphers.caesar-test (:require [clojure.test :refer :all] - [cipher-analytical-machine.caesar :refer :all] + [cipher-analytical-machine.ciphers.caesar :refer :all] )) (deftest calculate-char-index-test diff --git a/test/cipher_analytical_machine/symbol_factories_test.clj b/test/cipher_analytical_machine/symbols/factories_test.clj similarity index 94% rename from test/cipher_analytical_machine/symbol_factories_test.clj rename to test/cipher_analytical_machine/symbols/factories_test.clj index b00d054..0a85f02 100644 --- a/test/cipher_analytical_machine/symbol_factories_test.clj +++ b/test/cipher_analytical_machine/symbols/factories_test.clj @@ -1,7 +1,7 @@ -(ns cipher-analytical-machine.symbol-factories-test +(ns cipher-analytical-machine.symbols.factories-test (:require [clojure.test :refer :all] - [cipher-analytical-machine.symbol-factories :refer :all] + [cipher-analytical-machine.symbols.factories :refer :all] )) (deftest english-alphabet-factory-test From 476a24c90044177af9670ac654b5c81f0cf8bbae Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 12 Oct 2023 21:51:29 +0300 Subject: [PATCH 07/24] Fix the typo "frequences" to frequencies. --- .../analyzers/analyzers.clj | 6 ++-- .../analyzers/caesar.clj | 12 ++++---- src/cipher_analytical_machine/cli/cli.clj | 4 +-- .../symbols/frequences.clj | 2 +- .../analyzers/caesar_test.clj | 28 +++++++++---------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/cipher_analytical_machine/analyzers/analyzers.clj b/src/cipher_analytical_machine/analyzers/analyzers.clj index 74ea2df..d463afe 100644 --- a/src/cipher_analytical_machine/analyzers/analyzers.clj +++ b/src/cipher_analytical_machine/analyzers/analyzers.clj @@ -21,16 +21,16 @@ (defn chi-squared-statistic "To calculate the frequency distribution of a language. More detail about the algorithm here: http://practicalcryptography.com/cryptanalysis/text-characterisation/chi-squared-statistic/" - [text letter-frequences] + [text letter-frequencies] (let [length-text (count text) letter-counts (count-characters (cs/lower-case text))] ;letter-counts (reduce (fn [acc [char count]] (+ acc - (if (contains? letter-frequences char) + (if (contains? letter-frequencies char) (chi-squared-letter-statistic count - (get letter-frequences char) + (get letter-frequencies char) length-text) 0))) 0 diff --git a/src/cipher_analytical_machine/analyzers/caesar.clj b/src/cipher_analytical_machine/analyzers/caesar.clj index aa16145..6bc5af2 100644 --- a/src/cipher_analytical_machine/analyzers/caesar.clj +++ b/src/cipher_analytical_machine/analyzers/caesar.clj @@ -17,9 +17,9 @@ (defn get-all-scores "For pairs (key, plaintext) finds scores and return list of pairs [key, score]." - [letter-frequences pairs] + [letter-frequencies pairs] (map (fn [[key text]] - [key (ca/chi-squared-statistic text letter-frequences)]) + [key (ca/chi-squared-statistic text letter-frequencies)]) pairs)) (defn get-min-score-pair @@ -34,18 +34,18 @@ (defn get-key "To find the key with frequencies of letters." - [ciphertext symbols letter-frequences] + [ciphertext symbols letter-frequencies] (->> (get-all-texts ciphertext symbols) - (get-all-scores letter-frequences) + (get-all-scores letter-frequencies) (get-min-score-pair) (first))) (defn get-plaintext "Return the plaintext from a ciphertext. The function is case-insensitive." - [ciphertext symbols letter-frequences] + [ciphertext symbols letter-frequencies] (let [ciphertext (cs/lower-case ciphertext)] (caesar/decrypt-message ciphertext - (get-key ciphertext symbols letter-frequences) + (get-key ciphertext symbols letter-frequencies) symbols))) (defn frequency-analizer-get-plaintext diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index 3568516..22b1841 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -4,7 +4,7 @@ [cipher-analytical-machine.ciphers.caesar :as caesar] [cipher-analytical-machine.analyzers.caesar :as caesar-analyzers] [cipher-analytical-machine.symbols.factories :as sf] - [cipher-analytical-machine.symbols.frequences :as symbol-frequences] + [cipher-analytical-machine.symbols.frequencies :as symbol-frequencies] [clojure.string :as cs] [clojure.tools.cli :refer [parse-opts]]) (:gen-class)) @@ -155,7 +155,7 @@ [options arguments action-type] (let [message (:message options) symbols (:symbols options) - frequencies symbol-frequences/english-letter-frequences] + frequencies symbol-frequencies/english-letter-frequencies] (cond (= action-type :cracking) (caesar-analyzers/get-plaintext message symbols frequencies) diff --git a/src/cipher_analytical_machine/symbols/frequences.clj b/src/cipher_analytical_machine/symbols/frequences.clj index 491c475..c9e0ac4 100644 --- a/src/cipher_analytical_machine/symbols/frequences.clj +++ b/src/cipher_analytical_machine/symbols/frequences.clj @@ -1,4 +1,4 @@ -(ns cipher-analytical-machine.symbols.frequences +(ns cipher-analytical-machine.symbols.frequencies (:gen-class)) (def english-letter-frequences { diff --git a/test/cipher_analytical_machine/analyzers/caesar_test.clj b/test/cipher_analytical_machine/analyzers/caesar_test.clj index 894755a..b5a113b 100644 --- a/test/cipher_analytical_machine/analyzers/caesar_test.clj +++ b/test/cipher_analytical_machine/analyzers/caesar_test.clj @@ -2,7 +2,7 @@ (:require [clojure.test :refer :all] [cipher-analytical-machine.analyzers.caesar :refer :all] - [cipher-analytical-machine.symbols.frequences :as sf] + [cipher-analytical-machine.symbols.frequencies :as sf] [cipher-analytical-machine.analyzers.analyzers :as ca] [clojure.string :as cs])) @@ -25,9 +25,9 @@ (testing "There're 27 combinations for a 'Hello World'." (let [ciphertext "khoorczruog" symbols "abcdefghijklmnopqrstuvwxyz " - frequences sf/english-letter-frequences + frequencies sf/english-letter-frequencies text-pairs (get-all-texts ciphertext symbols)] - (is (= 27 (count (get-all-scores frequences text-pairs))))))) + (is (= 27 (count (get-all-scores frequencies text-pairs))))))) (deftest get-min-score-pair-test (testing "If a key is one, then the min score pair is 15." @@ -40,47 +40,47 @@ ciphertext "khoorczruog" key 3 symbols "abcdefghijklmnopqrstuvwxyz " - frequences sf/english-letter-frequences] + frequencies sf/english-letter-frequencies] (testing "The plaintext is encrypted with 3 as the key." - (is (= key (get-key ciphertext symbols frequences))))) + (is (= key (get-key ciphertext symbols frequencies))))) (let [; З поеми "Кавказ" Тараса Григоровича Шевченка: plaintext "Борітеся – поборете, Вам Бог помагає! За вас правда, за вас слава. І воля святая!" ciphertext "жхчощйшде–ецхжхчйщй,езєуежхиецхуєиєк!емєезєшецчєзїє,емєезєшештєзє.еоезхтдешздщєд!" key 7 symbols "абвгґдеєжзиіїйклмнопрстуфхцчшщьюя " - frequences sf/ukrainian-letter-frequences] + frequencies sf/ukrainian-letter-frequencies] (testing "The plaintext is encrypted with 3 as the key." - (is (= key (get-key ciphertext symbols frequences)))))) + (is (= key (get-key ciphertext symbols frequencies)))))) (deftest get-plaintext-test (let [plaintext "hello world" ciphertext "khoorczruog" symbols "abcdefghijklmnopqrstuvwxyz " - frequences sf/english-letter-frequences] + frequencies sf/english-letter-frequencies] (testing "The plaintext is encrypted with 3 as the key." - (is (= plaintext (get-plaintext ciphertext symbols frequences)))) + (is (= plaintext (get-plaintext ciphertext symbols frequencies)))) (testing "The ciphertext is case-insensitive." - (is (= plaintext (get-plaintext "KhoorcZruog" symbols frequences))))) + (is (= plaintext (get-plaintext "KhoorcZruog" symbols frequencies))))) (let [; З поеми "Кавказ" Тараса Григоровича Шевченка: plaintext "Борітеся – поборете, Вам Бог помагає! За вас правда, за вас слава. І воля святая!" ciphertext "жхчощйшде–ецхжхчйщй,езєуежхиецхуєиєк!емєезєшецчєзїє,емєезєшештєзє.еоезхтдешздщєд!" key 7 symbols "абвгґдеєжзиіїйклмнопрстуфхцчшщьюя " - frequences sf/ukrainian-letter-frequences] + frequencies sf/ukrainian-letter-frequencies] (testing "The ciphertext is case-insensitive." (is (= (cs/lower-case plaintext) - (get-plaintext ciphertext symbols frequences)))))) + (get-plaintext ciphertext symbols frequencies)))))) (deftest frequency-analizer-get-plaintext-test (let [plaintext "abc" ciphertext "bca" key 1 symbols "abc" - frequences sf/english-letter-frequences] + frequencies sf/english-letter-frequencies] (testing "The ciphertext is 'bca' and key is 1." (is (= plaintext - (frequency-analizer-get-plaintext ciphertext symbols frequences)))))) + (frequency-analizer-get-plaintext ciphertext symbols frequencies)))))) From de35d4e2d39298cef4736d464324f80d080fa34a Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 12 Oct 2023 22:04:39 +0300 Subject: [PATCH 08/24] Add the function to make a frequency string from a map. --- .../symbols/{frequences.clj => frequencies.clj} | 14 ++++++++++++-- .../symbols/frequencies_test.clj | 11 +++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) rename src/cipher_analytical_machine/symbols/{frequences.clj => frequencies.clj} (69%) create mode 100644 test/cipher_analytical_machine/symbols/frequencies_test.clj diff --git a/src/cipher_analytical_machine/symbols/frequences.clj b/src/cipher_analytical_machine/symbols/frequencies.clj similarity index 69% rename from src/cipher_analytical_machine/symbols/frequences.clj rename to src/cipher_analytical_machine/symbols/frequencies.clj index c9e0ac4..dad6368 100644 --- a/src/cipher_analytical_machine/symbols/frequences.clj +++ b/src/cipher_analytical_machine/symbols/frequencies.clj @@ -1,7 +1,17 @@ (ns cipher-analytical-machine.symbols.frequencies (:gen-class)) -(def english-letter-frequences { +(defn map-to-string + "Convert the map of frequencies to the frequency string. Letters are sorted by frequency in descending order." + [frequency-map] + (->> frequency-map + (reduce (fn [acc el] (conj acc el)) []) + (sort-by last) + (map first) + (reverse) + (apply str))) + +(def english-letter-frequencies { \a 0.0804 \b 0.0154 \c 0.0306 @@ -30,7 +40,7 @@ \z 0.0009 }) -(def ukrainian-letter-frequences { +(def ukrainian-letter-frequencies { \а 0.064 \б 0.013 \в 0.046 diff --git a/test/cipher_analytical_machine/symbols/frequencies_test.clj b/test/cipher_analytical_machine/symbols/frequencies_test.clj new file mode 100644 index 0000000..1db5bd0 --- /dev/null +++ b/test/cipher_analytical_machine/symbols/frequencies_test.clj @@ -0,0 +1,11 @@ +(ns cipher-analytical-machine.symbols.frequencies-test + (:require + [clojure.test :refer :all] + [cipher-analytical-machine.symbols.frequencies :refer :all])) + +(deftest calculate-char-index-test + (let [symbol-map english-letter-frequencies] + (testing "The map must be converted to 'etaoinsrhldcumfpgwybvkxjqz'" + (is (= "etaoinsrhldcumfpgwybvkxjqz" + (map-to-string symbol-map)))))) + From 043257bb6403844b63a4d3d59bde36beeea43b56 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Thu, 12 Oct 2023 22:07:02 +0300 Subject: [PATCH 09/24] Update the FrequencyAnalyzer to use the frequency string instead. --- src/cipher_analytical_machine/analyzers/caesar.clj | 4 ++-- .../analyzers/caesar/FrequencyAnalyzer.java | 4 +++- test/cipher_analytical_machine/analyzers/caesar_test.clj | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cipher_analytical_machine/analyzers/caesar.clj b/src/cipher_analytical_machine/analyzers/caesar.clj index 6bc5af2..e538c1e 100644 --- a/src/cipher_analytical_machine/analyzers/caesar.clj +++ b/src/cipher_analytical_machine/analyzers/caesar.clj @@ -50,10 +50,10 @@ (defn frequency-analizer-get-plaintext "Return the plaintext from a ciphertext using simple analizer. The function is case-insensitive." - [ciphertext symbols letter-frequences] + [ciphertext symbols letter-frequencies-string] (let [decrypt (reify Decrypted (decrypt [this message key symbols] (caesar/decrypt-message message key symbols)))] - (-> (new FrequencyAnalyzer ciphertext symbols letter-frequences decrypt) + (-> (new FrequencyAnalyzer ciphertext symbols letter-frequencies-string decrypt) .crack))) diff --git a/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java index 08c4e3b..31a68d8 100644 --- a/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java +++ b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java @@ -7,12 +7,14 @@ public class FrequencyAnalyzer { private String ciphertext; private int key; private String symbols; + private String symbol_frequences; private Decrypted decryptor; - public FrequencyAnalyzer(String ciphertext, String symbols, Map symbol_frequences, Decrypted decryptor) { + public FrequencyAnalyzer(String ciphertext, String symbols, String symbol_frequences, Decrypted decryptor) { this.ciphertext = ciphertext; this.key = 1; this.symbols = symbols; + this.symbol_frequences = symbol_frequences; this.decryptor = decryptor; } diff --git a/test/cipher_analytical_machine/analyzers/caesar_test.clj b/test/cipher_analytical_machine/analyzers/caesar_test.clj index b5a113b..84e1bba 100644 --- a/test/cipher_analytical_machine/analyzers/caesar_test.clj +++ b/test/cipher_analytical_machine/analyzers/caesar_test.clj @@ -79,7 +79,7 @@ ciphertext "bca" key 1 symbols "abc" - frequencies sf/english-letter-frequencies] + frequencies "etaoinsrhldcumfpgwybvkxjqz"] (testing "The ciphertext is 'bca' and key is 1." (is (= plaintext (frequency-analizer-get-plaintext ciphertext symbols frequencies)))))) From ac2cf2ac580c72a965e43192abbaa3edfed21972 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Fri, 13 Oct 2023 21:46:48 +0300 Subject: [PATCH 10/24] Fix the bug that the default language symbols override the symbols. --- src/cipher_analytical_machine/cli/cli.clj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index 22b1841..c0230b8 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -122,8 +122,10 @@ (defn set-symbols "Set defaults symbols for a language." [options] - (set-option options :symbols - (sf/default-symbol-factory (:language options)))) + (if (contains? options :language) + (set-option options :symbols + (sf/default-symbol-factory (:language options))) + options)) (defn load-and-set-option "Load the option and set it." From a44fc24bee6b072b00f2a2f600d24d4716fb5507 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 14 Oct 2023 17:10:03 +0300 Subject: [PATCH 11/24] Refactor to move options to a separated file. --- src/cipher_analytical_machine/cli/cli.clj | 25 ++------------ src/cipher_analytical_machine/cli/options.clj | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 src/cipher_analytical_machine/cli/options.clj diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index c0230b8..689fed4 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -5,32 +5,11 @@ [cipher-analytical-machine.analyzers.caesar :as caesar-analyzers] [cipher-analytical-machine.symbols.factories :as sf] [cipher-analytical-machine.symbols.frequencies :as symbol-frequencies] + [cipher-analytical-machine.cli.options :as options] [clojure.string :as cs] [clojure.tools.cli :refer [parse-opts]]) (:gen-class)) -(def cipher-options - #{"Caesar"}) - -(def language-options - #{"en", "uk"}) - -(def cli-options - [["-m" "--message MESSAGE" "The message will be encrypted or decrypted."] - ["-M" "--message-file MESSAGE-FILE" "The file contains the message that will be encrypted or decrypted."] - ["-k" "--key KEY" "The key will be used to encrypt or decrypt."] - ["-c" "--cipher CIPHER" "The cipher will be used to encrypt or decrypt a message." - :default "Caesar"] - ["-e" "--encrypt" "Encrypt the message."] - ["-d" "--decrypt" "Decrypt the message."] - ["-s" "--symbols" "The string will be used as a set of symbols for a cipher." - :default (sf/default-symbol-factory "en")] - ["-l" "--language CODE" "The string will be used to set a default symbols for a cipher." - :validate [#(contains? language-options %) "Must be a code from the list: en, uk!!!"]] - ["-C" "--cracking" "Cracking the encrypted message."] - ["-O" "--output-file OUTPUT-FILE" "Save the program output to a file."] - ["-h" "--help"]]) - (defn usage [options-summary] (->> ["This is cipher-analytical-machine. It can help you to learn how ciphers works." "" @@ -55,7 +34,7 @@ should exit (with an error message, and optional ok status), or a map indicating the action the program should take and the options provided." [args] - (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)] + (let [{:keys [options arguments errors summary]} (parse-opts args options/cli-options)] (cond (:help options) {:exit-message (usage summary) :ok? true} diff --git a/src/cipher_analytical_machine/cli/options.clj b/src/cipher_analytical_machine/cli/options.clj new file mode 100644 index 0000000..fcf1023 --- /dev/null +++ b/src/cipher_analytical_machine/cli/options.clj @@ -0,0 +1,33 @@ +(ns cipher-analytical-machine.cli.options + (:require + [cipher-analytical-machine.symbols.factories :as sf] + [clojure.string :as cs]) + (:gen-class)) + +(def cipher-options + #{"Caesar"}) + +(def default-cipher "Caesar") + +(def language-options + #{"en", "uk"}) + +(def default-symbols + (sf/default-symbol-factory "en")) + +(def cli-options + [["-m" "--message MESSAGE" "The message will be encrypted or decrypted."] + ["-M" "--message-file MESSAGE-FILE" "The file contains the message that will be encrypted or decrypted."] + ["-k" "--key KEY" "The key will be used to encrypt or decrypt."] + ["-c" "--cipher CIPHER" "The cipher will be used to encrypt or decrypt a message." + :default default-cipher] + ["-e" "--encrypt" "Encrypt the message."] + ["-d" "--decrypt" "Decrypt the message."] + ["-s" "--symbols SYMBOLS" "The string will be used as a set of symbols for a cipher." + :default default-symbols] + ["-l" "--language CODE" "The string will be used to set a default symbols for a cipher." + :validate [#(contains? language-options %) "Must be a code from the list: en, uk!!!"]] + ["-C" "--cracking" "Cracking the encrypted message."] + ["-O" "--output-file OUTPUT-FILE" "Save the program output to a file."] + ["-h" "--help"]]) + From 6339774bd13238fa0113b3aa995f49c952f456ab Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 14 Oct 2023 17:22:03 +0300 Subject: [PATCH 12/24] Add the analyzer options and their actions. --- src/cipher_analytical_machine/cli/cli.clj | 20 +++++++++++++++---- src/cipher_analytical_machine/cli/options.clj | 4 ++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index 689fed4..73f349f 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -132,14 +132,26 @@ (save-output output options)) (println output)) -(defn cracking-actions - [options arguments action-type] - (let [message (:message options) +(defn cracking-caesar + [options arguments] + (let [analyzer (:analyzer options) + message (:message options) symbols (:symbols options) frequencies symbol-frequencies/english-letter-frequencies] (cond - (= action-type :cracking) + (= analyzer "Chi^2") (caesar-analyzers/get-plaintext message symbols frequencies) + + (= analyzer "Frequency") + (caesar-analyzers/frequency-analizer-get-plaintext message symbols + (symbol-frequencies/map-to-string frequencies))))) + +(defn cracking-actions + [options arguments action-type] + (let [cipher (:cipher options)] + (cond + (= cipher "Caesar") + (cracking-caesar options arguments) ))) (defn crypt-actions diff --git a/src/cipher_analytical_machine/cli/options.clj b/src/cipher_analytical_machine/cli/options.clj index fcf1023..a1c1434 100644 --- a/src/cipher_analytical_machine/cli/options.clj +++ b/src/cipher_analytical_machine/cli/options.clj @@ -9,6 +9,9 @@ (def default-cipher "Caesar") +(def analyzers-options + {"Caesar" #{"Chi^2" "Frequency"}}) + (def language-options #{"en", "uk"}) @@ -28,6 +31,7 @@ ["-l" "--language CODE" "The string will be used to set a default symbols for a cipher." :validate [#(contains? language-options %) "Must be a code from the list: en, uk!!!"]] ["-C" "--cracking" "Cracking the encrypted message."] + ["-a" "--analyzer ANALYZER" "The way of cracking."] ["-O" "--output-file OUTPUT-FILE" "Save the program output to a file."] ["-h" "--help"]]) From 2f0254f6770f7b280b856c84e8f43a22dff3f597 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 14 Oct 2023 17:26:20 +0300 Subject: [PATCH 13/24] Add the available ciphers and analyzer for the help. --- src/cipher_analytical_machine/cli/cli.clj | 6 +++++ src/cipher_analytical_machine/cli/options.clj | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index 73f349f..ddc269b 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -17,6 +17,12 @@ "" "Options:" options-summary + "" + "Available values" + "" + (options/get-available-cipher-options-as-string) + "" + (options/get-available-analyzers-options-as-string) ""] (cs/join \newline))) diff --git a/src/cipher_analytical_machine/cli/options.clj b/src/cipher_analytical_machine/cli/options.clj index a1c1434..34eb18d 100644 --- a/src/cipher_analytical_machine/cli/options.clj +++ b/src/cipher_analytical_machine/cli/options.clj @@ -4,14 +4,41 @@ [clojure.string :as cs]) (:gen-class)) +(defn option-values-as-row + "Return the formatted string of values for an option." + [option values] + (str option ": " (cs/join ", " values))) + +(defn option-values-as-list + "Return the formatted string of values for an option as a multiline list." + [option values] + (str option ": \n - " (cs/join "\n - " values))) + +(defn map-of-option-value-as-list + "Return the formatted string of values for an option as a multiline list. + The values are a map of pairs (suboption and its options)." + [option values] + (let [values (map #(apply option-values-as-row %) values)] + (option-values-as-list option values))) + (def cipher-options #{"Caesar"}) (def default-cipher "Caesar") +(defn get-available-cipher-options-as-string + "Return the formatted string of analyzers options." + [] + (option-values-as-row "Ciphers" cipher-options)) + (def analyzers-options {"Caesar" #{"Chi^2" "Frequency"}}) +(defn get-available-analyzers-options-as-string + "Return the formatted string of analyzers options." + [] + (map-of-option-value-as-list "Analyzers" analyzers-options)) + (def language-options #{"en", "uk"}) From ef87a719a3485d16c88b60ee989e1591b80fa81c Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 14 Oct 2023 17:28:21 +0300 Subject: [PATCH 14/24] Add validations to check if a cipher or an analyzer is available. --- src/cipher_analytical_machine/cli/cli.clj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index ddc269b..c92d888 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -62,6 +62,16 @@ (file/is-file-exists? (:output-file options))) {:exit-message (error-msg ["Please, choose another file!!! Overwriting was prevented!!!"])} + (false? (contains? options/cipher-options (:cipher options))) + {:exit-message (error-msg ["Please, choose an available cipher!!!\n" + (options/get-available-cipher-options-as-string)])} + + (and (map-has-keys? options [:cipher, :cracking, :analyzer]) + (false? (contains? + (get options/analyzers-options (:cipher options)) (:analyzer options)))) + {:exit-message (error-msg ["Please, choose an available analyzer!!!\n" + (options/get-available-analyzers-options-as-string)])} + (and (map-has-keys? options [:cipher, :key]) (or (contains? options :message) (contains? options :message-file)) From b53559030f41bfd9b245abcb903266c69be0018b Mon Sep 17 00:00:00 2001 From: Kryls1fer Date: Sat, 14 Oct 2023 21:18:50 +0300 Subject: [PATCH 15/24] Update the frequency analyzer. --- .../analyzers/caesar/FrequencyAnalyzer.java | 39 +++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java index 31a68d8..c499de3 100644 --- a/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java +++ b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java @@ -1,25 +1,50 @@ package cipher_analytical_machine.analyzers.caesar; import cipher_analytical_machine.ciphers.caesar.Decrypted; + +import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; public class FrequencyAnalyzer { private String ciphertext; - private int key; private String symbols; private String symbol_frequences; private Decrypted decryptor; public FrequencyAnalyzer(String ciphertext, String symbols, String symbol_frequences, Decrypted decryptor) { - this.ciphertext = ciphertext; - this.key = 1; - this.symbols = symbols; - this.symbol_frequences = symbol_frequences; - this.decryptor = decryptor; + this.ciphertext = ciphertext; + this.symbol_frequences = symbol_frequences; + this.symbols = symbols; + this.decryptor = decryptor; } public String crack() { - return decryptor.decrypt(ciphertext, key, symbols); + // Знаходимо кількість літер + Map encryptedLetterCounts = new HashMap<>(); + + for (char c : ciphertext.toLowerCase().toCharArray()) { + encryptedLetterCounts.put(c, encryptedLetterCounts.getOrDefault(c, 0) + 1); + } + + // Знаходимо букву, яка зустрічається найчастіше + char mostFrequentEncryptedLetter = ' '; + int mostFrequentEncryptedLetterCount = 0; + + for (Entry entry : encryptedLetterCounts.entrySet()) { + if (entry.getValue() > mostFrequentEncryptedLetterCount) { + mostFrequentEncryptedLetter = entry.getKey(); + mostFrequentEncryptedLetterCount = entry.getValue(); + } + } + + // Обчислимо зміщення + int size = symbols.length(); + int indexOfMostFrequentEncryptedLetter = symbols.indexOf(mostFrequentEncryptedLetter); + int indexOfMostFrequentLetter = symbols.indexOf(symbol_frequences.charAt(0)); + int shift = (indexOfMostFrequentEncryptedLetter - indexOfMostFrequentLetter) % size; + + return decryptor.decrypt(ciphertext, shift, symbols); } } From a56704226b1cab8a8199567613cd754b94f7fea8 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 14 Oct 2023 21:32:56 +0300 Subject: [PATCH 16/24] Add the IsNonsense interface for FrequencyAnalyzer. --- src/cipher_analytical_machine/analyzers/caesar.clj | 11 ++++++++--- src/cipher_analytical_machine/cli/cli.clj | 3 ++- .../analyzers/caesar/FrequencyAnalyzer.java | 5 ++++- .../analyzers/caesar/IsNonsense.java | 6 ++++++ 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 src/main/java/cipher_analytical_machine/analyzers/caesar/IsNonsense.java diff --git a/src/cipher_analytical_machine/analyzers/caesar.clj b/src/cipher_analytical_machine/analyzers/caesar.clj index e538c1e..77f337b 100644 --- a/src/cipher_analytical_machine/analyzers/caesar.clj +++ b/src/cipher_analytical_machine/analyzers/caesar.clj @@ -1,8 +1,10 @@ (ns cipher-analytical-machine.analyzers.caesar (:require [cipher-analytical-machine.ciphers.caesar :as caesar] [clojure.string :as cs] + [cipher-analytical-machine.analyzers.language :as language] [cipher-analytical-machine.analyzers.analyzers :as ca]) (:import [cipher_analytical_machine.ciphers.caesar Decrypted] + [cipher_analytical_machine.analyzers.caesar IsNonsense] [cipher_analytical_machine.analyzers.caesar FrequencyAnalyzer]) (:gen-class)) @@ -50,10 +52,13 @@ (defn frequency-analizer-get-plaintext "Return the plaintext from a ciphertext using simple analizer. The function is case-insensitive." - [ciphertext symbols letter-frequencies-string] + [ciphertext symbols letter-frequencies-string language-code] (let [decrypt (reify Decrypted (decrypt [this message key symbols] - (caesar/decrypt-message message key symbols)))] - (-> (new FrequencyAnalyzer ciphertext symbols letter-frequencies-string decrypt) + (caesar/decrypt-message message key symbols))) + is-nonsense (reify IsNonsense + (isNonsense [this message] + (language/is-nonsense? message language-code)))] + (-> (new FrequencyAnalyzer ciphertext symbols letter-frequencies-string decrypt is-nonsense) .crack))) diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index c92d888..7c5fa5e 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -160,7 +160,8 @@ (= analyzer "Frequency") (caesar-analyzers/frequency-analizer-get-plaintext message symbols - (symbol-frequencies/map-to-string frequencies))))) + (symbol-frequencies/map-to-string frequencies) + (:language options "en"))))) (defn cracking-actions [options arguments action-type] diff --git a/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java index c499de3..ac75e0f 100644 --- a/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java +++ b/src/main/java/cipher_analytical_machine/analyzers/caesar/FrequencyAnalyzer.java @@ -1,5 +1,6 @@ package cipher_analytical_machine.analyzers.caesar; +import cipher_analytical_machine.analyzers.caesar.IsNonsense; import cipher_analytical_machine.ciphers.caesar.Decrypted; import java.util.HashMap; @@ -11,12 +12,14 @@ public class FrequencyAnalyzer { private String symbols; private String symbol_frequences; private Decrypted decryptor; + private IsNonsense isNonsense; - public FrequencyAnalyzer(String ciphertext, String symbols, String symbol_frequences, Decrypted decryptor) { + public FrequencyAnalyzer(String ciphertext, String symbols, String symbol_frequences, Decrypted decryptor, IsNonsense isNonsense) { this.ciphertext = ciphertext; this.symbol_frequences = symbol_frequences; this.symbols = symbols; this.decryptor = decryptor; + this.isNonsense = isNonsense; } public String crack() { diff --git a/src/main/java/cipher_analytical_machine/analyzers/caesar/IsNonsense.java b/src/main/java/cipher_analytical_machine/analyzers/caesar/IsNonsense.java new file mode 100644 index 0000000..c956921 --- /dev/null +++ b/src/main/java/cipher_analytical_machine/analyzers/caesar/IsNonsense.java @@ -0,0 +1,6 @@ +package cipher_analytical_machine.analyzers.caesar; + +public interface IsNonsense { + boolean isNonsense(String message); +} + From 5919ba8864192e97a4141295fe1495012d4b266e Mon Sep 17 00:00:00 2001 From: KKlochko Date: Fri, 20 Oct 2023 22:01:20 +0300 Subject: [PATCH 17/24] Refactor to move actions to separated files. --- .../cli/actions/cracking.clj | 26 +++++++++++ .../cli/actions/cryptography.clj | 24 ++++++++++ src/cipher_analytical_machine/cli/cli.clj | 44 ++----------------- 3 files changed, 54 insertions(+), 40 deletions(-) create mode 100644 src/cipher_analytical_machine/cli/actions/cracking.clj create mode 100644 src/cipher_analytical_machine/cli/actions/cryptography.clj diff --git a/src/cipher_analytical_machine/cli/actions/cracking.clj b/src/cipher_analytical_machine/cli/actions/cracking.clj new file mode 100644 index 0000000..5e68aa1 --- /dev/null +++ b/src/cipher_analytical_machine/cli/actions/cracking.clj @@ -0,0 +1,26 @@ +(ns cipher-analytical-machine.cli.actions.cracking + (:require + [cipher-analytical-machine.analyzers.caesar :as caesar-analyzers] + [cipher-analytical-machine.symbols.frequencies :as symbol-frequencies]) + (:gen-class)) + +(defn cracking-caesar + [options arguments] + (let [analyzer (:analyzer options) + message (:message options) + symbols (:symbols options) + frequencies symbol-frequencies/english-letter-frequencies] + (cond + (= analyzer "Chi^2") + (caesar-analyzers/get-plaintext message symbols frequencies) + + :else + (caesar-analyzers/get-plaintext message symbols frequencies)))) + +(defn cracking-actions + [options arguments action-type] + (let [cipher (:cipher options)] + (cond + (= cipher "Caesar") + (cracking-caesar options arguments)))) + diff --git a/src/cipher_analytical_machine/cli/actions/cryptography.clj b/src/cipher_analytical_machine/cli/actions/cryptography.clj new file mode 100644 index 0000000..cdddd12 --- /dev/null +++ b/src/cipher_analytical_machine/cli/actions/cryptography.clj @@ -0,0 +1,24 @@ +(ns cipher-analytical-machine.cli.actions.cryptography + (:require + [cipher-analytical-machine.ciphers.caesar :as caesar]) + (:gen-class)) + +(defn caesar-actions + [options arguments action-type] + (let [message (:message options) + key (Integer/parseInt (:key options)) + symbols (:symbols options)] + (cond + (= action-type :encrypt) + (caesar/encrypt-message message key symbols) + + (= action-type :decrypt) + (caesar/decrypt-message message key symbols)))) + +(defn cryptography-actions + [options arguments action-type] + (let [cipher (:cipher options)] + (cond + (= cipher "Caesar") + (caesar-actions options arguments action-type)))) + diff --git a/src/cipher_analytical_machine/cli/cli.clj b/src/cipher_analytical_machine/cli/cli.clj index 7c5fa5e..c4f67bc 100644 --- a/src/cipher_analytical_machine/cli/cli.clj +++ b/src/cipher_analytical_machine/cli/cli.clj @@ -1,12 +1,11 @@ (ns cipher-analytical-machine.cli.cli (:require [cipher-analytical-machine.cli.file :as file] - [cipher-analytical-machine.ciphers.caesar :as caesar] - [cipher-analytical-machine.analyzers.caesar :as caesar-analyzers] [cipher-analytical-machine.symbols.factories :as sf] - [cipher-analytical-machine.symbols.frequencies :as symbol-frequencies] [cipher-analytical-machine.cli.options :as options] [clojure.string :as cs] + [cipher-analytical-machine.cli.actions.cryptography :as cryptography] + [cipher-analytical-machine.cli.actions.cracking :as cracking] [clojure.tools.cli :refer [parse-opts]]) (:gen-class)) @@ -148,51 +147,16 @@ (save-output output options)) (println output)) -(defn cracking-caesar - [options arguments] - (let [analyzer (:analyzer options) - message (:message options) - symbols (:symbols options) - frequencies symbol-frequencies/english-letter-frequencies] - (cond - (= analyzer "Chi^2") - (caesar-analyzers/get-plaintext message symbols frequencies) - - (= analyzer "Frequency") - (caesar-analyzers/frequency-analizer-get-plaintext message symbols - (symbol-frequencies/map-to-string frequencies) - (:language options "en"))))) - -(defn cracking-actions - [options arguments action-type] - (let [cipher (:cipher options)] - (cond - (= cipher "Caesar") - (cracking-caesar options arguments) - ))) - -(defn crypt-actions - [options arguments action-type] - (let [message (:message options) - key (Integer/parseInt (:key options)) - symbols (:symbols options)] - (cond - (= action-type :encrypt) - (caesar/encrypt-message message key symbols) - - (= action-type :decrypt) - (caesar/decrypt-message message key symbols)))) - (defn actions [options arguments action-type] (let [options (load-all-options options)] (-> (cond (contains? #{:encrypt :decrypt} action-type) - (crypt-actions options arguments action-type) + (cryptography/cryptography-actions options arguments action-type) (= action-type :cracking) - (cracking-actions options arguments action-type)) + (cracking/cracking-actions options arguments action-type)) (show-and-save-output options)))) From f465d1112ebb958a58046b707f0825289e05aea8 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Fri, 20 Oct 2023 22:03:10 +0300 Subject: [PATCH 18/24] Remove the test for FrequencyAnalyzer. --- .../analyzers/caesar_test.clj | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/cipher_analytical_machine/analyzers/caesar_test.clj b/test/cipher_analytical_machine/analyzers/caesar_test.clj index 84e1bba..2c2977d 100644 --- a/test/cipher_analytical_machine/analyzers/caesar_test.clj +++ b/test/cipher_analytical_machine/analyzers/caesar_test.clj @@ -74,13 +74,3 @@ (is (= (cs/lower-case plaintext) (get-plaintext ciphertext symbols frequencies)))))) -(deftest frequency-analizer-get-plaintext-test - (let [plaintext "abc" - ciphertext "bca" - key 1 - symbols "abc" - frequencies "etaoinsrhldcumfpgwybvkxjqz"] - (testing "The ciphertext is 'bca' and key is 1." - (is (= plaintext - (frequency-analizer-get-plaintext ciphertext symbols frequencies)))))) - From dab131a32e7ceff67213b322dfd894c5cd5b96b6 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Fri, 20 Oct 2023 22:04:05 +0300 Subject: [PATCH 19/24] Remove the option for FrequencyAnalyzer. --- src/cipher_analytical_machine/cli/options.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cipher_analytical_machine/cli/options.clj b/src/cipher_analytical_machine/cli/options.clj index 34eb18d..0c9d968 100644 --- a/src/cipher_analytical_machine/cli/options.clj +++ b/src/cipher_analytical_machine/cli/options.clj @@ -32,7 +32,7 @@ (option-values-as-row "Ciphers" cipher-options)) (def analyzers-options - {"Caesar" #{"Chi^2" "Frequency"}}) + {"Caesar" #{"Chi^2"}}) (defn get-available-analyzers-options-as-string "Return the formatted string of analyzers options." From 633cdc471f56f5eea76ef60b4fa6e9ee4df3705b Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 21 Oct 2023 16:41:15 +0300 Subject: [PATCH 20/24] Update the CHANGELOG. --- CHANGELOG.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf3b74d..658879d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.7.2] - 2023-10-21 + +### Changed +- Update the CHANGELOG. +- Update the version. +- Update the README. +- Update the CI/CD configuration to publish the artifacts to the release. + +## [0.7.1] - 2023-10-20 + +### Removed +- Remove the test for FrequencyAnalyzer. +- Remove the option for FrequencyAnalyzer. + +## [0.7.0] - 2023-10-20 + +### Changed +- Refactor to move actions to separated files. + +## [0.6.3] - 2023-10-14 + +### Added +- Add the IsNonsense interface for FrequencyAnalyzer. + +### Changed +- Update the frequency analyzer. + +## [0.6.2] - 2023-10-14 + +### Added +- Add the analyzer options and their actions. +- Add the available ciphers and analyzer for the help. +- Add validations to check if a cipher or an analyzer is available. + +### Changed +- Refactor to move options to a separated file. + +## [0.6.1] - 2023-10-13 + +### Added +- Add the function to make a frequency string from a map. + +### Fixed +- Fix the bug that the default language symbols override the symbols. + +### Changed +- Update the FrequencyAnalyzer to use the frequency string instead. + +## [0.6.0] - 2023-10-12 + +### Fixed +- Fix the typo "frequences" to frequencies. + +### Changed +- Refactor the project structure. + +## [0.5.5] - 2023-10-09 + +### Added +- Add the Gitlab CI/CD configuration. + +## [0.5.4] - 2023-10-05 + +### Added +- Add the java source path. +- Add the Caesar decrypted interface for Java. +- Add a frequency analyzer as a stub. +- Add the clojure wrapper for the frequency analizer and its test. + ## [0.5.3] - 2023-10-05 ### Added From 40725f55a1a75bc405bfa7a396b65cc6ce0337fa Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 21 Oct 2023 16:46:32 +0300 Subject: [PATCH 21/24] Update the version. --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index ab703c5..116b5f3 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject cipher-analytical-machine "0.1.0-SNAPSHOT" +(defproject cipher-analytical-machine "0.7.2" :description "A program helps to learn how ciphers works." :url "https://gitlab.com/KKlochko/cipher-analytical-machine" :license {:name "LGPL" From 7c19e48828746b00467b524a2bc46c7a5d354eca Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 21 Oct 2023 16:46:57 +0300 Subject: [PATCH 22/24] Update the README. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ce950d..3f3f08b 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,12 @@ Download from https://gitlab.com/KKlochko/cipher-analytical-machine. You need install java, before run the application. Run the application with a command: - $ java -jar cipher-analytical-machine-0.1.0-standalone.jar [args] + $ java -jar cipher-analytical-machine-VERSION-standalone.jar [args] + $ java -jar cipher-analytical-machine-0.7.2-standalone.jar [args] ## License Copyright © 2023 Kostiantyn Klochko Under the GNU Lesser General Public License v3.0 or later. + From 05009f1a9634a5b4cc6f858af97558a3f0d26660 Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 21 Oct 2023 16:47:22 +0300 Subject: [PATCH 23/24] Update the CI/CD configuration to publish the artifacts to the release. --- .drone.yaml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.drone.yaml b/.drone.yaml index 9fbba0e..7e27df2 100644 --- a/.drone.yaml +++ b/.drone.yaml @@ -5,6 +5,42 @@ name: default steps: - name: test image: clojure:temurin-11-lein-2.10.0-alpine + volumes: + - name: package_cache + path: /root/.m2/ commands: - lein test + - name: build + image: clojure:temurin-11-lein-2.10.0-alpine + volumes: + - name: package_cache + path: /root/.m2/ + commands: + - lein uberjar + when: + event: tag + + - name: gitea_release + image: plugins/gitea-release + settings: + api_key: + from_secret: API_KEY + base_url: + from_secret: BASE_URL + files: + - target/uberjar/*.jar + checksum: + - md5 + - sha1 + - sha256 + - sha512 + - adler32 + - crc32 + when: + event: tag + +volumes: + - name: package_cache + temp: {} + From 2db631d8da945c8f85b6ad52941632c51c2dad5e Mon Sep 17 00:00:00 2001 From: KKlochko Date: Sat, 21 Oct 2023 16:56:32 +0300 Subject: [PATCH 24/24] Update the diffs in the CHANGELOG. --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 658879d..246820a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update the version. - Update the README. - Update the CI/CD configuration to publish the artifacts to the release. +- Update the diffs in the CHANGELOG. ## [0.7.1] - 2023-10-20 @@ -176,7 +177,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Project initialization. -[Unreleased]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.3...main?from_project_id=50218541&straight=false +[Unreleased]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.7.2...main?from_project_id=50218541&straight=false +[0.7.2]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.7.1...0.7.2?from_project_id=50218541&straight=false +[0.7.1]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.7.0...0.7.1?from_project_id=50218541&straight=false +[0.7.0]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.6.3...0.7.0?from_project_id=50218541&straight=false +[0.6.3]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.6.2...0.6.3?from_project_id=50218541&straight=false +[0.6.2]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.6.1...0.6.2?from_project_id=50218541&straight=false +[0.6.1]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.6.0...0.6.1?from_project_id=50218541&straight=false +[0.6.0]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.5...0.6.0?from_project_id=50218541&straight=false +[0.5.5]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.4...0.5.5?from_project_id=50218541&straight=false +[0.5.4]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.3...0.5.4?from_project_id=50218541&straight=false [0.5.3]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.2...0.5.3?from_project_id=50218541&straight=false [0.5.2]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.1...0.5.2?from_project_id=50218541&straight=false [0.5.1]: https://gitlab.com/KKlochko/cipher-analytical-machine/-/compare/0.5.0...0.5.1?from_project_id=50218541&straight=false