Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
Rename business package to crypto
Browse files Browse the repository at this point in the history
  • Loading branch information
varunsingh87 committed Feb 20, 2023
1 parent bd26763 commit 91e40b6
Show file tree
Hide file tree
Showing 30 changed files with 179 additions and 70 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ node_modules
*.vsix
.DS_Store
.vscode-test
undefined
target
dist
jre
lombok
bin/
generated*
data/outputs
snippets
.settings
.idea
.classpath
.project
test/resources/projects/**/.vscode
Expand Down
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Launch DataPopulater",
"request": "launch",
"mainClass": "dataanalysis.DataPopulater",
"projectName": "com.varunsingh.frequencyanalysissimulator"
},
{
"type": "java",
"name": "Launch DataFileReader",
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Frequency Analysis Simulator
**Start Date for Part 1: Monoalphabetic Ciphers**: July 22, 2019
**Start Date for Phase I: Monoalphabetic Ciphers**: July 22, 2019

**Start Date for Part 2: Vigenere Ciphers**: September 26, 2022
**Start Date for Phase II: Vigenere Ciphers**: September 26, 2022

## Objective
The purpose of this project is to decrypt a monoalphabetic substitution cipher using frequency analysis and find the most optimal algorithm of decrypting a Vigenere cipher.
Expand All @@ -17,7 +17,7 @@ The purpose of this project is to decrypt a monoalphabetic substitution cipher u
* Layered Architecture - separated into presentation code (Java Swing framework) and business logic (pure Java)

## Project Description
Frequency Analysis Simulator uses frequency analysis to output a plain text from a ciphertext without being given the key. If the type of cipher has been identified, the process may be sped up after the user inputs the type of cipher (monoalphabetic or Vigenere) on prompt. Frequency Analysis Simulator can decipher the Caesar cipher, a cipher that does not involve the use of frequency analysis for deciphering. The application can encrypt messages, too.
Frequency Analysis Simulator uses frequency analysis to output a plain text from a ciphertext without receiving the key.

## Getting Started

Expand All @@ -32,16 +32,24 @@ or for short, use `mvn`

### Running the data analysis tool

Run the following command:
Run the following command for data collection of a single input (~480 runs/data points):

```
mvn compile exec:java -Dexec.mainClass="dataanalysis.DataAnalysis"
```

## Process
* [Blog Post for Part 1](https://dev.to/varuns924/how-i-wrote-a-background-noise-remover-from-start-to-finish-3h9m)
* [Data from 2019 Phase]()
* [Current Data (Vigenere Phase)](https://docs.google.com/spreadsheets/d/1XFQO-QX4YYL0vaCMqR6Jr5qXWtcWEMhbKEUsunjp1KY/edit#gid=0)

### Current (Phase II)

* [Current Data (Phase II)](https://docs.google.com/spreadsheets/d/e/2PACX-1vQIqW8qXtnbI1yTCQR_LcYpy6F7p6eZg5EP07no3c-lBoEkMUbpTPyxo_oa5mCCj7Gfk8LOTonOY-4a/pubhtml)
* [Presentation](https://docs.google.com/presentation/d/e/2PACX-1vR5Vu_MXCbKyHm0vHaMW5Tn4qaJWVDV34Z_WX1WpHbejcwIzODNiuNKExOOTFTRUUDs7CPsYwz8PA1T/pub?start=false&loop=false&delayms=3000)


### Phase I

* [Data from Phase I](https://docs.google.com/spreadsheets/d/130cqH1bGJPZ7mq2LrrTY6sMdm6E7qZP2Jea3s8cg3tA/edit#gid=0)
* [Presentation](https://docs.google.com/presentation/d/e/2PACX-1vT29PD0nv69KI9cNDpZdsEA1p4eDg4P8V_XLVCWtpIFXDGnp_WmLrg-xiH120KWJkqppP9DZ-DlREr_/pub?start=false&loop=false&delayms=3000)

## Built With

Expand Down
6 changes: 0 additions & 6 deletions data/fails/ciphertext1.txt

This file was deleted.

1 change: 0 additions & 1 deletion data/fails/donquixote.txt

This file was deleted.

2 changes: 2 additions & 0 deletions data/inputs/3C.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Gawayne stood confounded, the blood rushed into his face, and he shrank within himself for very shame. "Cursed," he cried, "be cowardice and covetousness both; in you are villany and vice, that virtue destroy." Then he takes off the girdle and throws it to the knight in green, cursing his cowardice and covetousness. The Green Knight, laughing, thus spoke: "Thou hast confessed so clean, and acknowledged thy faults, that I hold thee as pure as thou hadst never forfeited since thou wast first born. I give thee, sir, the gold-hemmed girdle as a token of thy adventure at the Green Chapel. Come now to my castle, and we shall enjoy together the festivities of the New Year" (ll. 2340-2406).
"Nay, forsooth," quoth the knight, "but for your kindness may God requite you. Commend me to that courteous one your comely wife, who with her crafts has beguiled me. But it is no uncommon thing for a man to come to sorrow through women's wiles; for so was Adam beguiled with one, and Solomon with many. Samson was destroyed by Delilah, and David suffered much through Bathsheba. 'It were indeed great bliss for a man to love them well and believe them not.' Since the greatest upon earth were so beguiled, methinks I should be excused. But God reward you for your girdle, which I will ever wear in remembrance of my fault, and when pride shall exalt me, a look to this love-lace shall lessen it (ll. 2407-2438). But since ye are the lord of yonder land, from whom I have received so much honour, tell me truly your right name, and I shall ask no more questions."
1 change: 0 additions & 1 deletion data/successes/ambroisethomas.txt

This file was deleted.

2 changes: 0 additions & 2 deletions data/successes/holden.txt

This file was deleted.

1 change: 0 additions & 1 deletion data/successes/lutherking.txt

This file was deleted.

2 changes: 0 additions & 2 deletions data/successes/macbeth.txt

This file was deleted.

1 change: 0 additions & 1 deletion data/successes/morality.txt

This file was deleted.

1 change: 0 additions & 1 deletion data/successes/tempest.txt

This file was deleted.

3 changes: 0 additions & 3 deletions data/successes/unitedstates.txt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import java.io.FileWriter;
import java.io.IOException;

import frequencyanalysissimulator.business.Vigenere;
import frequencyanalysissimulator.crypto.Vigenere;

public class DataAnalysis {
public class DataCollector {

/**
*
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/dataanalysis/DataFileReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
import java.nio.file.Path;

public class DataFileReader {
public static void main(String[] args) {
/**
* Reads from data/inputs/arg[0].txt
*
* @param args
* arg[0] = trial id
*/
public static void main(String... args) {
try {
String expectedText = Files.readString(Path.of(String.format("data/inputs/%s.txt", args[0])));
expectedText = expectedText.replace(System.getProperty("line.separator"), " ");
System.out.println(expectedText);
DataAnalysis.main(new String[] { expectedText, args[0] });
DataCollector.main(new String[] { expectedText, args[0] });
} catch (IOException e) {
e.printStackTrace();
}
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/dataanalysis/DataPopulater.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dataanalysis;

import java.io.File;

/**
* Runs DataAnalysis without arguments, taking contents of every input file and feeding this to
* DataFileWriter, which in return feeds the content to DataAnalysis
* Used for populating all data, takes ~20 seconds to run and collects 5000 data points
*/
public class DataPopulater {
public static void main(String[] args) throws InterruptedException {
File inputFolder = new File("data/inputs");
File[] allInputs = inputFolder.listFiles();

for (int i = 0; i < allInputs.length; i++) {
System.out.printf("Collecting data on %s...%-20s", allInputs[i].getName(), ' ');

String fileNameWithoutExtension = allInputs[i].getName().substring(0,
allInputs[i].getName().lastIndexOf("."));
DataFileReader.main(fileNameWithoutExtension);

System.out.print("\rData collection complete. Moving to next file...\n");
}
System.out.print("\rData population complete");
}
}
11 changes: 11 additions & 0 deletions src/main/java/dataanalysis/DataVisualizer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dataanalysis;

public class DataVisualizer {
public DataVisualizer() {

}

public static void main(String[] args) {
new DataVisualizer();
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package frequencyanalysissimulator.business;
package frequencyanalysissimulator.crypto;

public class Caesar implements Cipher {
private String ciphertext;
Expand All @@ -16,7 +16,8 @@ public Caesar(String t) {
*
* @time O(n) - Increases linearly with the length of the ciphertext
*
* @param ciphertext The Caesar cipher text to get the letter rotation of
* @param ciphertext
* The Caesar cipher text to get the letter rotation of
* @return The letter that represents the number of rotations for the Caesar
* cipher and part of the key for the Vigenere cipher
*/
Expand Down Expand Up @@ -72,9 +73,10 @@ public String decrypt() {
*
* @apiNote A = 0, so encrypt('A') = encrypt(1 - 1) = encrypt(0)
*
* @param key Precondition: A-Z, one letter long
* @param key
* Precondition: A-Z, one letter long
* Postcondition: Encrypted Caesar ciphertext
* @see frequencyanalysissimulator.business.Cipher#encrypt(java.lang.String)
* @see frequencyanalysissimulator.crypto.Cipher#encrypt(java.lang.String)
*/
public static String encrypt(String plaintext, String key) {
return encrypt(plaintext, (int) (key.charAt(0) - 64 - 1));
Expand All @@ -84,7 +86,8 @@ public static String encrypt(String plaintext, String key) {
* Precondition: 0 <= key <= 26
*
* @apiNote Equals this.inputText when key is 0 or 26
* @param key The shift
* @param key
* The shift
* @return The encrypted ciphertext
*/
public static String encrypt(String plaintext, int key) {
Expand All @@ -105,4 +108,19 @@ public static String encrypt(String plaintext, int key) {

return ciphertext;
}

public float calculateIndexOfCoincidence() {
float indexOfCoincidence = 0;

int[] ciphertextLetterCounts = FrequencyAnalysis.calculateAbsoluteLetterFrequencies(ciphertext);

for (int i = 0; i < 26; i++) {
double countTimesCountMinusOne = ciphertextLetterCounts[i] * (ciphertextLetterCounts[i] - 1);
indexOfCoincidence += countTimesCountMinusOne;
}

indexOfCoincidence /= ciphertext.length() * (ciphertext.length() - 1);

return indexOfCoincidence;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package frequencyanalysissimulator.business;
package frequencyanalysissimulator.crypto;

public interface Cipher {
String decrypt();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package frequencyanalysissimulator.crypto;

public class CosetManager {

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package frequencyanalysissimulator.business;
package frequencyanalysissimulator.crypto;

public final class FrequencyAnalysis {
static double[] standardEnglishFrequencies = new double[] {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package frequencyanalysissimulator.crypto;

public enum KeyLengthMethod {
KASISKI, KERCKHOFF, FRIEDMAN
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package frequencyanalysissimulator.crypto;

/**
* Monoalphabetic substitution cipher
*
* @author Varun Singh on 2/20/2023
*/
public class SimpleSubstitutionCipher implements Cipher {
private String ciphertext;
private double[] frequencies;

@Override
public String decrypt() {
return null;
}

/**
* Decrypts an individual Caesar cipher using Chi Square analysis
* to find which number of shifts matches the standard English frequency
* distribution the most
*
* @time O(n) - Increases linearly with the length of the ciphertext
*
* @param ciphertext
* The cipher text to get the letter rotation of
* @return The letter that represents the number of rotations for the Caesar
* cipher and part of the key for the Vigenere cipher
*/
private double calculateChiSquare() {
// Populate ciphertext letter frequencies by adding one for every occurrence of
// letter O(n)
for (int i = 0; i < ciphertext.length(); i++) {
char letter = ciphertext.charAt(i);
int asNum = letter - 65;
// Ignore anything other than letters (such as spaces)
if (Character.isAlphabetic((int) letter)) {
frequencies[asNum] += 1.0 / ciphertext.length();
}
}

double chiSquareValue = 0;
for (int i = 0; i < 26; i++) {
double standardFrequency = FrequencyAnalysis.standardEnglishFrequencies[i];
double shiftedCiphertextFrequency = frequencies[i % 26];
chiSquareValue += Math.pow(shiftedCiphertextFrequency - standardFrequency, 2) / standardFrequency;
}

return chiSquareValue;
}

}
Loading

0 comments on commit 91e40b6

Please sign in to comment.