From 3dfbfab13e13fe62c20f9974feed077d3b9b2ad1 Mon Sep 17 00:00:00 2001 From: ngli Date: Sat, 21 Mar 2026 21:07:55 +0530 Subject: [PATCH 1/3] sonar info addedd --- .github/sonar.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/sonar.yml diff --git a/.github/sonar.yml b/.github/sonar.yml new file mode 100644 index 000000000000..30e21e67ba7b --- /dev/null +++ b/.github/sonar.yml @@ -0,0 +1,37 @@ +name: SonarQube Scan + +on: + push: + branches: + - main + pull_request: + +jobs: + sonar: + name: Build and Analyze + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build and SonarQube Scan + run: | + mvn clean verify sonar:sonar \ + -Dsonar.projectKey=Nglicloud_Java \ + -Dsonar.host.url= https://sonarcloud.io/projects \ + -Dsonar.login=75f5d23fd39669ae77ea05ba90a303606672ef5a \ + -Dsonar.organization=nglicloud \ No newline at end of file From 12ff2ef982d8f1fcdc22735c4b0082648fd1e4ee Mon Sep 17 00:00:00 2001 From: ngli Date: Sat, 21 Mar 2026 21:28:01 +0530 Subject: [PATCH 2/3] added duplicate code --- .../java/com/thealgorithms/ciphers/AES.java | 5562 +++++++++++++++++ 1 file changed, 5562 insertions(+) diff --git a/src/main/java/com/thealgorithms/ciphers/AES.java b/src/main/java/com/thealgorithms/ciphers/AES.java index df51eba55310..f8cad0b16070 100644 --- a/src/main/java/com/thealgorithms/ciphers/AES.java +++ b/src/main/java/com/thealgorithms/ciphers/AES.java @@ -2779,3 +2779,5565 @@ public static void main(String[] args) { } } } +package com.thealgorithms.ciphers; + +import java.math.BigInteger; +import java.util.Scanner; + +/** + * This class is build to demonstrate the application of the AES-algorithm on a + * single 128-Bit block of data. + */ +public final class AES { + private AES() { + } + + /** + * Precalculated values for x to the power of 2 in Rijndaels galois field. + * Used as 'RCON' during the key expansion. + */ + private static final int[] RCON = { + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + }; + + /** + * Rijndael S-box Substitution table used for encryption in the subBytes + * step, as well as the key expansion. + */ + private static final int[] SBOX = { + 0x63, + 0x7C, + 0x77, + 0x7B, + 0xF2, + 0x6B, + 0x6F, + 0xC5, + 0x30, + 0x01, + 0x67, + 0x2B, + 0xFE, + 0xD7, + 0xAB, + 0x76, + 0xCA, + 0x82, + 0xC9, + 0x7D, + 0xFA, + 0x59, + 0x47, + 0xF0, + 0xAD, + 0xD4, + 0xA2, + 0xAF, + 0x9C, + 0xA4, + 0x72, + 0xC0, + 0xB7, + 0xFD, + 0x93, + 0x26, + 0x36, + 0x3F, + 0xF7, + 0xCC, + 0x34, + 0xA5, + 0xE5, + 0xF1, + 0x71, + 0xD8, + 0x31, + 0x15, + 0x04, + 0xC7, + 0x23, + 0xC3, + 0x18, + 0x96, + 0x05, + 0x9A, + 0x07, + 0x12, + 0x80, + 0xE2, + 0xEB, + 0x27, + 0xB2, + 0x75, + 0x09, + 0x83, + 0x2C, + 0x1A, + 0x1B, + 0x6E, + 0x5A, + 0xA0, + 0x52, + 0x3B, + 0xD6, + 0xB3, + 0x29, + 0xE3, + 0x2F, + 0x84, + 0x53, + 0xD1, + 0x00, + 0xED, + 0x20, + 0xFC, + 0xB1, + 0x5B, + 0x6A, + 0xCB, + 0xBE, + 0x39, + 0x4A, + 0x4C, + 0x58, + 0xCF, + 0xD0, + 0xEF, + 0xAA, + 0xFB, + 0x43, + 0x4D, + 0x33, + 0x85, + 0x45, + 0xF9, + 0x02, + 0x7F, + 0x50, + 0x3C, + 0x9F, + 0xA8, + 0x51, + 0xA3, + 0x40, + 0x8F, + 0x92, + 0x9D, + 0x38, + 0xF5, + 0xBC, + 0xB6, + 0xDA, + 0x21, + 0x10, + 0xFF, + 0xF3, + 0xD2, + 0xCD, + 0x0C, + 0x13, + 0xEC, + 0x5F, + 0x97, + 0x44, + 0x17, + 0xC4, + 0xA7, + 0x7E, + 0x3D, + 0x64, + 0x5D, + 0x19, + 0x73, + 0x60, + 0x81, + 0x4F, + 0xDC, + 0x22, + 0x2A, + 0x90, + 0x88, + 0x46, + 0xEE, + 0xB8, + 0x14, + 0xDE, + 0x5E, + 0x0B, + 0xDB, + 0xE0, + 0x32, + 0x3A, + 0x0A, + 0x49, + 0x06, + 0x24, + 0x5C, + 0xC2, + 0xD3, + 0xAC, + 0x62, + 0x91, + 0x95, + 0xE4, + 0x79, + 0xE7, + 0xC8, + 0x37, + 0x6D, + 0x8D, + 0xD5, + 0x4E, + 0xA9, + 0x6C, + 0x56, + 0xF4, + 0xEA, + 0x65, + 0x7A, + 0xAE, + 0x08, + 0xBA, + 0x78, + 0x25, + 0x2E, + 0x1C, + 0xA6, + 0xB4, + 0xC6, + 0xE8, + 0xDD, + 0x74, + 0x1F, + 0x4B, + 0xBD, + 0x8B, + 0x8A, + 0x70, + 0x3E, + 0xB5, + 0x66, + 0x48, + 0x03, + 0xF6, + 0x0E, + 0x61, + 0x35, + 0x57, + 0xB9, + 0x86, + 0xC1, + 0x1D, + 0x9E, + 0xE1, + 0xF8, + 0x98, + 0x11, + 0x69, + 0xD9, + 0x8E, + 0x94, + 0x9B, + 0x1E, + 0x87, + 0xE9, + 0xCE, + 0x55, + 0x28, + 0xDF, + 0x8C, + 0xA1, + 0x89, + 0x0D, + 0xBF, + 0xE6, + 0x42, + 0x68, + 0x41, + 0x99, + 0x2D, + 0x0F, + 0xB0, + 0x54, + 0xBB, + 0x16, + }; + + /** + * Inverse Rijndael S-box Substitution table used for decryption in the + * subBytesDec step. + */ + private static final int[] INVERSE_SBOX = { + 0x52, + 0x09, + 0x6A, + 0xD5, + 0x30, + 0x36, + 0xA5, + 0x38, + 0xBF, + 0x40, + 0xA3, + 0x9E, + 0x81, + 0xF3, + 0xD7, + 0xFB, + 0x7C, + 0xE3, + 0x39, + 0x82, + 0x9B, + 0x2F, + 0xFF, + 0x87, + 0x34, + 0x8E, + 0x43, + 0x44, + 0xC4, + 0xDE, + 0xE9, + 0xCB, + 0x54, + 0x7B, + 0x94, + 0x32, + 0xA6, + 0xC2, + 0x23, + 0x3D, + 0xEE, + 0x4C, + 0x95, + 0x0B, + 0x42, + 0xFA, + 0xC3, + 0x4E, + 0x08, + 0x2E, + 0xA1, + 0x66, + 0x28, + 0xD9, + 0x24, + 0xB2, + 0x76, + 0x5B, + 0xA2, + 0x49, + 0x6D, + 0x8B, + 0xD1, + 0x25, + 0x72, + 0xF8, + 0xF6, + 0x64, + 0x86, + 0x68, + 0x98, + 0x16, + 0xD4, + 0xA4, + 0x5C, + 0xCC, + 0x5D, + 0x65, + 0xB6, + 0x92, + 0x6C, + 0x70, + 0x48, + 0x50, + 0xFD, + 0xED, + 0xB9, + 0xDA, + 0x5E, + 0x15, + 0x46, + 0x57, + 0xA7, + 0x8D, + 0x9D, + 0x84, + 0x90, + 0xD8, + 0xAB, + 0x00, + 0x8C, + 0xBC, + 0xD3, + 0x0A, + 0xF7, + 0xE4, + 0x58, + 0x05, + 0xB8, + 0xB3, + 0x45, + 0x06, + 0xD0, + 0x2C, + 0x1E, + 0x8F, + 0xCA, + 0x3F, + 0x0F, + 0x02, + 0xC1, + 0xAF, + 0xBD, + 0x03, + 0x01, + 0x13, + 0x8A, + 0x6B, + 0x3A, + 0x91, + 0x11, + 0x41, + 0x4F, + 0x67, + 0xDC, + 0xEA, + 0x97, + 0xF2, + 0xCF, + 0xCE, + 0xF0, + 0xB4, + 0xE6, + 0x73, + 0x96, + 0xAC, + 0x74, + 0x22, + 0xE7, + 0xAD, + 0x35, + 0x85, + 0xE2, + 0xF9, + 0x37, + 0xE8, + 0x1C, + 0x75, + 0xDF, + 0x6E, + 0x47, + 0xF1, + 0x1A, + 0x71, + 0x1D, + 0x29, + 0xC5, + 0x89, + 0x6F, + 0xB7, + 0x62, + 0x0E, + 0xAA, + 0x18, + 0xBE, + 0x1B, + 0xFC, + 0x56, + 0x3E, + 0x4B, + 0xC6, + 0xD2, + 0x79, + 0x20, + 0x9A, + 0xDB, + 0xC0, + 0xFE, + 0x78, + 0xCD, + 0x5A, + 0xF4, + 0x1F, + 0xDD, + 0xA8, + 0x33, + 0x88, + 0x07, + 0xC7, + 0x31, + 0xB1, + 0x12, + 0x10, + 0x59, + 0x27, + 0x80, + 0xEC, + 0x5F, + 0x60, + 0x51, + 0x7F, + 0xA9, + 0x19, + 0xB5, + 0x4A, + 0x0D, + 0x2D, + 0xE5, + 0x7A, + 0x9F, + 0x93, + 0xC9, + 0x9C, + 0xEF, + 0xA0, + 0xE0, + 0x3B, + 0x4D, + 0xAE, + 0x2A, + 0xF5, + 0xB0, + 0xC8, + 0xEB, + 0xBB, + 0x3C, + 0x83, + 0x53, + 0x99, + 0x61, + 0x17, + 0x2B, + 0x04, + 0x7E, + 0xBA, + 0x77, + 0xD6, + 0x26, + 0xE1, + 0x69, + 0x14, + 0x63, + 0x55, + 0x21, + 0x0C, + 0x7D, + }; + + /** + * Precalculated lookup table for galois field multiplication by 2 used in + * the MixColums step during encryption. + */ + private static final int[] MULT2 = { + 0x00, + 0x02, + 0x04, + 0x06, + 0x08, + 0x0a, + 0x0c, + 0x0e, + 0x10, + 0x12, + 0x14, + 0x16, + 0x18, + 0x1a, + 0x1c, + 0x1e, + 0x20, + 0x22, + 0x24, + 0x26, + 0x28, + 0x2a, + 0x2c, + 0x2e, + 0x30, + 0x32, + 0x34, + 0x36, + 0x38, + 0x3a, + 0x3c, + 0x3e, + 0x40, + 0x42, + 0x44, + 0x46, + 0x48, + 0x4a, + 0x4c, + 0x4e, + 0x50, + 0x52, + 0x54, + 0x56, + 0x58, + 0x5a, + 0x5c, + 0x5e, + 0x60, + 0x62, + 0x64, + 0x66, + 0x68, + 0x6a, + 0x6c, + 0x6e, + 0x70, + 0x72, + 0x74, + 0x76, + 0x78, + 0x7a, + 0x7c, + 0x7e, + 0x80, + 0x82, + 0x84, + 0x86, + 0x88, + 0x8a, + 0x8c, + 0x8e, + 0x90, + 0x92, + 0x94, + 0x96, + 0x98, + 0x9a, + 0x9c, + 0x9e, + 0xa0, + 0xa2, + 0xa4, + 0xa6, + 0xa8, + 0xaa, + 0xac, + 0xae, + 0xb0, + 0xb2, + 0xb4, + 0xb6, + 0xb8, + 0xba, + 0xbc, + 0xbe, + 0xc0, + 0xc2, + 0xc4, + 0xc6, + 0xc8, + 0xca, + 0xcc, + 0xce, + 0xd0, + 0xd2, + 0xd4, + 0xd6, + 0xd8, + 0xda, + 0xdc, + 0xde, + 0xe0, + 0xe2, + 0xe4, + 0xe6, + 0xe8, + 0xea, + 0xec, + 0xee, + 0xf0, + 0xf2, + 0xf4, + 0xf6, + 0xf8, + 0xfa, + 0xfc, + 0xfe, + 0x1b, + 0x19, + 0x1f, + 0x1d, + 0x13, + 0x11, + 0x17, + 0x15, + 0x0b, + 0x09, + 0x0f, + 0x0d, + 0x03, + 0x01, + 0x07, + 0x05, + 0x3b, + 0x39, + 0x3f, + 0x3d, + 0x33, + 0x31, + 0x37, + 0x35, + 0x2b, + 0x29, + 0x2f, + 0x2d, + 0x23, + 0x21, + 0x27, + 0x25, + 0x5b, + 0x59, + 0x5f, + 0x5d, + 0x53, + 0x51, + 0x57, + 0x55, + 0x4b, + 0x49, + 0x4f, + 0x4d, + 0x43, + 0x41, + 0x47, + 0x45, + 0x7b, + 0x79, + 0x7f, + 0x7d, + 0x73, + 0x71, + 0x77, + 0x75, + 0x6b, + 0x69, + 0x6f, + 0x6d, + 0x63, + 0x61, + 0x67, + 0x65, + 0x9b, + 0x99, + 0x9f, + 0x9d, + 0x93, + 0x91, + 0x97, + 0x95, + 0x8b, + 0x89, + 0x8f, + 0x8d, + 0x83, + 0x81, + 0x87, + 0x85, + 0xbb, + 0xb9, + 0xbf, + 0xbd, + 0xb3, + 0xb1, + 0xb7, + 0xb5, + 0xab, + 0xa9, + 0xaf, + 0xad, + 0xa3, + 0xa1, + 0xa7, + 0xa5, + 0xdb, + 0xd9, + 0xdf, + 0xdd, + 0xd3, + 0xd1, + 0xd7, + 0xd5, + 0xcb, + 0xc9, + 0xcf, + 0xcd, + 0xc3, + 0xc1, + 0xc7, + 0xc5, + 0xfb, + 0xf9, + 0xff, + 0xfd, + 0xf3, + 0xf1, + 0xf7, + 0xf5, + 0xeb, + 0xe9, + 0xef, + 0xed, + 0xe3, + 0xe1, + 0xe7, + 0xe5, + }; + + /** + * Precalculated lookup table for galois field multiplication by 3 used in + * the MixColums step during encryption. + */ + private static final int[] MULT3 = { + 0x00, + 0x03, + 0x06, + 0x05, + 0x0c, + 0x0f, + 0x0a, + 0x09, + 0x18, + 0x1b, + 0x1e, + 0x1d, + 0x14, + 0x17, + 0x12, + 0x11, + 0x30, + 0x33, + 0x36, + 0x35, + 0x3c, + 0x3f, + 0x3a, + 0x39, + 0x28, + 0x2b, + 0x2e, + 0x2d, + 0x24, + 0x27, + 0x22, + 0x21, + 0x60, + 0x63, + 0x66, + 0x65, + 0x6c, + 0x6f, + 0x6a, + 0x69, + 0x78, + 0x7b, + 0x7e, + 0x7d, + 0x74, + 0x77, + 0x72, + 0x71, + 0x50, + 0x53, + 0x56, + 0x55, + 0x5c, + 0x5f, + 0x5a, + 0x59, + 0x48, + 0x4b, + 0x4e, + 0x4d, + 0x44, + 0x47, + 0x42, + 0x41, + 0xc0, + 0xc3, + 0xc6, + 0xc5, + 0xcc, + 0xcf, + 0xca, + 0xc9, + 0xd8, + 0xdb, + 0xde, + 0xdd, + 0xd4, + 0xd7, + 0xd2, + 0xd1, + 0xf0, + 0xf3, + 0xf6, + 0xf5, + 0xfc, + 0xff, + 0xfa, + 0xf9, + 0xe8, + 0xeb, + 0xee, + 0xed, + 0xe4, + 0xe7, + 0xe2, + 0xe1, + 0xa0, + 0xa3, + 0xa6, + 0xa5, + 0xac, + 0xaf, + 0xaa, + 0xa9, + 0xb8, + 0xbb, + 0xbe, + 0xbd, + 0xb4, + 0xb7, + 0xb2, + 0xb1, + 0x90, + 0x93, + 0x96, + 0x95, + 0x9c, + 0x9f, + 0x9a, + 0x99, + 0x88, + 0x8b, + 0x8e, + 0x8d, + 0x84, + 0x87, + 0x82, + 0x81, + 0x9b, + 0x98, + 0x9d, + 0x9e, + 0x97, + 0x94, + 0x91, + 0x92, + 0x83, + 0x80, + 0x85, + 0x86, + 0x8f, + 0x8c, + 0x89, + 0x8a, + 0xab, + 0xa8, + 0xad, + 0xae, + 0xa7, + 0xa4, + 0xa1, + 0xa2, + 0xb3, + 0xb0, + 0xb5, + 0xb6, + 0xbf, + 0xbc, + 0xb9, + 0xba, + 0xfb, + 0xf8, + 0xfd, + 0xfe, + 0xf7, + 0xf4, + 0xf1, + 0xf2, + 0xe3, + 0xe0, + 0xe5, + 0xe6, + 0xef, + 0xec, + 0xe9, + 0xea, + 0xcb, + 0xc8, + 0xcd, + 0xce, + 0xc7, + 0xc4, + 0xc1, + 0xc2, + 0xd3, + 0xd0, + 0xd5, + 0xd6, + 0xdf, + 0xdc, + 0xd9, + 0xda, + 0x5b, + 0x58, + 0x5d, + 0x5e, + 0x57, + 0x54, + 0x51, + 0x52, + 0x43, + 0x40, + 0x45, + 0x46, + 0x4f, + 0x4c, + 0x49, + 0x4a, + 0x6b, + 0x68, + 0x6d, + 0x6e, + 0x67, + 0x64, + 0x61, + 0x62, + 0x73, + 0x70, + 0x75, + 0x76, + 0x7f, + 0x7c, + 0x79, + 0x7a, + 0x3b, + 0x38, + 0x3d, + 0x3e, + 0x37, + 0x34, + 0x31, + 0x32, + 0x23, + 0x20, + 0x25, + 0x26, + 0x2f, + 0x2c, + 0x29, + 0x2a, + 0x0b, + 0x08, + 0x0d, + 0x0e, + 0x07, + 0x04, + 0x01, + 0x02, + 0x13, + 0x10, + 0x15, + 0x16, + 0x1f, + 0x1c, + 0x19, + 0x1a, + }; + + /** + * Precalculated lookup table for galois field multiplication by 9 used in + * the MixColums step during decryption. + */ + private static final int[] MULT9 = { + 0x00, + 0x09, + 0x12, + 0x1b, + 0x24, + 0x2d, + 0x36, + 0x3f, + 0x48, + 0x41, + 0x5a, + 0x53, + 0x6c, + 0x65, + 0x7e, + 0x77, + 0x90, + 0x99, + 0x82, + 0x8b, + 0xb4, + 0xbd, + 0xa6, + 0xaf, + 0xd8, + 0xd1, + 0xca, + 0xc3, + 0xfc, + 0xf5, + 0xee, + 0xe7, + 0x3b, + 0x32, + 0x29, + 0x20, + 0x1f, + 0x16, + 0x0d, + 0x04, + 0x73, + 0x7a, + 0x61, + 0x68, + 0x57, + 0x5e, + 0x45, + 0x4c, + 0xab, + 0xa2, + 0xb9, + 0xb0, + 0x8f, + 0x86, + 0x9d, + 0x94, + 0xe3, + 0xea, + 0xf1, + 0xf8, + 0xc7, + 0xce, + 0xd5, + 0xdc, + 0x76, + 0x7f, + 0x64, + 0x6d, + 0x52, + 0x5b, + 0x40, + 0x49, + 0x3e, + 0x37, + 0x2c, + 0x25, + 0x1a, + 0x13, + 0x08, + 0x01, + 0xe6, + 0xef, + 0xf4, + 0xfd, + 0xc2, + 0xcb, + 0xd0, + 0xd9, + 0xae, + 0xa7, + 0xbc, + 0xb5, + 0x8a, + 0x83, + 0x98, + 0x91, + 0x4d, + 0x44, + 0x5f, + 0x56, + 0x69, + 0x60, + 0x7b, + 0x72, + 0x05, + 0x0c, + 0x17, + 0x1e, + 0x21, + 0x28, + 0x33, + 0x3a, + 0xdd, + 0xd4, + 0xcf, + 0xc6, + 0xf9, + 0xf0, + 0xeb, + 0xe2, + 0x95, + 0x9c, + 0x87, + 0x8e, + 0xb1, + 0xb8, + 0xa3, + 0xaa, + 0xec, + 0xe5, + 0xfe, + 0xf7, + 0xc8, + 0xc1, + 0xda, + 0xd3, + 0xa4, + 0xad, + 0xb6, + 0xbf, + 0x80, + 0x89, + 0x92, + 0x9b, + 0x7c, + 0x75, + 0x6e, + 0x67, + 0x58, + 0x51, + 0x4a, + 0x43, + 0x34, + 0x3d, + 0x26, + 0x2f, + 0x10, + 0x19, + 0x02, + 0x0b, + 0xd7, + 0xde, + 0xc5, + 0xcc, + 0xf3, + 0xfa, + 0xe1, + 0xe8, + 0x9f, + 0x96, + 0x8d, + 0x84, + 0xbb, + 0xb2, + 0xa9, + 0xa0, + 0x47, + 0x4e, + 0x55, + 0x5c, + 0x63, + 0x6a, + 0x71, + 0x78, + 0x0f, + 0x06, + 0x1d, + 0x14, + 0x2b, + 0x22, + 0x39, + 0x30, + 0x9a, + 0x93, + 0x88, + 0x81, + 0xbe, + 0xb7, + 0xac, + 0xa5, + 0xd2, + 0xdb, + 0xc0, + 0xc9, + 0xf6, + 0xff, + 0xe4, + 0xed, + 0x0a, + 0x03, + 0x18, + 0x11, + 0x2e, + 0x27, + 0x3c, + 0x35, + 0x42, + 0x4b, + 0x50, + 0x59, + 0x66, + 0x6f, + 0x74, + 0x7d, + 0xa1, + 0xa8, + 0xb3, + 0xba, + 0x85, + 0x8c, + 0x97, + 0x9e, + 0xe9, + 0xe0, + 0xfb, + 0xf2, + 0xcd, + 0xc4, + 0xdf, + 0xd6, + 0x31, + 0x38, + 0x23, + 0x2a, + 0x15, + 0x1c, + 0x07, + 0x0e, + 0x79, + 0x70, + 0x6b, + 0x62, + 0x5d, + 0x54, + 0x4f, + 0x46, + }; + + /** + * Precalculated lookup table for galois field multiplication by 11 used in + * the MixColums step during decryption. + */ + private static final int[] MULT11 = { + 0x00, + 0x0b, + 0x16, + 0x1d, + 0x2c, + 0x27, + 0x3a, + 0x31, + 0x58, + 0x53, + 0x4e, + 0x45, + 0x74, + 0x7f, + 0x62, + 0x69, + 0xb0, + 0xbb, + 0xa6, + 0xad, + 0x9c, + 0x97, + 0x8a, + 0x81, + 0xe8, + 0xe3, + 0xfe, + 0xf5, + 0xc4, + 0xcf, + 0xd2, + 0xd9, + 0x7b, + 0x70, + 0x6d, + 0x66, + 0x57, + 0x5c, + 0x41, + 0x4a, + 0x23, + 0x28, + 0x35, + 0x3e, + 0x0f, + 0x04, + 0x19, + 0x12, + 0xcb, + 0xc0, + 0xdd, + 0xd6, + 0xe7, + 0xec, + 0xf1, + 0xfa, + 0x93, + 0x98, + 0x85, + 0x8e, + 0xbf, + 0xb4, + 0xa9, + 0xa2, + 0xf6, + 0xfd, + 0xe0, + 0xeb, + 0xda, + 0xd1, + 0xcc, + 0xc7, + 0xae, + 0xa5, + 0xb8, + 0xb3, + 0x82, + 0x89, + 0x94, + 0x9f, + 0x46, + 0x4d, + 0x50, + 0x5b, + 0x6a, + 0x61, + 0x7c, + 0x77, + 0x1e, + 0x15, + 0x08, + 0x03, + 0x32, + 0x39, + 0x24, + 0x2f, + 0x8d, + 0x86, + 0x9b, + 0x90, + 0xa1, + 0xaa, + 0xb7, + 0xbc, + 0xd5, + 0xde, + 0xc3, + 0xc8, + 0xf9, + 0xf2, + 0xef, + 0xe4, + 0x3d, + 0x36, + 0x2b, + 0x20, + 0x11, + 0x1a, + 0x07, + 0x0c, + 0x65, + 0x6e, + 0x73, + 0x78, + 0x49, + 0x42, + 0x5f, + 0x54, + 0xf7, + 0xfc, + 0xe1, + 0xea, + 0xdb, + 0xd0, + 0xcd, + 0xc6, + 0xaf, + 0xa4, + 0xb9, + 0xb2, + 0x83, + 0x88, + 0x95, + 0x9e, + 0x47, + 0x4c, + 0x51, + 0x5a, + 0x6b, + 0x60, + 0x7d, + 0x76, + 0x1f, + 0x14, + 0x09, + 0x02, + 0x33, + 0x38, + 0x25, + 0x2e, + 0x8c, + 0x87, + 0x9a, + 0x91, + 0xa0, + 0xab, + 0xb6, + 0xbd, + 0xd4, + 0xdf, + 0xc2, + 0xc9, + 0xf8, + 0xf3, + 0xee, + 0xe5, + 0x3c, + 0x37, + 0x2a, + 0x21, + 0x10, + 0x1b, + 0x06, + 0x0d, + 0x64, + 0x6f, + 0x72, + 0x79, + 0x48, + 0x43, + 0x5e, + 0x55, + 0x01, + 0x0a, + 0x17, + 0x1c, + 0x2d, + 0x26, + 0x3b, + 0x30, + 0x59, + 0x52, + 0x4f, + 0x44, + 0x75, + 0x7e, + 0x63, + 0x68, + 0xb1, + 0xba, + 0xa7, + 0xac, + 0x9d, + 0x96, + 0x8b, + 0x80, + 0xe9, + 0xe2, + 0xff, + 0xf4, + 0xc5, + 0xce, + 0xd3, + 0xd8, + 0x7a, + 0x71, + 0x6c, + 0x67, + 0x56, + 0x5d, + 0x40, + 0x4b, + 0x22, + 0x29, + 0x34, + 0x3f, + 0x0e, + 0x05, + 0x18, + 0x13, + 0xca, + 0xc1, + 0xdc, + 0xd7, + 0xe6, + 0xed, + 0xf0, + 0xfb, + 0x92, + 0x99, + 0x84, + 0x8f, + 0xbe, + 0xb5, + 0xa8, + 0xa3, + }; + + /** + * Precalculated lookup table for galois field multiplication by 13 used in + * the MixColums step during decryption. + */ + private static final int[] MULT13 = { + 0x00, + 0x0d, + 0x1a, + 0x17, + 0x34, + 0x39, + 0x2e, + 0x23, + 0x68, + 0x65, + 0x72, + 0x7f, + 0x5c, + 0x51, + 0x46, + 0x4b, + 0xd0, + 0xdd, + 0xca, + 0xc7, + 0xe4, + 0xe9, + 0xfe, + 0xf3, + 0xb8, + 0xb5, + 0xa2, + 0xaf, + 0x8c, + 0x81, + 0x96, + 0x9b, + 0xbb, + 0xb6, + 0xa1, + 0xac, + 0x8f, + 0x82, + 0x95, + 0x98, + 0xd3, + 0xde, + 0xc9, + 0xc4, + 0xe7, + 0xea, + 0xfd, + 0xf0, + 0x6b, + 0x66, + 0x71, + 0x7c, + 0x5f, + 0x52, + 0x45, + 0x48, + 0x03, + 0x0e, + 0x19, + 0x14, + 0x37, + 0x3a, + 0x2d, + 0x20, + 0x6d, + 0x60, + 0x77, + 0x7a, + 0x59, + 0x54, + 0x43, + 0x4e, + 0x05, + 0x08, + 0x1f, + 0x12, + 0x31, + 0x3c, + 0x2b, + 0x26, + 0xbd, + 0xb0, + 0xa7, + 0xaa, + 0x89, + 0x84, + 0x93, + 0x9e, + 0xd5, + 0xd8, + 0xcf, + 0xc2, + 0xe1, + 0xec, + 0xfb, + 0xf6, + 0xd6, + 0xdb, + 0xcc, + 0xc1, + 0xe2, + 0xef, + 0xf8, + 0xf5, + 0xbe, + 0xb3, + 0xa4, + 0xa9, + 0x8a, + 0x87, + 0x90, + 0x9d, + 0x06, + 0x0b, + 0x1c, + 0x11, + 0x32, + 0x3f, + 0x28, + 0x25, + 0x6e, + 0x63, + 0x74, + 0x79, + 0x5a, + 0x57, + 0x40, + 0x4d, + 0xda, + 0xd7, + 0xc0, + 0xcd, + 0xee, + 0xe3, + 0xf4, + 0xf9, + 0xb2, + 0xbf, + 0xa8, + 0xa5, + 0x86, + 0x8b, + 0x9c, + 0x91, + 0x0a, + 0x07, + 0x10, + 0x1d, + 0x3e, + 0x33, + 0x24, + 0x29, + 0x62, + 0x6f, + 0x78, + 0x75, + 0x56, + 0x5b, + 0x4c, + 0x41, + 0x61, + 0x6c, + 0x7b, + 0x76, + 0x55, + 0x58, + 0x4f, + 0x42, + 0x09, + 0x04, + 0x13, + 0x1e, + 0x3d, + 0x30, + 0x27, + 0x2a, + 0xb1, + 0xbc, + 0xab, + 0xa6, + 0x85, + 0x88, + 0x9f, + 0x92, + 0xd9, + 0xd4, + 0xc3, + 0xce, + 0xed, + 0xe0, + 0xf7, + 0xfa, + 0xb7, + 0xba, + 0xad, + 0xa0, + 0x83, + 0x8e, + 0x99, + 0x94, + 0xdf, + 0xd2, + 0xc5, + 0xc8, + 0xeb, + 0xe6, + 0xf1, + 0xfc, + 0x67, + 0x6a, + 0x7d, + 0x70, + 0x53, + 0x5e, + 0x49, + 0x44, + 0x0f, + 0x02, + 0x15, + 0x18, + 0x3b, + 0x36, + 0x21, + 0x2c, + 0x0c, + 0x01, + 0x16, + 0x1b, + 0x38, + 0x35, + 0x22, + 0x2f, + 0x64, + 0x69, + 0x7e, + 0x73, + 0x50, + 0x5d, + 0x4a, + 0x47, + 0xdc, + 0xd1, + 0xc6, + 0xcb, + 0xe8, + 0xe5, + 0xf2, + 0xff, + 0xb4, + 0xb9, + 0xae, + 0xa3, + 0x80, + 0x8d, + 0x9a, + 0x97, + }; + + /** + * Precalculated lookup table for galois field multiplication by 14 used in + * the MixColums step during decryption. + */ + private static final int[] MULT14 = { + 0x00, + 0x0e, + 0x1c, + 0x12, + 0x38, + 0x36, + 0x24, + 0x2a, + 0x70, + 0x7e, + 0x6c, + 0x62, + 0x48, + 0x46, + 0x54, + 0x5a, + 0xe0, + 0xee, + 0xfc, + 0xf2, + 0xd8, + 0xd6, + 0xc4, + 0xca, + 0x90, + 0x9e, + 0x8c, + 0x82, + 0xa8, + 0xa6, + 0xb4, + 0xba, + 0xdb, + 0xd5, + 0xc7, + 0xc9, + 0xe3, + 0xed, + 0xff, + 0xf1, + 0xab, + 0xa5, + 0xb7, + 0xb9, + 0x93, + 0x9d, + 0x8f, + 0x81, + 0x3b, + 0x35, + 0x27, + 0x29, + 0x03, + 0x0d, + 0x1f, + 0x11, + 0x4b, + 0x45, + 0x57, + 0x59, + 0x73, + 0x7d, + 0x6f, + 0x61, + 0xad, + 0xa3, + 0xb1, + 0xbf, + 0x95, + 0x9b, + 0x89, + 0x87, + 0xdd, + 0xd3, + 0xc1, + 0xcf, + 0xe5, + 0xeb, + 0xf9, + 0xf7, + 0x4d, + 0x43, + 0x51, + 0x5f, + 0x75, + 0x7b, + 0x69, + 0x67, + 0x3d, + 0x33, + 0x21, + 0x2f, + 0x05, + 0x0b, + 0x19, + 0x17, + 0x76, + 0x78, + 0x6a, + 0x64, + 0x4e, + 0x40, + 0x52, + 0x5c, + 0x06, + 0x08, + 0x1a, + 0x14, + 0x3e, + 0x30, + 0x22, + 0x2c, + 0x96, + 0x98, + 0x8a, + 0x84, + 0xae, + 0xa0, + 0xb2, + 0xbc, + 0xe6, + 0xe8, + 0xfa, + 0xf4, + 0xde, + 0xd0, + 0xc2, + 0xcc, + 0x41, + 0x4f, + 0x5d, + 0x53, + 0x79, + 0x77, + 0x65, + 0x6b, + 0x31, + 0x3f, + 0x2d, + 0x23, + 0x09, + 0x07, + 0x15, + 0x1b, + 0xa1, + 0xaf, + 0xbd, + 0xb3, + 0x99, + 0x97, + 0x85, + 0x8b, + 0xd1, + 0xdf, + 0xcd, + 0xc3, + 0xe9, + 0xe7, + 0xf5, + 0xfb, + 0x9a, + 0x94, + 0x86, + 0x88, + 0xa2, + 0xac, + 0xbe, + 0xb0, + 0xea, + 0xe4, + 0xf6, + 0xf8, + 0xd2, + 0xdc, + 0xce, + 0xc0, + 0x7a, + 0x74, + 0x66, + 0x68, + 0x42, + 0x4c, + 0x5e, + 0x50, + 0x0a, + 0x04, + 0x16, + 0x18, + 0x32, + 0x3c, + 0x2e, + 0x20, + 0xec, + 0xe2, + 0xf0, + 0xfe, + 0xd4, + 0xda, + 0xc8, + 0xc6, + 0x9c, + 0x92, + 0x80, + 0x8e, + 0xa4, + 0xaa, + 0xb8, + 0xb6, + 0x0c, + 0x02, + 0x10, + 0x1e, + 0x34, + 0x3a, + 0x28, + 0x26, + 0x7c, + 0x72, + 0x60, + 0x6e, + 0x44, + 0x4a, + 0x58, + 0x56, + 0x37, + 0x39, + 0x2b, + 0x25, + 0x0f, + 0x01, + 0x13, + 0x1d, + 0x47, + 0x49, + 0x5b, + 0x55, + 0x7f, + 0x71, + 0x63, + 0x6d, + 0xd7, + 0xd9, + 0xcb, + 0xc5, + 0xef, + 0xe1, + 0xf3, + 0xfd, + 0xa7, + 0xa9, + 0xbb, + 0xb5, + 0x9f, + 0x91, + 0x83, + 0x8d, + }; + + /** + * Subroutine of the Rijndael key expansion. + */ + public static BigInteger scheduleCore(BigInteger t, int rconCounter) { + StringBuilder rBytes = new StringBuilder(t.toString(16)); + + // Add zero padding + while (rBytes.length() < 8) { + rBytes.insert(0, "0"); + } + + // rotate the first 16 bits to the back + String rotatingBytes = rBytes.substring(0, 2); + String fixedBytes = rBytes.substring(2); + + rBytes = new StringBuilder(fixedBytes + rotatingBytes); + + // apply S-Box to all 8-Bit Substrings + for (int i = 0; i < 4; i++) { + StringBuilder currentByteBits = new StringBuilder(rBytes.substring(i * 2, (i + 1) * 2)); + + int currentByte = Integer.parseInt(currentByteBits.toString(), 16); + currentByte = SBOX[currentByte]; + + // add the current RCON value to the first byte + if (i == 0) { + currentByte = currentByte ^ RCON[rconCounter]; + } + + currentByteBits = new StringBuilder(Integer.toHexString(currentByte)); + + // Add zero padding + while (currentByteBits.length() < 2) { + currentByteBits.insert(0, '0'); + } + + // replace bytes in original string + rBytes = new StringBuilder(rBytes.substring(0, i * 2) + currentByteBits + rBytes.substring((i + 1) * 2)); + } + + return new BigInteger(rBytes.toString(), 16); + } + + /** + * Returns an array of 10 + 1 round keys that are calculated by using + * Rijndael key schedule + * + * @return array of 10 + 1 round keys + */ + public static BigInteger[] keyExpansion(BigInteger initialKey) { + BigInteger[] roundKeys = { + initialKey, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + }; + + // initialize rcon iteration + int rconCounter = 1; + + for (int i = 1; i < 11; i++) { + // get the previous 32 bits the key + BigInteger t = roundKeys[i - 1].remainder(new BigInteger("100000000", 16)); + + // split previous key into 8-bit segments + BigInteger[] prevKey = { + roundKeys[i - 1].remainder(new BigInteger("100000000", 16)), + roundKeys[i - 1].remainder(new BigInteger("10000000000000000", 16)).divide(new BigInteger("100000000", 16)), + roundKeys[i - 1].remainder(new BigInteger("1000000000000000000000000", 16)).divide(new BigInteger("10000000000000000", 16)), + roundKeys[i - 1].divide(new BigInteger("1000000000000000000000000", 16)), + }; + + // run schedule core + t = scheduleCore(t, rconCounter); + rconCounter += 1; + + // Calculate partial round key + BigInteger t0 = t.xor(prevKey[3]); + BigInteger t1 = t0.xor(prevKey[2]); + BigInteger t2 = t1.xor(prevKey[1]); + BigInteger t3 = t2.xor(prevKey[0]); + + // Join round key segments + t2 = t2.multiply(new BigInteger("100000000", 16)); + t1 = t1.multiply(new BigInteger("10000000000000000", 16)); + t0 = t0.multiply(new BigInteger("1000000000000000000000000", 16)); + roundKeys[i] = t0.add(t1).add(t2).add(t3); + } + return roundKeys; + } + + /** + * representation of the input 128-bit block as an array of 8-bit integers. + * + * @param block of 128-bit integers + * @return array of 8-bit integers + */ + public static int[] splitBlockIntoCells(BigInteger block) { + int[] cells = new int[16]; + StringBuilder blockBits = new StringBuilder(block.toString(2)); + + // Append leading 0 for full "128-bit" string + while (blockBits.length() < 128) { + blockBits.insert(0, '0'); + } + + // split 128 to 8 bit cells + for (int i = 0; i < cells.length; i++) { + String cellBits = blockBits.substring(8 * i, 8 * (i + 1)); + cells[i] = Integer.parseInt(cellBits, 2); + } + + return cells; + } + + /** + * Returns the 128-bit BigInteger representation of the input of an array of + * 8-bit integers. + * + * @param cells that we need to merge + * @return block of merged cells + */ + public static BigInteger mergeCellsIntoBlock(int[] cells) { + StringBuilder blockBits = new StringBuilder(); + for (int i = 0; i < 16; i++) { + StringBuilder cellBits = new StringBuilder(Integer.toBinaryString(cells[i])); + + // Append leading 0 for full "8-bit" strings + while (cellBits.length() < 8) { + cellBits.insert(0, '0'); + } + + blockBits.append(cellBits); + } + + return new BigInteger(blockBits.toString(), 2); + } + + /** + * @return ciphertext XOR key + */ + public static BigInteger addRoundKey(BigInteger ciphertext, BigInteger key) { + return ciphertext.xor(key); + } + + /** + * substitutes 8-Bit long substrings of the input using the S-Box and + * returns the result. + * + * @return subtraction Output + */ + public static BigInteger subBytes(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + + for (int i = 0; i < 16; i++) { + cells[i] = SBOX[cells[i]]; + } + + return mergeCellsIntoBlock(cells); + } + + /** + * substitutes 8-Bit long substrings of the input using the inverse S-Box + * for decryption and returns the result. + * + * @return subtraction Output + */ + public static BigInteger subBytesDec(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + + for (int i = 0; i < 16; i++) { + cells[i] = INVERSE_SBOX[cells[i]]; + } + + return mergeCellsIntoBlock(cells); + } + + /** + * Cell permutation step. Shifts cells within the rows of the input and + * returns the result. + */ + public static BigInteger shiftRows(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] output = new int[16]; + + // do nothing in the first row + output[0] = cells[0]; + output[4] = cells[4]; + output[8] = cells[8]; + output[12] = cells[12]; + + // shift the second row backwards by one cell + output[1] = cells[5]; + output[5] = cells[9]; + output[9] = cells[13]; + output[13] = cells[1]; + + // shift the third row backwards by two cell + output[2] = cells[10]; + output[6] = cells[14]; + output[10] = cells[2]; + output[14] = cells[6]; + + // shift the forth row backwards by tree cell + output[3] = cells[15]; + output[7] = cells[3]; + output[11] = cells[7]; + output[15] = cells[11]; + + return mergeCellsIntoBlock(output); + } + + /** + * Cell permutation step for decryption . Shifts cells within the rows of + * the input and returns the result. + */ + public static BigInteger shiftRowsDec(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] output = new int[16]; + + // do nothing in the first row + output[0] = cells[0]; + output[4] = cells[4]; + output[8] = cells[8]; + output[12] = cells[12]; + + // shift the second row forwards by one cell + output[1] = cells[13]; + output[5] = cells[1]; + output[9] = cells[5]; + output[13] = cells[9]; + + // shift the third row forwards by two cell + output[2] = cells[10]; + output[6] = cells[14]; + output[10] = cells[2]; + output[14] = cells[6]; + + // shift the forth row forwards by tree cell + output[3] = cells[7]; + output[7] = cells[11]; + output[11] = cells[15]; + output[15] = cells[3]; + + return mergeCellsIntoBlock(output); + } + + /** + * Applies the Rijndael MixColumns to the input and returns the result. + */ + public static BigInteger mixColumns(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] outputCells = new int[16]; + + for (int i = 0; i < 4; i++) { + int[] row = { + cells[i * 4], + cells[i * 4 + 1], + cells[i * 4 + 2], + cells[i * 4 + 3], + }; + + outputCells[i * 4] = MULT2[row[0]] ^ MULT3[row[1]] ^ row[2] ^ row[3]; + outputCells[i * 4 + 1] = row[0] ^ MULT2[row[1]] ^ MULT3[row[2]] ^ row[3]; + outputCells[i * 4 + 2] = row[0] ^ row[1] ^ MULT2[row[2]] ^ MULT3[row[3]]; + outputCells[i * 4 + 3] = MULT3[row[0]] ^ row[1] ^ row[2] ^ MULT2[row[3]]; + } + return mergeCellsIntoBlock(outputCells); + } + + /** + * Applies the inverse Rijndael MixColumns for decryption to the input and + * returns the result. + */ + public static BigInteger mixColumnsDec(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] outputCells = new int[16]; + + for (int i = 0; i < 4; i++) { + int[] row = { + cells[i * 4], + cells[i * 4 + 1], + cells[i * 4 + 2], + cells[i * 4 + 3], + }; + + outputCells[i * 4] = MULT14[row[0]] ^ MULT11[row[1]] ^ MULT13[row[2]] ^ MULT9[row[3]]; + outputCells[i * 4 + 1] = MULT9[row[0]] ^ MULT14[row[1]] ^ MULT11[row[2]] ^ MULT13[row[3]]; + outputCells[i * 4 + 2] = MULT13[row[0]] ^ MULT9[row[1]] ^ MULT14[row[2]] ^ MULT11[row[3]]; + outputCells[i * 4 + 3] = MULT11[row[0]] ^ MULT13[row[1]] ^ MULT9[row[2]] ^ MULT14[row[3]]; + } + return mergeCellsIntoBlock(outputCells); + } + + /** + * Encrypts the plaintext with the key and returns the result + * + * @param plainText which we want to encrypt + * @param key the key for encrypt + * @return EncryptedText + */ + public static BigInteger encrypt(BigInteger plainText, BigInteger key) { + BigInteger[] roundKeys = keyExpansion(key); + + // Initial round + plainText = addRoundKey(plainText, roundKeys[0]); + + // Main rounds + for (int i = 1; i < 10; i++) { + plainText = subBytes(plainText); + plainText = shiftRows(plainText); + plainText = mixColumns(plainText); + plainText = addRoundKey(plainText, roundKeys[i]); + } + + // Final round + plainText = subBytes(plainText); + plainText = shiftRows(plainText); + plainText = addRoundKey(plainText, roundKeys[10]); + + return plainText; + } + + /** + * Decrypts the ciphertext with the key and returns the result + * + * @param cipherText The Encrypted text which we want to decrypt + * @return decryptedText + */ + public static BigInteger decrypt(BigInteger cipherText, BigInteger key) { + BigInteger[] roundKeys = keyExpansion(key); + + // Invert final round + cipherText = addRoundKey(cipherText, roundKeys[10]); + cipherText = shiftRowsDec(cipherText); + cipherText = subBytesDec(cipherText); + + // Invert main rounds + for (int i = 9; i > 0; i--) { + cipherText = addRoundKey(cipherText, roundKeys[i]); + cipherText = mixColumnsDec(cipherText); + cipherText = shiftRowsDec(cipherText); + cipherText = subBytesDec(cipherText); + } + + // Invert initial round + cipherText = addRoundKey(cipherText, roundKeys[0]); + + return cipherText; + } + + public static void main(String[] args) { + try (Scanner input = new Scanner(System.in)) { + System.out.println("Enter (e) letter for encrypt or (d) letter for decrypt :"); + char choice = input.nextLine().charAt(0); + String in; + switch (choice) { + case 'E', 'e' -> { + System.out.println( + "Choose a plaintext block (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger plaintext = new BigInteger(in, 16); + System.out.println( + "Choose a Key (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger encryptionKey = new BigInteger(in, 16); + System.out.println( + "The encrypted message is: \n" + + encrypt(plaintext, encryptionKey).toString(16) + ); + } + case 'D', 'd' -> { + System.out.println( + "Enter your ciphertext block (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger ciphertext = new BigInteger(in, 16); + System.out.println( + "Choose a Key (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger decryptionKey = new BigInteger(in, 16); + System.out.println( + "The deciphered message is:\n" + + decrypt(ciphertext, decryptionKey).toString(16) + ); + } + default -> System.out.println("** End **"); + } + } + } +} +package com.thealgorithms.ciphers; + +import java.math.BigInteger; +import java.util.Scanner; + +/** + * This class is build to demonstrate the application of the AES-algorithm on a + * single 128-Bit block of data. + */ +public final class AES { + private AES() { + } + + /** + * Precalculated values for x to the power of 2 in Rijndaels galois field. + * Used as 'RCON' during the key expansion. + */ + private static final int[] RCON = { + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + 0x01, + 0x02, + 0x04, + 0x08, + 0x10, + 0x20, + 0x40, + 0x80, + 0x1b, + 0x36, + 0x6c, + 0xd8, + 0xab, + 0x4d, + 0x9a, + 0x2f, + 0x5e, + 0xbc, + 0x63, + 0xc6, + 0x97, + 0x35, + 0x6a, + 0xd4, + 0xb3, + 0x7d, + 0xfa, + 0xef, + 0xc5, + 0x91, + 0x39, + 0x72, + 0xe4, + 0xd3, + 0xbd, + 0x61, + 0xc2, + 0x9f, + 0x25, + 0x4a, + 0x94, + 0x33, + 0x66, + 0xcc, + 0x83, + 0x1d, + 0x3a, + 0x74, + 0xe8, + 0xcb, + 0x8d, + }; + + /** + * Rijndael S-box Substitution table used for encryption in the subBytes + * step, as well as the key expansion. + */ + private static final int[] SBOX = { + 0x63, + 0x7C, + 0x77, + 0x7B, + 0xF2, + 0x6B, + 0x6F, + 0xC5, + 0x30, + 0x01, + 0x67, + 0x2B, + 0xFE, + 0xD7, + 0xAB, + 0x76, + 0xCA, + 0x82, + 0xC9, + 0x7D, + 0xFA, + 0x59, + 0x47, + 0xF0, + 0xAD, + 0xD4, + 0xA2, + 0xAF, + 0x9C, + 0xA4, + 0x72, + 0xC0, + 0xB7, + 0xFD, + 0x93, + 0x26, + 0x36, + 0x3F, + 0xF7, + 0xCC, + 0x34, + 0xA5, + 0xE5, + 0xF1, + 0x71, + 0xD8, + 0x31, + 0x15, + 0x04, + 0xC7, + 0x23, + 0xC3, + 0x18, + 0x96, + 0x05, + 0x9A, + 0x07, + 0x12, + 0x80, + 0xE2, + 0xEB, + 0x27, + 0xB2, + 0x75, + 0x09, + 0x83, + 0x2C, + 0x1A, + 0x1B, + 0x6E, + 0x5A, + 0xA0, + 0x52, + 0x3B, + 0xD6, + 0xB3, + 0x29, + 0xE3, + 0x2F, + 0x84, + 0x53, + 0xD1, + 0x00, + 0xED, + 0x20, + 0xFC, + 0xB1, + 0x5B, + 0x6A, + 0xCB, + 0xBE, + 0x39, + 0x4A, + 0x4C, + 0x58, + 0xCF, + 0xD0, + 0xEF, + 0xAA, + 0xFB, + 0x43, + 0x4D, + 0x33, + 0x85, + 0x45, + 0xF9, + 0x02, + 0x7F, + 0x50, + 0x3C, + 0x9F, + 0xA8, + 0x51, + 0xA3, + 0x40, + 0x8F, + 0x92, + 0x9D, + 0x38, + 0xF5, + 0xBC, + 0xB6, + 0xDA, + 0x21, + 0x10, + 0xFF, + 0xF3, + 0xD2, + 0xCD, + 0x0C, + 0x13, + 0xEC, + 0x5F, + 0x97, + 0x44, + 0x17, + 0xC4, + 0xA7, + 0x7E, + 0x3D, + 0x64, + 0x5D, + 0x19, + 0x73, + 0x60, + 0x81, + 0x4F, + 0xDC, + 0x22, + 0x2A, + 0x90, + 0x88, + 0x46, + 0xEE, + 0xB8, + 0x14, + 0xDE, + 0x5E, + 0x0B, + 0xDB, + 0xE0, + 0x32, + 0x3A, + 0x0A, + 0x49, + 0x06, + 0x24, + 0x5C, + 0xC2, + 0xD3, + 0xAC, + 0x62, + 0x91, + 0x95, + 0xE4, + 0x79, + 0xE7, + 0xC8, + 0x37, + 0x6D, + 0x8D, + 0xD5, + 0x4E, + 0xA9, + 0x6C, + 0x56, + 0xF4, + 0xEA, + 0x65, + 0x7A, + 0xAE, + 0x08, + 0xBA, + 0x78, + 0x25, + 0x2E, + 0x1C, + 0xA6, + 0xB4, + 0xC6, + 0xE8, + 0xDD, + 0x74, + 0x1F, + 0x4B, + 0xBD, + 0x8B, + 0x8A, + 0x70, + 0x3E, + 0xB5, + 0x66, + 0x48, + 0x03, + 0xF6, + 0x0E, + 0x61, + 0x35, + 0x57, + 0xB9, + 0x86, + 0xC1, + 0x1D, + 0x9E, + 0xE1, + 0xF8, + 0x98, + 0x11, + 0x69, + 0xD9, + 0x8E, + 0x94, + 0x9B, + 0x1E, + 0x87, + 0xE9, + 0xCE, + 0x55, + 0x28, + 0xDF, + 0x8C, + 0xA1, + 0x89, + 0x0D, + 0xBF, + 0xE6, + 0x42, + 0x68, + 0x41, + 0x99, + 0x2D, + 0x0F, + 0xB0, + 0x54, + 0xBB, + 0x16, + }; + + /** + * Inverse Rijndael S-box Substitution table used for decryption in the + * subBytesDec step. + */ + private static final int[] INVERSE_SBOX = { + 0x52, + 0x09, + 0x6A, + 0xD5, + 0x30, + 0x36, + 0xA5, + 0x38, + 0xBF, + 0x40, + 0xA3, + 0x9E, + 0x81, + 0xF3, + 0xD7, + 0xFB, + 0x7C, + 0xE3, + 0x39, + 0x82, + 0x9B, + 0x2F, + 0xFF, + 0x87, + 0x34, + 0x8E, + 0x43, + 0x44, + 0xC4, + 0xDE, + 0xE9, + 0xCB, + 0x54, + 0x7B, + 0x94, + 0x32, + 0xA6, + 0xC2, + 0x23, + 0x3D, + 0xEE, + 0x4C, + 0x95, + 0x0B, + 0x42, + 0xFA, + 0xC3, + 0x4E, + 0x08, + 0x2E, + 0xA1, + 0x66, + 0x28, + 0xD9, + 0x24, + 0xB2, + 0x76, + 0x5B, + 0xA2, + 0x49, + 0x6D, + 0x8B, + 0xD1, + 0x25, + 0x72, + 0xF8, + 0xF6, + 0x64, + 0x86, + 0x68, + 0x98, + 0x16, + 0xD4, + 0xA4, + 0x5C, + 0xCC, + 0x5D, + 0x65, + 0xB6, + 0x92, + 0x6C, + 0x70, + 0x48, + 0x50, + 0xFD, + 0xED, + 0xB9, + 0xDA, + 0x5E, + 0x15, + 0x46, + 0x57, + 0xA7, + 0x8D, + 0x9D, + 0x84, + 0x90, + 0xD8, + 0xAB, + 0x00, + 0x8C, + 0xBC, + 0xD3, + 0x0A, + 0xF7, + 0xE4, + 0x58, + 0x05, + 0xB8, + 0xB3, + 0x45, + 0x06, + 0xD0, + 0x2C, + 0x1E, + 0x8F, + 0xCA, + 0x3F, + 0x0F, + 0x02, + 0xC1, + 0xAF, + 0xBD, + 0x03, + 0x01, + 0x13, + 0x8A, + 0x6B, + 0x3A, + 0x91, + 0x11, + 0x41, + 0x4F, + 0x67, + 0xDC, + 0xEA, + 0x97, + 0xF2, + 0xCF, + 0xCE, + 0xF0, + 0xB4, + 0xE6, + 0x73, + 0x96, + 0xAC, + 0x74, + 0x22, + 0xE7, + 0xAD, + 0x35, + 0x85, + 0xE2, + 0xF9, + 0x37, + 0xE8, + 0x1C, + 0x75, + 0xDF, + 0x6E, + 0x47, + 0xF1, + 0x1A, + 0x71, + 0x1D, + 0x29, + 0xC5, + 0x89, + 0x6F, + 0xB7, + 0x62, + 0x0E, + 0xAA, + 0x18, + 0xBE, + 0x1B, + 0xFC, + 0x56, + 0x3E, + 0x4B, + 0xC6, + 0xD2, + 0x79, + 0x20, + 0x9A, + 0xDB, + 0xC0, + 0xFE, + 0x78, + 0xCD, + 0x5A, + 0xF4, + 0x1F, + 0xDD, + 0xA8, + 0x33, + 0x88, + 0x07, + 0xC7, + 0x31, + 0xB1, + 0x12, + 0x10, + 0x59, + 0x27, + 0x80, + 0xEC, + 0x5F, + 0x60, + 0x51, + 0x7F, + 0xA9, + 0x19, + 0xB5, + 0x4A, + 0x0D, + 0x2D, + 0xE5, + 0x7A, + 0x9F, + 0x93, + 0xC9, + 0x9C, + 0xEF, + 0xA0, + 0xE0, + 0x3B, + 0x4D, + 0xAE, + 0x2A, + 0xF5, + 0xB0, + 0xC8, + 0xEB, + 0xBB, + 0x3C, + 0x83, + 0x53, + 0x99, + 0x61, + 0x17, + 0x2B, + 0x04, + 0x7E, + 0xBA, + 0x77, + 0xD6, + 0x26, + 0xE1, + 0x69, + 0x14, + 0x63, + 0x55, + 0x21, + 0x0C, + 0x7D, + }; + + /** + * Precalculated lookup table for galois field multiplication by 2 used in + * the MixColums step during encryption. + */ + private static final int[] MULT2 = { + 0x00, + 0x02, + 0x04, + 0x06, + 0x08, + 0x0a, + 0x0c, + 0x0e, + 0x10, + 0x12, + 0x14, + 0x16, + 0x18, + 0x1a, + 0x1c, + 0x1e, + 0x20, + 0x22, + 0x24, + 0x26, + 0x28, + 0x2a, + 0x2c, + 0x2e, + 0x30, + 0x32, + 0x34, + 0x36, + 0x38, + 0x3a, + 0x3c, + 0x3e, + 0x40, + 0x42, + 0x44, + 0x46, + 0x48, + 0x4a, + 0x4c, + 0x4e, + 0x50, + 0x52, + 0x54, + 0x56, + 0x58, + 0x5a, + 0x5c, + 0x5e, + 0x60, + 0x62, + 0x64, + 0x66, + 0x68, + 0x6a, + 0x6c, + 0x6e, + 0x70, + 0x72, + 0x74, + 0x76, + 0x78, + 0x7a, + 0x7c, + 0x7e, + 0x80, + 0x82, + 0x84, + 0x86, + 0x88, + 0x8a, + 0x8c, + 0x8e, + 0x90, + 0x92, + 0x94, + 0x96, + 0x98, + 0x9a, + 0x9c, + 0x9e, + 0xa0, + 0xa2, + 0xa4, + 0xa6, + 0xa8, + 0xaa, + 0xac, + 0xae, + 0xb0, + 0xb2, + 0xb4, + 0xb6, + 0xb8, + 0xba, + 0xbc, + 0xbe, + 0xc0, + 0xc2, + 0xc4, + 0xc6, + 0xc8, + 0xca, + 0xcc, + 0xce, + 0xd0, + 0xd2, + 0xd4, + 0xd6, + 0xd8, + 0xda, + 0xdc, + 0xde, + 0xe0, + 0xe2, + 0xe4, + 0xe6, + 0xe8, + 0xea, + 0xec, + 0xee, + 0xf0, + 0xf2, + 0xf4, + 0xf6, + 0xf8, + 0xfa, + 0xfc, + 0xfe, + 0x1b, + 0x19, + 0x1f, + 0x1d, + 0x13, + 0x11, + 0x17, + 0x15, + 0x0b, + 0x09, + 0x0f, + 0x0d, + 0x03, + 0x01, + 0x07, + 0x05, + 0x3b, + 0x39, + 0x3f, + 0x3d, + 0x33, + 0x31, + 0x37, + 0x35, + 0x2b, + 0x29, + 0x2f, + 0x2d, + 0x23, + 0x21, + 0x27, + 0x25, + 0x5b, + 0x59, + 0x5f, + 0x5d, + 0x53, + 0x51, + 0x57, + 0x55, + 0x4b, + 0x49, + 0x4f, + 0x4d, + 0x43, + 0x41, + 0x47, + 0x45, + 0x7b, + 0x79, + 0x7f, + 0x7d, + 0x73, + 0x71, + 0x77, + 0x75, + 0x6b, + 0x69, + 0x6f, + 0x6d, + 0x63, + 0x61, + 0x67, + 0x65, + 0x9b, + 0x99, + 0x9f, + 0x9d, + 0x93, + 0x91, + 0x97, + 0x95, + 0x8b, + 0x89, + 0x8f, + 0x8d, + 0x83, + 0x81, + 0x87, + 0x85, + 0xbb, + 0xb9, + 0xbf, + 0xbd, + 0xb3, + 0xb1, + 0xb7, + 0xb5, + 0xab, + 0xa9, + 0xaf, + 0xad, + 0xa3, + 0xa1, + 0xa7, + 0xa5, + 0xdb, + 0xd9, + 0xdf, + 0xdd, + 0xd3, + 0xd1, + 0xd7, + 0xd5, + 0xcb, + 0xc9, + 0xcf, + 0xcd, + 0xc3, + 0xc1, + 0xc7, + 0xc5, + 0xfb, + 0xf9, + 0xff, + 0xfd, + 0xf3, + 0xf1, + 0xf7, + 0xf5, + 0xeb, + 0xe9, + 0xef, + 0xed, + 0xe3, + 0xe1, + 0xe7, + 0xe5, + }; + + /** + * Precalculated lookup table for galois field multiplication by 3 used in + * the MixColums step during encryption. + */ + private static final int[] MULT3 = { + 0x00, + 0x03, + 0x06, + 0x05, + 0x0c, + 0x0f, + 0x0a, + 0x09, + 0x18, + 0x1b, + 0x1e, + 0x1d, + 0x14, + 0x17, + 0x12, + 0x11, + 0x30, + 0x33, + 0x36, + 0x35, + 0x3c, + 0x3f, + 0x3a, + 0x39, + 0x28, + 0x2b, + 0x2e, + 0x2d, + 0x24, + 0x27, + 0x22, + 0x21, + 0x60, + 0x63, + 0x66, + 0x65, + 0x6c, + 0x6f, + 0x6a, + 0x69, + 0x78, + 0x7b, + 0x7e, + 0x7d, + 0x74, + 0x77, + 0x72, + 0x71, + 0x50, + 0x53, + 0x56, + 0x55, + 0x5c, + 0x5f, + 0x5a, + 0x59, + 0x48, + 0x4b, + 0x4e, + 0x4d, + 0x44, + 0x47, + 0x42, + 0x41, + 0xc0, + 0xc3, + 0xc6, + 0xc5, + 0xcc, + 0xcf, + 0xca, + 0xc9, + 0xd8, + 0xdb, + 0xde, + 0xdd, + 0xd4, + 0xd7, + 0xd2, + 0xd1, + 0xf0, + 0xf3, + 0xf6, + 0xf5, + 0xfc, + 0xff, + 0xfa, + 0xf9, + 0xe8, + 0xeb, + 0xee, + 0xed, + 0xe4, + 0xe7, + 0xe2, + 0xe1, + 0xa0, + 0xa3, + 0xa6, + 0xa5, + 0xac, + 0xaf, + 0xaa, + 0xa9, + 0xb8, + 0xbb, + 0xbe, + 0xbd, + 0xb4, + 0xb7, + 0xb2, + 0xb1, + 0x90, + 0x93, + 0x96, + 0x95, + 0x9c, + 0x9f, + 0x9a, + 0x99, + 0x88, + 0x8b, + 0x8e, + 0x8d, + 0x84, + 0x87, + 0x82, + 0x81, + 0x9b, + 0x98, + 0x9d, + 0x9e, + 0x97, + 0x94, + 0x91, + 0x92, + 0x83, + 0x80, + 0x85, + 0x86, + 0x8f, + 0x8c, + 0x89, + 0x8a, + 0xab, + 0xa8, + 0xad, + 0xae, + 0xa7, + 0xa4, + 0xa1, + 0xa2, + 0xb3, + 0xb0, + 0xb5, + 0xb6, + 0xbf, + 0xbc, + 0xb9, + 0xba, + 0xfb, + 0xf8, + 0xfd, + 0xfe, + 0xf7, + 0xf4, + 0xf1, + 0xf2, + 0xe3, + 0xe0, + 0xe5, + 0xe6, + 0xef, + 0xec, + 0xe9, + 0xea, + 0xcb, + 0xc8, + 0xcd, + 0xce, + 0xc7, + 0xc4, + 0xc1, + 0xc2, + 0xd3, + 0xd0, + 0xd5, + 0xd6, + 0xdf, + 0xdc, + 0xd9, + 0xda, + 0x5b, + 0x58, + 0x5d, + 0x5e, + 0x57, + 0x54, + 0x51, + 0x52, + 0x43, + 0x40, + 0x45, + 0x46, + 0x4f, + 0x4c, + 0x49, + 0x4a, + 0x6b, + 0x68, + 0x6d, + 0x6e, + 0x67, + 0x64, + 0x61, + 0x62, + 0x73, + 0x70, + 0x75, + 0x76, + 0x7f, + 0x7c, + 0x79, + 0x7a, + 0x3b, + 0x38, + 0x3d, + 0x3e, + 0x37, + 0x34, + 0x31, + 0x32, + 0x23, + 0x20, + 0x25, + 0x26, + 0x2f, + 0x2c, + 0x29, + 0x2a, + 0x0b, + 0x08, + 0x0d, + 0x0e, + 0x07, + 0x04, + 0x01, + 0x02, + 0x13, + 0x10, + 0x15, + 0x16, + 0x1f, + 0x1c, + 0x19, + 0x1a, + }; + + /** + * Precalculated lookup table for galois field multiplication by 9 used in + * the MixColums step during decryption. + */ + private static final int[] MULT9 = { + 0x00, + 0x09, + 0x12, + 0x1b, + 0x24, + 0x2d, + 0x36, + 0x3f, + 0x48, + 0x41, + 0x5a, + 0x53, + 0x6c, + 0x65, + 0x7e, + 0x77, + 0x90, + 0x99, + 0x82, + 0x8b, + 0xb4, + 0xbd, + 0xa6, + 0xaf, + 0xd8, + 0xd1, + 0xca, + 0xc3, + 0xfc, + 0xf5, + 0xee, + 0xe7, + 0x3b, + 0x32, + 0x29, + 0x20, + 0x1f, + 0x16, + 0x0d, + 0x04, + 0x73, + 0x7a, + 0x61, + 0x68, + 0x57, + 0x5e, + 0x45, + 0x4c, + 0xab, + 0xa2, + 0xb9, + 0xb0, + 0x8f, + 0x86, + 0x9d, + 0x94, + 0xe3, + 0xea, + 0xf1, + 0xf8, + 0xc7, + 0xce, + 0xd5, + 0xdc, + 0x76, + 0x7f, + 0x64, + 0x6d, + 0x52, + 0x5b, + 0x40, + 0x49, + 0x3e, + 0x37, + 0x2c, + 0x25, + 0x1a, + 0x13, + 0x08, + 0x01, + 0xe6, + 0xef, + 0xf4, + 0xfd, + 0xc2, + 0xcb, + 0xd0, + 0xd9, + 0xae, + 0xa7, + 0xbc, + 0xb5, + 0x8a, + 0x83, + 0x98, + 0x91, + 0x4d, + 0x44, + 0x5f, + 0x56, + 0x69, + 0x60, + 0x7b, + 0x72, + 0x05, + 0x0c, + 0x17, + 0x1e, + 0x21, + 0x28, + 0x33, + 0x3a, + 0xdd, + 0xd4, + 0xcf, + 0xc6, + 0xf9, + 0xf0, + 0xeb, + 0xe2, + 0x95, + 0x9c, + 0x87, + 0x8e, + 0xb1, + 0xb8, + 0xa3, + 0xaa, + 0xec, + 0xe5, + 0xfe, + 0xf7, + 0xc8, + 0xc1, + 0xda, + 0xd3, + 0xa4, + 0xad, + 0xb6, + 0xbf, + 0x80, + 0x89, + 0x92, + 0x9b, + 0x7c, + 0x75, + 0x6e, + 0x67, + 0x58, + 0x51, + 0x4a, + 0x43, + 0x34, + 0x3d, + 0x26, + 0x2f, + 0x10, + 0x19, + 0x02, + 0x0b, + 0xd7, + 0xde, + 0xc5, + 0xcc, + 0xf3, + 0xfa, + 0xe1, + 0xe8, + 0x9f, + 0x96, + 0x8d, + 0x84, + 0xbb, + 0xb2, + 0xa9, + 0xa0, + 0x47, + 0x4e, + 0x55, + 0x5c, + 0x63, + 0x6a, + 0x71, + 0x78, + 0x0f, + 0x06, + 0x1d, + 0x14, + 0x2b, + 0x22, + 0x39, + 0x30, + 0x9a, + 0x93, + 0x88, + 0x81, + 0xbe, + 0xb7, + 0xac, + 0xa5, + 0xd2, + 0xdb, + 0xc0, + 0xc9, + 0xf6, + 0xff, + 0xe4, + 0xed, + 0x0a, + 0x03, + 0x18, + 0x11, + 0x2e, + 0x27, + 0x3c, + 0x35, + 0x42, + 0x4b, + 0x50, + 0x59, + 0x66, + 0x6f, + 0x74, + 0x7d, + 0xa1, + 0xa8, + 0xb3, + 0xba, + 0x85, + 0x8c, + 0x97, + 0x9e, + 0xe9, + 0xe0, + 0xfb, + 0xf2, + 0xcd, + 0xc4, + 0xdf, + 0xd6, + 0x31, + 0x38, + 0x23, + 0x2a, + 0x15, + 0x1c, + 0x07, + 0x0e, + 0x79, + 0x70, + 0x6b, + 0x62, + 0x5d, + 0x54, + 0x4f, + 0x46, + }; + + /** + * Precalculated lookup table for galois field multiplication by 11 used in + * the MixColums step during decryption. + */ + private static final int[] MULT11 = { + 0x00, + 0x0b, + 0x16, + 0x1d, + 0x2c, + 0x27, + 0x3a, + 0x31, + 0x58, + 0x53, + 0x4e, + 0x45, + 0x74, + 0x7f, + 0x62, + 0x69, + 0xb0, + 0xbb, + 0xa6, + 0xad, + 0x9c, + 0x97, + 0x8a, + 0x81, + 0xe8, + 0xe3, + 0xfe, + 0xf5, + 0xc4, + 0xcf, + 0xd2, + 0xd9, + 0x7b, + 0x70, + 0x6d, + 0x66, + 0x57, + 0x5c, + 0x41, + 0x4a, + 0x23, + 0x28, + 0x35, + 0x3e, + 0x0f, + 0x04, + 0x19, + 0x12, + 0xcb, + 0xc0, + 0xdd, + 0xd6, + 0xe7, + 0xec, + 0xf1, + 0xfa, + 0x93, + 0x98, + 0x85, + 0x8e, + 0xbf, + 0xb4, + 0xa9, + 0xa2, + 0xf6, + 0xfd, + 0xe0, + 0xeb, + 0xda, + 0xd1, + 0xcc, + 0xc7, + 0xae, + 0xa5, + 0xb8, + 0xb3, + 0x82, + 0x89, + 0x94, + 0x9f, + 0x46, + 0x4d, + 0x50, + 0x5b, + 0x6a, + 0x61, + 0x7c, + 0x77, + 0x1e, + 0x15, + 0x08, + 0x03, + 0x32, + 0x39, + 0x24, + 0x2f, + 0x8d, + 0x86, + 0x9b, + 0x90, + 0xa1, + 0xaa, + 0xb7, + 0xbc, + 0xd5, + 0xde, + 0xc3, + 0xc8, + 0xf9, + 0xf2, + 0xef, + 0xe4, + 0x3d, + 0x36, + 0x2b, + 0x20, + 0x11, + 0x1a, + 0x07, + 0x0c, + 0x65, + 0x6e, + 0x73, + 0x78, + 0x49, + 0x42, + 0x5f, + 0x54, + 0xf7, + 0xfc, + 0xe1, + 0xea, + 0xdb, + 0xd0, + 0xcd, + 0xc6, + 0xaf, + 0xa4, + 0xb9, + 0xb2, + 0x83, + 0x88, + 0x95, + 0x9e, + 0x47, + 0x4c, + 0x51, + 0x5a, + 0x6b, + 0x60, + 0x7d, + 0x76, + 0x1f, + 0x14, + 0x09, + 0x02, + 0x33, + 0x38, + 0x25, + 0x2e, + 0x8c, + 0x87, + 0x9a, + 0x91, + 0xa0, + 0xab, + 0xb6, + 0xbd, + 0xd4, + 0xdf, + 0xc2, + 0xc9, + 0xf8, + 0xf3, + 0xee, + 0xe5, + 0x3c, + 0x37, + 0x2a, + 0x21, + 0x10, + 0x1b, + 0x06, + 0x0d, + 0x64, + 0x6f, + 0x72, + 0x79, + 0x48, + 0x43, + 0x5e, + 0x55, + 0x01, + 0x0a, + 0x17, + 0x1c, + 0x2d, + 0x26, + 0x3b, + 0x30, + 0x59, + 0x52, + 0x4f, + 0x44, + 0x75, + 0x7e, + 0x63, + 0x68, + 0xb1, + 0xba, + 0xa7, + 0xac, + 0x9d, + 0x96, + 0x8b, + 0x80, + 0xe9, + 0xe2, + 0xff, + 0xf4, + 0xc5, + 0xce, + 0xd3, + 0xd8, + 0x7a, + 0x71, + 0x6c, + 0x67, + 0x56, + 0x5d, + 0x40, + 0x4b, + 0x22, + 0x29, + 0x34, + 0x3f, + 0x0e, + 0x05, + 0x18, + 0x13, + 0xca, + 0xc1, + 0xdc, + 0xd7, + 0xe6, + 0xed, + 0xf0, + 0xfb, + 0x92, + 0x99, + 0x84, + 0x8f, + 0xbe, + 0xb5, + 0xa8, + 0xa3, + }; + + /** + * Precalculated lookup table for galois field multiplication by 13 used in + * the MixColums step during decryption. + */ + private static final int[] MULT13 = { + 0x00, + 0x0d, + 0x1a, + 0x17, + 0x34, + 0x39, + 0x2e, + 0x23, + 0x68, + 0x65, + 0x72, + 0x7f, + 0x5c, + 0x51, + 0x46, + 0x4b, + 0xd0, + 0xdd, + 0xca, + 0xc7, + 0xe4, + 0xe9, + 0xfe, + 0xf3, + 0xb8, + 0xb5, + 0xa2, + 0xaf, + 0x8c, + 0x81, + 0x96, + 0x9b, + 0xbb, + 0xb6, + 0xa1, + 0xac, + 0x8f, + 0x82, + 0x95, + 0x98, + 0xd3, + 0xde, + 0xc9, + 0xc4, + 0xe7, + 0xea, + 0xfd, + 0xf0, + 0x6b, + 0x66, + 0x71, + 0x7c, + 0x5f, + 0x52, + 0x45, + 0x48, + 0x03, + 0x0e, + 0x19, + 0x14, + 0x37, + 0x3a, + 0x2d, + 0x20, + 0x6d, + 0x60, + 0x77, + 0x7a, + 0x59, + 0x54, + 0x43, + 0x4e, + 0x05, + 0x08, + 0x1f, + 0x12, + 0x31, + 0x3c, + 0x2b, + 0x26, + 0xbd, + 0xb0, + 0xa7, + 0xaa, + 0x89, + 0x84, + 0x93, + 0x9e, + 0xd5, + 0xd8, + 0xcf, + 0xc2, + 0xe1, + 0xec, + 0xfb, + 0xf6, + 0xd6, + 0xdb, + 0xcc, + 0xc1, + 0xe2, + 0xef, + 0xf8, + 0xf5, + 0xbe, + 0xb3, + 0xa4, + 0xa9, + 0x8a, + 0x87, + 0x90, + 0x9d, + 0x06, + 0x0b, + 0x1c, + 0x11, + 0x32, + 0x3f, + 0x28, + 0x25, + 0x6e, + 0x63, + 0x74, + 0x79, + 0x5a, + 0x57, + 0x40, + 0x4d, + 0xda, + 0xd7, + 0xc0, + 0xcd, + 0xee, + 0xe3, + 0xf4, + 0xf9, + 0xb2, + 0xbf, + 0xa8, + 0xa5, + 0x86, + 0x8b, + 0x9c, + 0x91, + 0x0a, + 0x07, + 0x10, + 0x1d, + 0x3e, + 0x33, + 0x24, + 0x29, + 0x62, + 0x6f, + 0x78, + 0x75, + 0x56, + 0x5b, + 0x4c, + 0x41, + 0x61, + 0x6c, + 0x7b, + 0x76, + 0x55, + 0x58, + 0x4f, + 0x42, + 0x09, + 0x04, + 0x13, + 0x1e, + 0x3d, + 0x30, + 0x27, + 0x2a, + 0xb1, + 0xbc, + 0xab, + 0xa6, + 0x85, + 0x88, + 0x9f, + 0x92, + 0xd9, + 0xd4, + 0xc3, + 0xce, + 0xed, + 0xe0, + 0xf7, + 0xfa, + 0xb7, + 0xba, + 0xad, + 0xa0, + 0x83, + 0x8e, + 0x99, + 0x94, + 0xdf, + 0xd2, + 0xc5, + 0xc8, + 0xeb, + 0xe6, + 0xf1, + 0xfc, + 0x67, + 0x6a, + 0x7d, + 0x70, + 0x53, + 0x5e, + 0x49, + 0x44, + 0x0f, + 0x02, + 0x15, + 0x18, + 0x3b, + 0x36, + 0x21, + 0x2c, + 0x0c, + 0x01, + 0x16, + 0x1b, + 0x38, + 0x35, + 0x22, + 0x2f, + 0x64, + 0x69, + 0x7e, + 0x73, + 0x50, + 0x5d, + 0x4a, + 0x47, + 0xdc, + 0xd1, + 0xc6, + 0xcb, + 0xe8, + 0xe5, + 0xf2, + 0xff, + 0xb4, + 0xb9, + 0xae, + 0xa3, + 0x80, + 0x8d, + 0x9a, + 0x97, + }; + + /** + * Precalculated lookup table for galois field multiplication by 14 used in + * the MixColums step during decryption. + */ + private static final int[] MULT14 = { + 0x00, + 0x0e, + 0x1c, + 0x12, + 0x38, + 0x36, + 0x24, + 0x2a, + 0x70, + 0x7e, + 0x6c, + 0x62, + 0x48, + 0x46, + 0x54, + 0x5a, + 0xe0, + 0xee, + 0xfc, + 0xf2, + 0xd8, + 0xd6, + 0xc4, + 0xca, + 0x90, + 0x9e, + 0x8c, + 0x82, + 0xa8, + 0xa6, + 0xb4, + 0xba, + 0xdb, + 0xd5, + 0xc7, + 0xc9, + 0xe3, + 0xed, + 0xff, + 0xf1, + 0xab, + 0xa5, + 0xb7, + 0xb9, + 0x93, + 0x9d, + 0x8f, + 0x81, + 0x3b, + 0x35, + 0x27, + 0x29, + 0x03, + 0x0d, + 0x1f, + 0x11, + 0x4b, + 0x45, + 0x57, + 0x59, + 0x73, + 0x7d, + 0x6f, + 0x61, + 0xad, + 0xa3, + 0xb1, + 0xbf, + 0x95, + 0x9b, + 0x89, + 0x87, + 0xdd, + 0xd3, + 0xc1, + 0xcf, + 0xe5, + 0xeb, + 0xf9, + 0xf7, + 0x4d, + 0x43, + 0x51, + 0x5f, + 0x75, + 0x7b, + 0x69, + 0x67, + 0x3d, + 0x33, + 0x21, + 0x2f, + 0x05, + 0x0b, + 0x19, + 0x17, + 0x76, + 0x78, + 0x6a, + 0x64, + 0x4e, + 0x40, + 0x52, + 0x5c, + 0x06, + 0x08, + 0x1a, + 0x14, + 0x3e, + 0x30, + 0x22, + 0x2c, + 0x96, + 0x98, + 0x8a, + 0x84, + 0xae, + 0xa0, + 0xb2, + 0xbc, + 0xe6, + 0xe8, + 0xfa, + 0xf4, + 0xde, + 0xd0, + 0xc2, + 0xcc, + 0x41, + 0x4f, + 0x5d, + 0x53, + 0x79, + 0x77, + 0x65, + 0x6b, + 0x31, + 0x3f, + 0x2d, + 0x23, + 0x09, + 0x07, + 0x15, + 0x1b, + 0xa1, + 0xaf, + 0xbd, + 0xb3, + 0x99, + 0x97, + 0x85, + 0x8b, + 0xd1, + 0xdf, + 0xcd, + 0xc3, + 0xe9, + 0xe7, + 0xf5, + 0xfb, + 0x9a, + 0x94, + 0x86, + 0x88, + 0xa2, + 0xac, + 0xbe, + 0xb0, + 0xea, + 0xe4, + 0xf6, + 0xf8, + 0xd2, + 0xdc, + 0xce, + 0xc0, + 0x7a, + 0x74, + 0x66, + 0x68, + 0x42, + 0x4c, + 0x5e, + 0x50, + 0x0a, + 0x04, + 0x16, + 0x18, + 0x32, + 0x3c, + 0x2e, + 0x20, + 0xec, + 0xe2, + 0xf0, + 0xfe, + 0xd4, + 0xda, + 0xc8, + 0xc6, + 0x9c, + 0x92, + 0x80, + 0x8e, + 0xa4, + 0xaa, + 0xb8, + 0xb6, + 0x0c, + 0x02, + 0x10, + 0x1e, + 0x34, + 0x3a, + 0x28, + 0x26, + 0x7c, + 0x72, + 0x60, + 0x6e, + 0x44, + 0x4a, + 0x58, + 0x56, + 0x37, + 0x39, + 0x2b, + 0x25, + 0x0f, + 0x01, + 0x13, + 0x1d, + 0x47, + 0x49, + 0x5b, + 0x55, + 0x7f, + 0x71, + 0x63, + 0x6d, + 0xd7, + 0xd9, + 0xcb, + 0xc5, + 0xef, + 0xe1, + 0xf3, + 0xfd, + 0xa7, + 0xa9, + 0xbb, + 0xb5, + 0x9f, + 0x91, + 0x83, + 0x8d, + }; + + /** + * Subroutine of the Rijndael key expansion. + */ + public static BigInteger scheduleCore(BigInteger t, int rconCounter) { + StringBuilder rBytes = new StringBuilder(t.toString(16)); + + // Add zero padding + while (rBytes.length() < 8) { + rBytes.insert(0, "0"); + } + + // rotate the first 16 bits to the back + String rotatingBytes = rBytes.substring(0, 2); + String fixedBytes = rBytes.substring(2); + + rBytes = new StringBuilder(fixedBytes + rotatingBytes); + + // apply S-Box to all 8-Bit Substrings + for (int i = 0; i < 4; i++) { + StringBuilder currentByteBits = new StringBuilder(rBytes.substring(i * 2, (i + 1) * 2)); + + int currentByte = Integer.parseInt(currentByteBits.toString(), 16); + currentByte = SBOX[currentByte]; + + // add the current RCON value to the first byte + if (i == 0) { + currentByte = currentByte ^ RCON[rconCounter]; + } + + currentByteBits = new StringBuilder(Integer.toHexString(currentByte)); + + // Add zero padding + while (currentByteBits.length() < 2) { + currentByteBits.insert(0, '0'); + } + + // replace bytes in original string + rBytes = new StringBuilder(rBytes.substring(0, i * 2) + currentByteBits + rBytes.substring((i + 1) * 2)); + } + + return new BigInteger(rBytes.toString(), 16); + } + + /** + * Returns an array of 10 + 1 round keys that are calculated by using + * Rijndael key schedule + * + * @return array of 10 + 1 round keys + */ + public static BigInteger[] keyExpansion(BigInteger initialKey) { + BigInteger[] roundKeys = { + initialKey, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + BigInteger.ZERO, + }; + + // initialize rcon iteration + int rconCounter = 1; + + for (int i = 1; i < 11; i++) { + // get the previous 32 bits the key + BigInteger t = roundKeys[i - 1].remainder(new BigInteger("100000000", 16)); + + // split previous key into 8-bit segments + BigInteger[] prevKey = { + roundKeys[i - 1].remainder(new BigInteger("100000000", 16)), + roundKeys[i - 1].remainder(new BigInteger("10000000000000000", 16)).divide(new BigInteger("100000000", 16)), + roundKeys[i - 1].remainder(new BigInteger("1000000000000000000000000", 16)).divide(new BigInteger("10000000000000000", 16)), + roundKeys[i - 1].divide(new BigInteger("1000000000000000000000000", 16)), + }; + + // run schedule core + t = scheduleCore(t, rconCounter); + rconCounter += 1; + + // Calculate partial round key + BigInteger t0 = t.xor(prevKey[3]); + BigInteger t1 = t0.xor(prevKey[2]); + BigInteger t2 = t1.xor(prevKey[1]); + BigInteger t3 = t2.xor(prevKey[0]); + + // Join round key segments + t2 = t2.multiply(new BigInteger("100000000", 16)); + t1 = t1.multiply(new BigInteger("10000000000000000", 16)); + t0 = t0.multiply(new BigInteger("1000000000000000000000000", 16)); + roundKeys[i] = t0.add(t1).add(t2).add(t3); + } + return roundKeys; + } + + /** + * representation of the input 128-bit block as an array of 8-bit integers. + * + * @param block of 128-bit integers + * @return array of 8-bit integers + */ + public static int[] splitBlockIntoCells(BigInteger block) { + int[] cells = new int[16]; + StringBuilder blockBits = new StringBuilder(block.toString(2)); + + // Append leading 0 for full "128-bit" string + while (blockBits.length() < 128) { + blockBits.insert(0, '0'); + } + + // split 128 to 8 bit cells + for (int i = 0; i < cells.length; i++) { + String cellBits = blockBits.substring(8 * i, 8 * (i + 1)); + cells[i] = Integer.parseInt(cellBits, 2); + } + + return cells; + } + + /** + * Returns the 128-bit BigInteger representation of the input of an array of + * 8-bit integers. + * + * @param cells that we need to merge + * @return block of merged cells + */ + public static BigInteger mergeCellsIntoBlock(int[] cells) { + StringBuilder blockBits = new StringBuilder(); + for (int i = 0; i < 16; i++) { + StringBuilder cellBits = new StringBuilder(Integer.toBinaryString(cells[i])); + + // Append leading 0 for full "8-bit" strings + while (cellBits.length() < 8) { + cellBits.insert(0, '0'); + } + + blockBits.append(cellBits); + } + + return new BigInteger(blockBits.toString(), 2); + } + + /** + * @return ciphertext XOR key + */ + public static BigInteger addRoundKey(BigInteger ciphertext, BigInteger key) { + return ciphertext.xor(key); + } + + /** + * substitutes 8-Bit long substrings of the input using the S-Box and + * returns the result. + * + * @return subtraction Output + */ + public static BigInteger subBytes(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + + for (int i = 0; i < 16; i++) { + cells[i] = SBOX[cells[i]]; + } + + return mergeCellsIntoBlock(cells); + } + + /** + * substitutes 8-Bit long substrings of the input using the inverse S-Box + * for decryption and returns the result. + * + * @return subtraction Output + */ + public static BigInteger subBytesDec(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + + for (int i = 0; i < 16; i++) { + cells[i] = INVERSE_SBOX[cells[i]]; + } + + return mergeCellsIntoBlock(cells); + } + + /** + * Cell permutation step. Shifts cells within the rows of the input and + * returns the result. + */ + public static BigInteger shiftRows(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] output = new int[16]; + + // do nothing in the first row + output[0] = cells[0]; + output[4] = cells[4]; + output[8] = cells[8]; + output[12] = cells[12]; + + // shift the second row backwards by one cell + output[1] = cells[5]; + output[5] = cells[9]; + output[9] = cells[13]; + output[13] = cells[1]; + + // shift the third row backwards by two cell + output[2] = cells[10]; + output[6] = cells[14]; + output[10] = cells[2]; + output[14] = cells[6]; + + // shift the forth row backwards by tree cell + output[3] = cells[15]; + output[7] = cells[3]; + output[11] = cells[7]; + output[15] = cells[11]; + + return mergeCellsIntoBlock(output); + } + + /** + * Cell permutation step for decryption . Shifts cells within the rows of + * the input and returns the result. + */ + public static BigInteger shiftRowsDec(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] output = new int[16]; + + // do nothing in the first row + output[0] = cells[0]; + output[4] = cells[4]; + output[8] = cells[8]; + output[12] = cells[12]; + + // shift the second row forwards by one cell + output[1] = cells[13]; + output[5] = cells[1]; + output[9] = cells[5]; + output[13] = cells[9]; + + // shift the third row forwards by two cell + output[2] = cells[10]; + output[6] = cells[14]; + output[10] = cells[2]; + output[14] = cells[6]; + + // shift the forth row forwards by tree cell + output[3] = cells[7]; + output[7] = cells[11]; + output[11] = cells[15]; + output[15] = cells[3]; + + return mergeCellsIntoBlock(output); + } + + /** + * Applies the Rijndael MixColumns to the input and returns the result. + */ + public static BigInteger mixColumns(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] outputCells = new int[16]; + + for (int i = 0; i < 4; i++) { + int[] row = { + cells[i * 4], + cells[i * 4 + 1], + cells[i * 4 + 2], + cells[i * 4 + 3], + }; + + outputCells[i * 4] = MULT2[row[0]] ^ MULT3[row[1]] ^ row[2] ^ row[3]; + outputCells[i * 4 + 1] = row[0] ^ MULT2[row[1]] ^ MULT3[row[2]] ^ row[3]; + outputCells[i * 4 + 2] = row[0] ^ row[1] ^ MULT2[row[2]] ^ MULT3[row[3]]; + outputCells[i * 4 + 3] = MULT3[row[0]] ^ row[1] ^ row[2] ^ MULT2[row[3]]; + } + return mergeCellsIntoBlock(outputCells); + } + + /** + * Applies the inverse Rijndael MixColumns for decryption to the input and + * returns the result. + */ + public static BigInteger mixColumnsDec(BigInteger ciphertext) { + int[] cells = splitBlockIntoCells(ciphertext); + int[] outputCells = new int[16]; + + for (int i = 0; i < 4; i++) { + int[] row = { + cells[i * 4], + cells[i * 4 + 1], + cells[i * 4 + 2], + cells[i * 4 + 3], + }; + + outputCells[i * 4] = MULT14[row[0]] ^ MULT11[row[1]] ^ MULT13[row[2]] ^ MULT9[row[3]]; + outputCells[i * 4 + 1] = MULT9[row[0]] ^ MULT14[row[1]] ^ MULT11[row[2]] ^ MULT13[row[3]]; + outputCells[i * 4 + 2] = MULT13[row[0]] ^ MULT9[row[1]] ^ MULT14[row[2]] ^ MULT11[row[3]]; + outputCells[i * 4 + 3] = MULT11[row[0]] ^ MULT13[row[1]] ^ MULT9[row[2]] ^ MULT14[row[3]]; + } + return mergeCellsIntoBlock(outputCells); + } + + /** + * Encrypts the plaintext with the key and returns the result + * + * @param plainText which we want to encrypt + * @param key the key for encrypt + * @return EncryptedText + */ + public static BigInteger encrypt(BigInteger plainText, BigInteger key) { + BigInteger[] roundKeys = keyExpansion(key); + + // Initial round + plainText = addRoundKey(plainText, roundKeys[0]); + + // Main rounds + for (int i = 1; i < 10; i++) { + plainText = subBytes(plainText); + plainText = shiftRows(plainText); + plainText = mixColumns(plainText); + plainText = addRoundKey(plainText, roundKeys[i]); + } + + // Final round + plainText = subBytes(plainText); + plainText = shiftRows(plainText); + plainText = addRoundKey(plainText, roundKeys[10]); + + return plainText; + } + + /** + * Decrypts the ciphertext with the key and returns the result + * + * @param cipherText The Encrypted text which we want to decrypt + * @return decryptedText + */ + public static BigInteger decrypt(BigInteger cipherText, BigInteger key) { + BigInteger[] roundKeys = keyExpansion(key); + + // Invert final round + cipherText = addRoundKey(cipherText, roundKeys[10]); + cipherText = shiftRowsDec(cipherText); + cipherText = subBytesDec(cipherText); + + // Invert main rounds + for (int i = 9; i > 0; i--) { + cipherText = addRoundKey(cipherText, roundKeys[i]); + cipherText = mixColumnsDec(cipherText); + cipherText = shiftRowsDec(cipherText); + cipherText = subBytesDec(cipherText); + } + + // Invert initial round + cipherText = addRoundKey(cipherText, roundKeys[0]); + + return cipherText; + } + + public static void main(String[] args) { + try (Scanner input = new Scanner(System.in)) { + System.out.println("Enter (e) letter for encrypt or (d) letter for decrypt :"); + char choice = input.nextLine().charAt(0); + String in; + switch (choice) { + case 'E', 'e' -> { + System.out.println( + "Choose a plaintext block (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger plaintext = new BigInteger(in, 16); + System.out.println( + "Choose a Key (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger encryptionKey = new BigInteger(in, 16); + System.out.println( + "The encrypted message is: \n" + + encrypt(plaintext, encryptionKey).toString(16) + ); + } + case 'D', 'd' -> { + System.out.println( + "Enter your ciphertext block (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger ciphertext = new BigInteger(in, 16); + System.out.println( + "Choose a Key (128-Bit Integer in base 16):" + ); + in = input.nextLine(); + BigInteger decryptionKey = new BigInteger(in, 16); + System.out.println( + "The deciphered message is:\n" + + decrypt(ciphertext, decryptionKey).toString(16) + ); + } + default -> System.out.println("** End **"); + } + } + } +} From 5b1810ce8b3e08e67452ce8f32f8b94f8749a2ab Mon Sep 17 00:00:00 2001 From: ngli Date: Sat, 21 Mar 2026 21:30:54 +0530 Subject: [PATCH 3/3] added duplicate code1 --- .../java/com/thealgorithms/ciphers/AES.java | 5562 ----------------- 1 file changed, 5562 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/AES.java b/src/main/java/com/thealgorithms/ciphers/AES.java index f8cad0b16070..df51eba55310 100644 --- a/src/main/java/com/thealgorithms/ciphers/AES.java +++ b/src/main/java/com/thealgorithms/ciphers/AES.java @@ -2779,5565 +2779,3 @@ public static void main(String[] args) { } } } -package com.thealgorithms.ciphers; - -import java.math.BigInteger; -import java.util.Scanner; - -/** - * This class is build to demonstrate the application of the AES-algorithm on a - * single 128-Bit block of data. - */ -public final class AES { - private AES() { - } - - /** - * Precalculated values for x to the power of 2 in Rijndaels galois field. - * Used as 'RCON' during the key expansion. - */ - private static final int[] RCON = { - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - }; - - /** - * Rijndael S-box Substitution table used for encryption in the subBytes - * step, as well as the key expansion. - */ - private static final int[] SBOX = { - 0x63, - 0x7C, - 0x77, - 0x7B, - 0xF2, - 0x6B, - 0x6F, - 0xC5, - 0x30, - 0x01, - 0x67, - 0x2B, - 0xFE, - 0xD7, - 0xAB, - 0x76, - 0xCA, - 0x82, - 0xC9, - 0x7D, - 0xFA, - 0x59, - 0x47, - 0xF0, - 0xAD, - 0xD4, - 0xA2, - 0xAF, - 0x9C, - 0xA4, - 0x72, - 0xC0, - 0xB7, - 0xFD, - 0x93, - 0x26, - 0x36, - 0x3F, - 0xF7, - 0xCC, - 0x34, - 0xA5, - 0xE5, - 0xF1, - 0x71, - 0xD8, - 0x31, - 0x15, - 0x04, - 0xC7, - 0x23, - 0xC3, - 0x18, - 0x96, - 0x05, - 0x9A, - 0x07, - 0x12, - 0x80, - 0xE2, - 0xEB, - 0x27, - 0xB2, - 0x75, - 0x09, - 0x83, - 0x2C, - 0x1A, - 0x1B, - 0x6E, - 0x5A, - 0xA0, - 0x52, - 0x3B, - 0xD6, - 0xB3, - 0x29, - 0xE3, - 0x2F, - 0x84, - 0x53, - 0xD1, - 0x00, - 0xED, - 0x20, - 0xFC, - 0xB1, - 0x5B, - 0x6A, - 0xCB, - 0xBE, - 0x39, - 0x4A, - 0x4C, - 0x58, - 0xCF, - 0xD0, - 0xEF, - 0xAA, - 0xFB, - 0x43, - 0x4D, - 0x33, - 0x85, - 0x45, - 0xF9, - 0x02, - 0x7F, - 0x50, - 0x3C, - 0x9F, - 0xA8, - 0x51, - 0xA3, - 0x40, - 0x8F, - 0x92, - 0x9D, - 0x38, - 0xF5, - 0xBC, - 0xB6, - 0xDA, - 0x21, - 0x10, - 0xFF, - 0xF3, - 0xD2, - 0xCD, - 0x0C, - 0x13, - 0xEC, - 0x5F, - 0x97, - 0x44, - 0x17, - 0xC4, - 0xA7, - 0x7E, - 0x3D, - 0x64, - 0x5D, - 0x19, - 0x73, - 0x60, - 0x81, - 0x4F, - 0xDC, - 0x22, - 0x2A, - 0x90, - 0x88, - 0x46, - 0xEE, - 0xB8, - 0x14, - 0xDE, - 0x5E, - 0x0B, - 0xDB, - 0xE0, - 0x32, - 0x3A, - 0x0A, - 0x49, - 0x06, - 0x24, - 0x5C, - 0xC2, - 0xD3, - 0xAC, - 0x62, - 0x91, - 0x95, - 0xE4, - 0x79, - 0xE7, - 0xC8, - 0x37, - 0x6D, - 0x8D, - 0xD5, - 0x4E, - 0xA9, - 0x6C, - 0x56, - 0xF4, - 0xEA, - 0x65, - 0x7A, - 0xAE, - 0x08, - 0xBA, - 0x78, - 0x25, - 0x2E, - 0x1C, - 0xA6, - 0xB4, - 0xC6, - 0xE8, - 0xDD, - 0x74, - 0x1F, - 0x4B, - 0xBD, - 0x8B, - 0x8A, - 0x70, - 0x3E, - 0xB5, - 0x66, - 0x48, - 0x03, - 0xF6, - 0x0E, - 0x61, - 0x35, - 0x57, - 0xB9, - 0x86, - 0xC1, - 0x1D, - 0x9E, - 0xE1, - 0xF8, - 0x98, - 0x11, - 0x69, - 0xD9, - 0x8E, - 0x94, - 0x9B, - 0x1E, - 0x87, - 0xE9, - 0xCE, - 0x55, - 0x28, - 0xDF, - 0x8C, - 0xA1, - 0x89, - 0x0D, - 0xBF, - 0xE6, - 0x42, - 0x68, - 0x41, - 0x99, - 0x2D, - 0x0F, - 0xB0, - 0x54, - 0xBB, - 0x16, - }; - - /** - * Inverse Rijndael S-box Substitution table used for decryption in the - * subBytesDec step. - */ - private static final int[] INVERSE_SBOX = { - 0x52, - 0x09, - 0x6A, - 0xD5, - 0x30, - 0x36, - 0xA5, - 0x38, - 0xBF, - 0x40, - 0xA3, - 0x9E, - 0x81, - 0xF3, - 0xD7, - 0xFB, - 0x7C, - 0xE3, - 0x39, - 0x82, - 0x9B, - 0x2F, - 0xFF, - 0x87, - 0x34, - 0x8E, - 0x43, - 0x44, - 0xC4, - 0xDE, - 0xE9, - 0xCB, - 0x54, - 0x7B, - 0x94, - 0x32, - 0xA6, - 0xC2, - 0x23, - 0x3D, - 0xEE, - 0x4C, - 0x95, - 0x0B, - 0x42, - 0xFA, - 0xC3, - 0x4E, - 0x08, - 0x2E, - 0xA1, - 0x66, - 0x28, - 0xD9, - 0x24, - 0xB2, - 0x76, - 0x5B, - 0xA2, - 0x49, - 0x6D, - 0x8B, - 0xD1, - 0x25, - 0x72, - 0xF8, - 0xF6, - 0x64, - 0x86, - 0x68, - 0x98, - 0x16, - 0xD4, - 0xA4, - 0x5C, - 0xCC, - 0x5D, - 0x65, - 0xB6, - 0x92, - 0x6C, - 0x70, - 0x48, - 0x50, - 0xFD, - 0xED, - 0xB9, - 0xDA, - 0x5E, - 0x15, - 0x46, - 0x57, - 0xA7, - 0x8D, - 0x9D, - 0x84, - 0x90, - 0xD8, - 0xAB, - 0x00, - 0x8C, - 0xBC, - 0xD3, - 0x0A, - 0xF7, - 0xE4, - 0x58, - 0x05, - 0xB8, - 0xB3, - 0x45, - 0x06, - 0xD0, - 0x2C, - 0x1E, - 0x8F, - 0xCA, - 0x3F, - 0x0F, - 0x02, - 0xC1, - 0xAF, - 0xBD, - 0x03, - 0x01, - 0x13, - 0x8A, - 0x6B, - 0x3A, - 0x91, - 0x11, - 0x41, - 0x4F, - 0x67, - 0xDC, - 0xEA, - 0x97, - 0xF2, - 0xCF, - 0xCE, - 0xF0, - 0xB4, - 0xE6, - 0x73, - 0x96, - 0xAC, - 0x74, - 0x22, - 0xE7, - 0xAD, - 0x35, - 0x85, - 0xE2, - 0xF9, - 0x37, - 0xE8, - 0x1C, - 0x75, - 0xDF, - 0x6E, - 0x47, - 0xF1, - 0x1A, - 0x71, - 0x1D, - 0x29, - 0xC5, - 0x89, - 0x6F, - 0xB7, - 0x62, - 0x0E, - 0xAA, - 0x18, - 0xBE, - 0x1B, - 0xFC, - 0x56, - 0x3E, - 0x4B, - 0xC6, - 0xD2, - 0x79, - 0x20, - 0x9A, - 0xDB, - 0xC0, - 0xFE, - 0x78, - 0xCD, - 0x5A, - 0xF4, - 0x1F, - 0xDD, - 0xA8, - 0x33, - 0x88, - 0x07, - 0xC7, - 0x31, - 0xB1, - 0x12, - 0x10, - 0x59, - 0x27, - 0x80, - 0xEC, - 0x5F, - 0x60, - 0x51, - 0x7F, - 0xA9, - 0x19, - 0xB5, - 0x4A, - 0x0D, - 0x2D, - 0xE5, - 0x7A, - 0x9F, - 0x93, - 0xC9, - 0x9C, - 0xEF, - 0xA0, - 0xE0, - 0x3B, - 0x4D, - 0xAE, - 0x2A, - 0xF5, - 0xB0, - 0xC8, - 0xEB, - 0xBB, - 0x3C, - 0x83, - 0x53, - 0x99, - 0x61, - 0x17, - 0x2B, - 0x04, - 0x7E, - 0xBA, - 0x77, - 0xD6, - 0x26, - 0xE1, - 0x69, - 0x14, - 0x63, - 0x55, - 0x21, - 0x0C, - 0x7D, - }; - - /** - * Precalculated lookup table for galois field multiplication by 2 used in - * the MixColums step during encryption. - */ - private static final int[] MULT2 = { - 0x00, - 0x02, - 0x04, - 0x06, - 0x08, - 0x0a, - 0x0c, - 0x0e, - 0x10, - 0x12, - 0x14, - 0x16, - 0x18, - 0x1a, - 0x1c, - 0x1e, - 0x20, - 0x22, - 0x24, - 0x26, - 0x28, - 0x2a, - 0x2c, - 0x2e, - 0x30, - 0x32, - 0x34, - 0x36, - 0x38, - 0x3a, - 0x3c, - 0x3e, - 0x40, - 0x42, - 0x44, - 0x46, - 0x48, - 0x4a, - 0x4c, - 0x4e, - 0x50, - 0x52, - 0x54, - 0x56, - 0x58, - 0x5a, - 0x5c, - 0x5e, - 0x60, - 0x62, - 0x64, - 0x66, - 0x68, - 0x6a, - 0x6c, - 0x6e, - 0x70, - 0x72, - 0x74, - 0x76, - 0x78, - 0x7a, - 0x7c, - 0x7e, - 0x80, - 0x82, - 0x84, - 0x86, - 0x88, - 0x8a, - 0x8c, - 0x8e, - 0x90, - 0x92, - 0x94, - 0x96, - 0x98, - 0x9a, - 0x9c, - 0x9e, - 0xa0, - 0xa2, - 0xa4, - 0xa6, - 0xa8, - 0xaa, - 0xac, - 0xae, - 0xb0, - 0xb2, - 0xb4, - 0xb6, - 0xb8, - 0xba, - 0xbc, - 0xbe, - 0xc0, - 0xc2, - 0xc4, - 0xc6, - 0xc8, - 0xca, - 0xcc, - 0xce, - 0xd0, - 0xd2, - 0xd4, - 0xd6, - 0xd8, - 0xda, - 0xdc, - 0xde, - 0xe0, - 0xe2, - 0xe4, - 0xe6, - 0xe8, - 0xea, - 0xec, - 0xee, - 0xf0, - 0xf2, - 0xf4, - 0xf6, - 0xf8, - 0xfa, - 0xfc, - 0xfe, - 0x1b, - 0x19, - 0x1f, - 0x1d, - 0x13, - 0x11, - 0x17, - 0x15, - 0x0b, - 0x09, - 0x0f, - 0x0d, - 0x03, - 0x01, - 0x07, - 0x05, - 0x3b, - 0x39, - 0x3f, - 0x3d, - 0x33, - 0x31, - 0x37, - 0x35, - 0x2b, - 0x29, - 0x2f, - 0x2d, - 0x23, - 0x21, - 0x27, - 0x25, - 0x5b, - 0x59, - 0x5f, - 0x5d, - 0x53, - 0x51, - 0x57, - 0x55, - 0x4b, - 0x49, - 0x4f, - 0x4d, - 0x43, - 0x41, - 0x47, - 0x45, - 0x7b, - 0x79, - 0x7f, - 0x7d, - 0x73, - 0x71, - 0x77, - 0x75, - 0x6b, - 0x69, - 0x6f, - 0x6d, - 0x63, - 0x61, - 0x67, - 0x65, - 0x9b, - 0x99, - 0x9f, - 0x9d, - 0x93, - 0x91, - 0x97, - 0x95, - 0x8b, - 0x89, - 0x8f, - 0x8d, - 0x83, - 0x81, - 0x87, - 0x85, - 0xbb, - 0xb9, - 0xbf, - 0xbd, - 0xb3, - 0xb1, - 0xb7, - 0xb5, - 0xab, - 0xa9, - 0xaf, - 0xad, - 0xa3, - 0xa1, - 0xa7, - 0xa5, - 0xdb, - 0xd9, - 0xdf, - 0xdd, - 0xd3, - 0xd1, - 0xd7, - 0xd5, - 0xcb, - 0xc9, - 0xcf, - 0xcd, - 0xc3, - 0xc1, - 0xc7, - 0xc5, - 0xfb, - 0xf9, - 0xff, - 0xfd, - 0xf3, - 0xf1, - 0xf7, - 0xf5, - 0xeb, - 0xe9, - 0xef, - 0xed, - 0xe3, - 0xe1, - 0xe7, - 0xe5, - }; - - /** - * Precalculated lookup table for galois field multiplication by 3 used in - * the MixColums step during encryption. - */ - private static final int[] MULT3 = { - 0x00, - 0x03, - 0x06, - 0x05, - 0x0c, - 0x0f, - 0x0a, - 0x09, - 0x18, - 0x1b, - 0x1e, - 0x1d, - 0x14, - 0x17, - 0x12, - 0x11, - 0x30, - 0x33, - 0x36, - 0x35, - 0x3c, - 0x3f, - 0x3a, - 0x39, - 0x28, - 0x2b, - 0x2e, - 0x2d, - 0x24, - 0x27, - 0x22, - 0x21, - 0x60, - 0x63, - 0x66, - 0x65, - 0x6c, - 0x6f, - 0x6a, - 0x69, - 0x78, - 0x7b, - 0x7e, - 0x7d, - 0x74, - 0x77, - 0x72, - 0x71, - 0x50, - 0x53, - 0x56, - 0x55, - 0x5c, - 0x5f, - 0x5a, - 0x59, - 0x48, - 0x4b, - 0x4e, - 0x4d, - 0x44, - 0x47, - 0x42, - 0x41, - 0xc0, - 0xc3, - 0xc6, - 0xc5, - 0xcc, - 0xcf, - 0xca, - 0xc9, - 0xd8, - 0xdb, - 0xde, - 0xdd, - 0xd4, - 0xd7, - 0xd2, - 0xd1, - 0xf0, - 0xf3, - 0xf6, - 0xf5, - 0xfc, - 0xff, - 0xfa, - 0xf9, - 0xe8, - 0xeb, - 0xee, - 0xed, - 0xe4, - 0xe7, - 0xe2, - 0xe1, - 0xa0, - 0xa3, - 0xa6, - 0xa5, - 0xac, - 0xaf, - 0xaa, - 0xa9, - 0xb8, - 0xbb, - 0xbe, - 0xbd, - 0xb4, - 0xb7, - 0xb2, - 0xb1, - 0x90, - 0x93, - 0x96, - 0x95, - 0x9c, - 0x9f, - 0x9a, - 0x99, - 0x88, - 0x8b, - 0x8e, - 0x8d, - 0x84, - 0x87, - 0x82, - 0x81, - 0x9b, - 0x98, - 0x9d, - 0x9e, - 0x97, - 0x94, - 0x91, - 0x92, - 0x83, - 0x80, - 0x85, - 0x86, - 0x8f, - 0x8c, - 0x89, - 0x8a, - 0xab, - 0xa8, - 0xad, - 0xae, - 0xa7, - 0xa4, - 0xa1, - 0xa2, - 0xb3, - 0xb0, - 0xb5, - 0xb6, - 0xbf, - 0xbc, - 0xb9, - 0xba, - 0xfb, - 0xf8, - 0xfd, - 0xfe, - 0xf7, - 0xf4, - 0xf1, - 0xf2, - 0xe3, - 0xe0, - 0xe5, - 0xe6, - 0xef, - 0xec, - 0xe9, - 0xea, - 0xcb, - 0xc8, - 0xcd, - 0xce, - 0xc7, - 0xc4, - 0xc1, - 0xc2, - 0xd3, - 0xd0, - 0xd5, - 0xd6, - 0xdf, - 0xdc, - 0xd9, - 0xda, - 0x5b, - 0x58, - 0x5d, - 0x5e, - 0x57, - 0x54, - 0x51, - 0x52, - 0x43, - 0x40, - 0x45, - 0x46, - 0x4f, - 0x4c, - 0x49, - 0x4a, - 0x6b, - 0x68, - 0x6d, - 0x6e, - 0x67, - 0x64, - 0x61, - 0x62, - 0x73, - 0x70, - 0x75, - 0x76, - 0x7f, - 0x7c, - 0x79, - 0x7a, - 0x3b, - 0x38, - 0x3d, - 0x3e, - 0x37, - 0x34, - 0x31, - 0x32, - 0x23, - 0x20, - 0x25, - 0x26, - 0x2f, - 0x2c, - 0x29, - 0x2a, - 0x0b, - 0x08, - 0x0d, - 0x0e, - 0x07, - 0x04, - 0x01, - 0x02, - 0x13, - 0x10, - 0x15, - 0x16, - 0x1f, - 0x1c, - 0x19, - 0x1a, - }; - - /** - * Precalculated lookup table for galois field multiplication by 9 used in - * the MixColums step during decryption. - */ - private static final int[] MULT9 = { - 0x00, - 0x09, - 0x12, - 0x1b, - 0x24, - 0x2d, - 0x36, - 0x3f, - 0x48, - 0x41, - 0x5a, - 0x53, - 0x6c, - 0x65, - 0x7e, - 0x77, - 0x90, - 0x99, - 0x82, - 0x8b, - 0xb4, - 0xbd, - 0xa6, - 0xaf, - 0xd8, - 0xd1, - 0xca, - 0xc3, - 0xfc, - 0xf5, - 0xee, - 0xe7, - 0x3b, - 0x32, - 0x29, - 0x20, - 0x1f, - 0x16, - 0x0d, - 0x04, - 0x73, - 0x7a, - 0x61, - 0x68, - 0x57, - 0x5e, - 0x45, - 0x4c, - 0xab, - 0xa2, - 0xb9, - 0xb0, - 0x8f, - 0x86, - 0x9d, - 0x94, - 0xe3, - 0xea, - 0xf1, - 0xf8, - 0xc7, - 0xce, - 0xd5, - 0xdc, - 0x76, - 0x7f, - 0x64, - 0x6d, - 0x52, - 0x5b, - 0x40, - 0x49, - 0x3e, - 0x37, - 0x2c, - 0x25, - 0x1a, - 0x13, - 0x08, - 0x01, - 0xe6, - 0xef, - 0xf4, - 0xfd, - 0xc2, - 0xcb, - 0xd0, - 0xd9, - 0xae, - 0xa7, - 0xbc, - 0xb5, - 0x8a, - 0x83, - 0x98, - 0x91, - 0x4d, - 0x44, - 0x5f, - 0x56, - 0x69, - 0x60, - 0x7b, - 0x72, - 0x05, - 0x0c, - 0x17, - 0x1e, - 0x21, - 0x28, - 0x33, - 0x3a, - 0xdd, - 0xd4, - 0xcf, - 0xc6, - 0xf9, - 0xf0, - 0xeb, - 0xe2, - 0x95, - 0x9c, - 0x87, - 0x8e, - 0xb1, - 0xb8, - 0xa3, - 0xaa, - 0xec, - 0xe5, - 0xfe, - 0xf7, - 0xc8, - 0xc1, - 0xda, - 0xd3, - 0xa4, - 0xad, - 0xb6, - 0xbf, - 0x80, - 0x89, - 0x92, - 0x9b, - 0x7c, - 0x75, - 0x6e, - 0x67, - 0x58, - 0x51, - 0x4a, - 0x43, - 0x34, - 0x3d, - 0x26, - 0x2f, - 0x10, - 0x19, - 0x02, - 0x0b, - 0xd7, - 0xde, - 0xc5, - 0xcc, - 0xf3, - 0xfa, - 0xe1, - 0xe8, - 0x9f, - 0x96, - 0x8d, - 0x84, - 0xbb, - 0xb2, - 0xa9, - 0xa0, - 0x47, - 0x4e, - 0x55, - 0x5c, - 0x63, - 0x6a, - 0x71, - 0x78, - 0x0f, - 0x06, - 0x1d, - 0x14, - 0x2b, - 0x22, - 0x39, - 0x30, - 0x9a, - 0x93, - 0x88, - 0x81, - 0xbe, - 0xb7, - 0xac, - 0xa5, - 0xd2, - 0xdb, - 0xc0, - 0xc9, - 0xf6, - 0xff, - 0xe4, - 0xed, - 0x0a, - 0x03, - 0x18, - 0x11, - 0x2e, - 0x27, - 0x3c, - 0x35, - 0x42, - 0x4b, - 0x50, - 0x59, - 0x66, - 0x6f, - 0x74, - 0x7d, - 0xa1, - 0xa8, - 0xb3, - 0xba, - 0x85, - 0x8c, - 0x97, - 0x9e, - 0xe9, - 0xe0, - 0xfb, - 0xf2, - 0xcd, - 0xc4, - 0xdf, - 0xd6, - 0x31, - 0x38, - 0x23, - 0x2a, - 0x15, - 0x1c, - 0x07, - 0x0e, - 0x79, - 0x70, - 0x6b, - 0x62, - 0x5d, - 0x54, - 0x4f, - 0x46, - }; - - /** - * Precalculated lookup table for galois field multiplication by 11 used in - * the MixColums step during decryption. - */ - private static final int[] MULT11 = { - 0x00, - 0x0b, - 0x16, - 0x1d, - 0x2c, - 0x27, - 0x3a, - 0x31, - 0x58, - 0x53, - 0x4e, - 0x45, - 0x74, - 0x7f, - 0x62, - 0x69, - 0xb0, - 0xbb, - 0xa6, - 0xad, - 0x9c, - 0x97, - 0x8a, - 0x81, - 0xe8, - 0xe3, - 0xfe, - 0xf5, - 0xc4, - 0xcf, - 0xd2, - 0xd9, - 0x7b, - 0x70, - 0x6d, - 0x66, - 0x57, - 0x5c, - 0x41, - 0x4a, - 0x23, - 0x28, - 0x35, - 0x3e, - 0x0f, - 0x04, - 0x19, - 0x12, - 0xcb, - 0xc0, - 0xdd, - 0xd6, - 0xe7, - 0xec, - 0xf1, - 0xfa, - 0x93, - 0x98, - 0x85, - 0x8e, - 0xbf, - 0xb4, - 0xa9, - 0xa2, - 0xf6, - 0xfd, - 0xe0, - 0xeb, - 0xda, - 0xd1, - 0xcc, - 0xc7, - 0xae, - 0xa5, - 0xb8, - 0xb3, - 0x82, - 0x89, - 0x94, - 0x9f, - 0x46, - 0x4d, - 0x50, - 0x5b, - 0x6a, - 0x61, - 0x7c, - 0x77, - 0x1e, - 0x15, - 0x08, - 0x03, - 0x32, - 0x39, - 0x24, - 0x2f, - 0x8d, - 0x86, - 0x9b, - 0x90, - 0xa1, - 0xaa, - 0xb7, - 0xbc, - 0xd5, - 0xde, - 0xc3, - 0xc8, - 0xf9, - 0xf2, - 0xef, - 0xe4, - 0x3d, - 0x36, - 0x2b, - 0x20, - 0x11, - 0x1a, - 0x07, - 0x0c, - 0x65, - 0x6e, - 0x73, - 0x78, - 0x49, - 0x42, - 0x5f, - 0x54, - 0xf7, - 0xfc, - 0xe1, - 0xea, - 0xdb, - 0xd0, - 0xcd, - 0xc6, - 0xaf, - 0xa4, - 0xb9, - 0xb2, - 0x83, - 0x88, - 0x95, - 0x9e, - 0x47, - 0x4c, - 0x51, - 0x5a, - 0x6b, - 0x60, - 0x7d, - 0x76, - 0x1f, - 0x14, - 0x09, - 0x02, - 0x33, - 0x38, - 0x25, - 0x2e, - 0x8c, - 0x87, - 0x9a, - 0x91, - 0xa0, - 0xab, - 0xb6, - 0xbd, - 0xd4, - 0xdf, - 0xc2, - 0xc9, - 0xf8, - 0xf3, - 0xee, - 0xe5, - 0x3c, - 0x37, - 0x2a, - 0x21, - 0x10, - 0x1b, - 0x06, - 0x0d, - 0x64, - 0x6f, - 0x72, - 0x79, - 0x48, - 0x43, - 0x5e, - 0x55, - 0x01, - 0x0a, - 0x17, - 0x1c, - 0x2d, - 0x26, - 0x3b, - 0x30, - 0x59, - 0x52, - 0x4f, - 0x44, - 0x75, - 0x7e, - 0x63, - 0x68, - 0xb1, - 0xba, - 0xa7, - 0xac, - 0x9d, - 0x96, - 0x8b, - 0x80, - 0xe9, - 0xe2, - 0xff, - 0xf4, - 0xc5, - 0xce, - 0xd3, - 0xd8, - 0x7a, - 0x71, - 0x6c, - 0x67, - 0x56, - 0x5d, - 0x40, - 0x4b, - 0x22, - 0x29, - 0x34, - 0x3f, - 0x0e, - 0x05, - 0x18, - 0x13, - 0xca, - 0xc1, - 0xdc, - 0xd7, - 0xe6, - 0xed, - 0xf0, - 0xfb, - 0x92, - 0x99, - 0x84, - 0x8f, - 0xbe, - 0xb5, - 0xa8, - 0xa3, - }; - - /** - * Precalculated lookup table for galois field multiplication by 13 used in - * the MixColums step during decryption. - */ - private static final int[] MULT13 = { - 0x00, - 0x0d, - 0x1a, - 0x17, - 0x34, - 0x39, - 0x2e, - 0x23, - 0x68, - 0x65, - 0x72, - 0x7f, - 0x5c, - 0x51, - 0x46, - 0x4b, - 0xd0, - 0xdd, - 0xca, - 0xc7, - 0xe4, - 0xe9, - 0xfe, - 0xf3, - 0xb8, - 0xb5, - 0xa2, - 0xaf, - 0x8c, - 0x81, - 0x96, - 0x9b, - 0xbb, - 0xb6, - 0xa1, - 0xac, - 0x8f, - 0x82, - 0x95, - 0x98, - 0xd3, - 0xde, - 0xc9, - 0xc4, - 0xe7, - 0xea, - 0xfd, - 0xf0, - 0x6b, - 0x66, - 0x71, - 0x7c, - 0x5f, - 0x52, - 0x45, - 0x48, - 0x03, - 0x0e, - 0x19, - 0x14, - 0x37, - 0x3a, - 0x2d, - 0x20, - 0x6d, - 0x60, - 0x77, - 0x7a, - 0x59, - 0x54, - 0x43, - 0x4e, - 0x05, - 0x08, - 0x1f, - 0x12, - 0x31, - 0x3c, - 0x2b, - 0x26, - 0xbd, - 0xb0, - 0xa7, - 0xaa, - 0x89, - 0x84, - 0x93, - 0x9e, - 0xd5, - 0xd8, - 0xcf, - 0xc2, - 0xe1, - 0xec, - 0xfb, - 0xf6, - 0xd6, - 0xdb, - 0xcc, - 0xc1, - 0xe2, - 0xef, - 0xf8, - 0xf5, - 0xbe, - 0xb3, - 0xa4, - 0xa9, - 0x8a, - 0x87, - 0x90, - 0x9d, - 0x06, - 0x0b, - 0x1c, - 0x11, - 0x32, - 0x3f, - 0x28, - 0x25, - 0x6e, - 0x63, - 0x74, - 0x79, - 0x5a, - 0x57, - 0x40, - 0x4d, - 0xda, - 0xd7, - 0xc0, - 0xcd, - 0xee, - 0xe3, - 0xf4, - 0xf9, - 0xb2, - 0xbf, - 0xa8, - 0xa5, - 0x86, - 0x8b, - 0x9c, - 0x91, - 0x0a, - 0x07, - 0x10, - 0x1d, - 0x3e, - 0x33, - 0x24, - 0x29, - 0x62, - 0x6f, - 0x78, - 0x75, - 0x56, - 0x5b, - 0x4c, - 0x41, - 0x61, - 0x6c, - 0x7b, - 0x76, - 0x55, - 0x58, - 0x4f, - 0x42, - 0x09, - 0x04, - 0x13, - 0x1e, - 0x3d, - 0x30, - 0x27, - 0x2a, - 0xb1, - 0xbc, - 0xab, - 0xa6, - 0x85, - 0x88, - 0x9f, - 0x92, - 0xd9, - 0xd4, - 0xc3, - 0xce, - 0xed, - 0xe0, - 0xf7, - 0xfa, - 0xb7, - 0xba, - 0xad, - 0xa0, - 0x83, - 0x8e, - 0x99, - 0x94, - 0xdf, - 0xd2, - 0xc5, - 0xc8, - 0xeb, - 0xe6, - 0xf1, - 0xfc, - 0x67, - 0x6a, - 0x7d, - 0x70, - 0x53, - 0x5e, - 0x49, - 0x44, - 0x0f, - 0x02, - 0x15, - 0x18, - 0x3b, - 0x36, - 0x21, - 0x2c, - 0x0c, - 0x01, - 0x16, - 0x1b, - 0x38, - 0x35, - 0x22, - 0x2f, - 0x64, - 0x69, - 0x7e, - 0x73, - 0x50, - 0x5d, - 0x4a, - 0x47, - 0xdc, - 0xd1, - 0xc6, - 0xcb, - 0xe8, - 0xe5, - 0xf2, - 0xff, - 0xb4, - 0xb9, - 0xae, - 0xa3, - 0x80, - 0x8d, - 0x9a, - 0x97, - }; - - /** - * Precalculated lookup table for galois field multiplication by 14 used in - * the MixColums step during decryption. - */ - private static final int[] MULT14 = { - 0x00, - 0x0e, - 0x1c, - 0x12, - 0x38, - 0x36, - 0x24, - 0x2a, - 0x70, - 0x7e, - 0x6c, - 0x62, - 0x48, - 0x46, - 0x54, - 0x5a, - 0xe0, - 0xee, - 0xfc, - 0xf2, - 0xd8, - 0xd6, - 0xc4, - 0xca, - 0x90, - 0x9e, - 0x8c, - 0x82, - 0xa8, - 0xa6, - 0xb4, - 0xba, - 0xdb, - 0xd5, - 0xc7, - 0xc9, - 0xe3, - 0xed, - 0xff, - 0xf1, - 0xab, - 0xa5, - 0xb7, - 0xb9, - 0x93, - 0x9d, - 0x8f, - 0x81, - 0x3b, - 0x35, - 0x27, - 0x29, - 0x03, - 0x0d, - 0x1f, - 0x11, - 0x4b, - 0x45, - 0x57, - 0x59, - 0x73, - 0x7d, - 0x6f, - 0x61, - 0xad, - 0xa3, - 0xb1, - 0xbf, - 0x95, - 0x9b, - 0x89, - 0x87, - 0xdd, - 0xd3, - 0xc1, - 0xcf, - 0xe5, - 0xeb, - 0xf9, - 0xf7, - 0x4d, - 0x43, - 0x51, - 0x5f, - 0x75, - 0x7b, - 0x69, - 0x67, - 0x3d, - 0x33, - 0x21, - 0x2f, - 0x05, - 0x0b, - 0x19, - 0x17, - 0x76, - 0x78, - 0x6a, - 0x64, - 0x4e, - 0x40, - 0x52, - 0x5c, - 0x06, - 0x08, - 0x1a, - 0x14, - 0x3e, - 0x30, - 0x22, - 0x2c, - 0x96, - 0x98, - 0x8a, - 0x84, - 0xae, - 0xa0, - 0xb2, - 0xbc, - 0xe6, - 0xe8, - 0xfa, - 0xf4, - 0xde, - 0xd0, - 0xc2, - 0xcc, - 0x41, - 0x4f, - 0x5d, - 0x53, - 0x79, - 0x77, - 0x65, - 0x6b, - 0x31, - 0x3f, - 0x2d, - 0x23, - 0x09, - 0x07, - 0x15, - 0x1b, - 0xa1, - 0xaf, - 0xbd, - 0xb3, - 0x99, - 0x97, - 0x85, - 0x8b, - 0xd1, - 0xdf, - 0xcd, - 0xc3, - 0xe9, - 0xe7, - 0xf5, - 0xfb, - 0x9a, - 0x94, - 0x86, - 0x88, - 0xa2, - 0xac, - 0xbe, - 0xb0, - 0xea, - 0xe4, - 0xf6, - 0xf8, - 0xd2, - 0xdc, - 0xce, - 0xc0, - 0x7a, - 0x74, - 0x66, - 0x68, - 0x42, - 0x4c, - 0x5e, - 0x50, - 0x0a, - 0x04, - 0x16, - 0x18, - 0x32, - 0x3c, - 0x2e, - 0x20, - 0xec, - 0xe2, - 0xf0, - 0xfe, - 0xd4, - 0xda, - 0xc8, - 0xc6, - 0x9c, - 0x92, - 0x80, - 0x8e, - 0xa4, - 0xaa, - 0xb8, - 0xb6, - 0x0c, - 0x02, - 0x10, - 0x1e, - 0x34, - 0x3a, - 0x28, - 0x26, - 0x7c, - 0x72, - 0x60, - 0x6e, - 0x44, - 0x4a, - 0x58, - 0x56, - 0x37, - 0x39, - 0x2b, - 0x25, - 0x0f, - 0x01, - 0x13, - 0x1d, - 0x47, - 0x49, - 0x5b, - 0x55, - 0x7f, - 0x71, - 0x63, - 0x6d, - 0xd7, - 0xd9, - 0xcb, - 0xc5, - 0xef, - 0xe1, - 0xf3, - 0xfd, - 0xa7, - 0xa9, - 0xbb, - 0xb5, - 0x9f, - 0x91, - 0x83, - 0x8d, - }; - - /** - * Subroutine of the Rijndael key expansion. - */ - public static BigInteger scheduleCore(BigInteger t, int rconCounter) { - StringBuilder rBytes = new StringBuilder(t.toString(16)); - - // Add zero padding - while (rBytes.length() < 8) { - rBytes.insert(0, "0"); - } - - // rotate the first 16 bits to the back - String rotatingBytes = rBytes.substring(0, 2); - String fixedBytes = rBytes.substring(2); - - rBytes = new StringBuilder(fixedBytes + rotatingBytes); - - // apply S-Box to all 8-Bit Substrings - for (int i = 0; i < 4; i++) { - StringBuilder currentByteBits = new StringBuilder(rBytes.substring(i * 2, (i + 1) * 2)); - - int currentByte = Integer.parseInt(currentByteBits.toString(), 16); - currentByte = SBOX[currentByte]; - - // add the current RCON value to the first byte - if (i == 0) { - currentByte = currentByte ^ RCON[rconCounter]; - } - - currentByteBits = new StringBuilder(Integer.toHexString(currentByte)); - - // Add zero padding - while (currentByteBits.length() < 2) { - currentByteBits.insert(0, '0'); - } - - // replace bytes in original string - rBytes = new StringBuilder(rBytes.substring(0, i * 2) + currentByteBits + rBytes.substring((i + 1) * 2)); - } - - return new BigInteger(rBytes.toString(), 16); - } - - /** - * Returns an array of 10 + 1 round keys that are calculated by using - * Rijndael key schedule - * - * @return array of 10 + 1 round keys - */ - public static BigInteger[] keyExpansion(BigInteger initialKey) { - BigInteger[] roundKeys = { - initialKey, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - }; - - // initialize rcon iteration - int rconCounter = 1; - - for (int i = 1; i < 11; i++) { - // get the previous 32 bits the key - BigInteger t = roundKeys[i - 1].remainder(new BigInteger("100000000", 16)); - - // split previous key into 8-bit segments - BigInteger[] prevKey = { - roundKeys[i - 1].remainder(new BigInteger("100000000", 16)), - roundKeys[i - 1].remainder(new BigInteger("10000000000000000", 16)).divide(new BigInteger("100000000", 16)), - roundKeys[i - 1].remainder(new BigInteger("1000000000000000000000000", 16)).divide(new BigInteger("10000000000000000", 16)), - roundKeys[i - 1].divide(new BigInteger("1000000000000000000000000", 16)), - }; - - // run schedule core - t = scheduleCore(t, rconCounter); - rconCounter += 1; - - // Calculate partial round key - BigInteger t0 = t.xor(prevKey[3]); - BigInteger t1 = t0.xor(prevKey[2]); - BigInteger t2 = t1.xor(prevKey[1]); - BigInteger t3 = t2.xor(prevKey[0]); - - // Join round key segments - t2 = t2.multiply(new BigInteger("100000000", 16)); - t1 = t1.multiply(new BigInteger("10000000000000000", 16)); - t0 = t0.multiply(new BigInteger("1000000000000000000000000", 16)); - roundKeys[i] = t0.add(t1).add(t2).add(t3); - } - return roundKeys; - } - - /** - * representation of the input 128-bit block as an array of 8-bit integers. - * - * @param block of 128-bit integers - * @return array of 8-bit integers - */ - public static int[] splitBlockIntoCells(BigInteger block) { - int[] cells = new int[16]; - StringBuilder blockBits = new StringBuilder(block.toString(2)); - - // Append leading 0 for full "128-bit" string - while (blockBits.length() < 128) { - blockBits.insert(0, '0'); - } - - // split 128 to 8 bit cells - for (int i = 0; i < cells.length; i++) { - String cellBits = blockBits.substring(8 * i, 8 * (i + 1)); - cells[i] = Integer.parseInt(cellBits, 2); - } - - return cells; - } - - /** - * Returns the 128-bit BigInteger representation of the input of an array of - * 8-bit integers. - * - * @param cells that we need to merge - * @return block of merged cells - */ - public static BigInteger mergeCellsIntoBlock(int[] cells) { - StringBuilder blockBits = new StringBuilder(); - for (int i = 0; i < 16; i++) { - StringBuilder cellBits = new StringBuilder(Integer.toBinaryString(cells[i])); - - // Append leading 0 for full "8-bit" strings - while (cellBits.length() < 8) { - cellBits.insert(0, '0'); - } - - blockBits.append(cellBits); - } - - return new BigInteger(blockBits.toString(), 2); - } - - /** - * @return ciphertext XOR key - */ - public static BigInteger addRoundKey(BigInteger ciphertext, BigInteger key) { - return ciphertext.xor(key); - } - - /** - * substitutes 8-Bit long substrings of the input using the S-Box and - * returns the result. - * - * @return subtraction Output - */ - public static BigInteger subBytes(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - - for (int i = 0; i < 16; i++) { - cells[i] = SBOX[cells[i]]; - } - - return mergeCellsIntoBlock(cells); - } - - /** - * substitutes 8-Bit long substrings of the input using the inverse S-Box - * for decryption and returns the result. - * - * @return subtraction Output - */ - public static BigInteger subBytesDec(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - - for (int i = 0; i < 16; i++) { - cells[i] = INVERSE_SBOX[cells[i]]; - } - - return mergeCellsIntoBlock(cells); - } - - /** - * Cell permutation step. Shifts cells within the rows of the input and - * returns the result. - */ - public static BigInteger shiftRows(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] output = new int[16]; - - // do nothing in the first row - output[0] = cells[0]; - output[4] = cells[4]; - output[8] = cells[8]; - output[12] = cells[12]; - - // shift the second row backwards by one cell - output[1] = cells[5]; - output[5] = cells[9]; - output[9] = cells[13]; - output[13] = cells[1]; - - // shift the third row backwards by two cell - output[2] = cells[10]; - output[6] = cells[14]; - output[10] = cells[2]; - output[14] = cells[6]; - - // shift the forth row backwards by tree cell - output[3] = cells[15]; - output[7] = cells[3]; - output[11] = cells[7]; - output[15] = cells[11]; - - return mergeCellsIntoBlock(output); - } - - /** - * Cell permutation step for decryption . Shifts cells within the rows of - * the input and returns the result. - */ - public static BigInteger shiftRowsDec(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] output = new int[16]; - - // do nothing in the first row - output[0] = cells[0]; - output[4] = cells[4]; - output[8] = cells[8]; - output[12] = cells[12]; - - // shift the second row forwards by one cell - output[1] = cells[13]; - output[5] = cells[1]; - output[9] = cells[5]; - output[13] = cells[9]; - - // shift the third row forwards by two cell - output[2] = cells[10]; - output[6] = cells[14]; - output[10] = cells[2]; - output[14] = cells[6]; - - // shift the forth row forwards by tree cell - output[3] = cells[7]; - output[7] = cells[11]; - output[11] = cells[15]; - output[15] = cells[3]; - - return mergeCellsIntoBlock(output); - } - - /** - * Applies the Rijndael MixColumns to the input and returns the result. - */ - public static BigInteger mixColumns(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] outputCells = new int[16]; - - for (int i = 0; i < 4; i++) { - int[] row = { - cells[i * 4], - cells[i * 4 + 1], - cells[i * 4 + 2], - cells[i * 4 + 3], - }; - - outputCells[i * 4] = MULT2[row[0]] ^ MULT3[row[1]] ^ row[2] ^ row[3]; - outputCells[i * 4 + 1] = row[0] ^ MULT2[row[1]] ^ MULT3[row[2]] ^ row[3]; - outputCells[i * 4 + 2] = row[0] ^ row[1] ^ MULT2[row[2]] ^ MULT3[row[3]]; - outputCells[i * 4 + 3] = MULT3[row[0]] ^ row[1] ^ row[2] ^ MULT2[row[3]]; - } - return mergeCellsIntoBlock(outputCells); - } - - /** - * Applies the inverse Rijndael MixColumns for decryption to the input and - * returns the result. - */ - public static BigInteger mixColumnsDec(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] outputCells = new int[16]; - - for (int i = 0; i < 4; i++) { - int[] row = { - cells[i * 4], - cells[i * 4 + 1], - cells[i * 4 + 2], - cells[i * 4 + 3], - }; - - outputCells[i * 4] = MULT14[row[0]] ^ MULT11[row[1]] ^ MULT13[row[2]] ^ MULT9[row[3]]; - outputCells[i * 4 + 1] = MULT9[row[0]] ^ MULT14[row[1]] ^ MULT11[row[2]] ^ MULT13[row[3]]; - outputCells[i * 4 + 2] = MULT13[row[0]] ^ MULT9[row[1]] ^ MULT14[row[2]] ^ MULT11[row[3]]; - outputCells[i * 4 + 3] = MULT11[row[0]] ^ MULT13[row[1]] ^ MULT9[row[2]] ^ MULT14[row[3]]; - } - return mergeCellsIntoBlock(outputCells); - } - - /** - * Encrypts the plaintext with the key and returns the result - * - * @param plainText which we want to encrypt - * @param key the key for encrypt - * @return EncryptedText - */ - public static BigInteger encrypt(BigInteger plainText, BigInteger key) { - BigInteger[] roundKeys = keyExpansion(key); - - // Initial round - plainText = addRoundKey(plainText, roundKeys[0]); - - // Main rounds - for (int i = 1; i < 10; i++) { - plainText = subBytes(plainText); - plainText = shiftRows(plainText); - plainText = mixColumns(plainText); - plainText = addRoundKey(plainText, roundKeys[i]); - } - - // Final round - plainText = subBytes(plainText); - plainText = shiftRows(plainText); - plainText = addRoundKey(plainText, roundKeys[10]); - - return plainText; - } - - /** - * Decrypts the ciphertext with the key and returns the result - * - * @param cipherText The Encrypted text which we want to decrypt - * @return decryptedText - */ - public static BigInteger decrypt(BigInteger cipherText, BigInteger key) { - BigInteger[] roundKeys = keyExpansion(key); - - // Invert final round - cipherText = addRoundKey(cipherText, roundKeys[10]); - cipherText = shiftRowsDec(cipherText); - cipherText = subBytesDec(cipherText); - - // Invert main rounds - for (int i = 9; i > 0; i--) { - cipherText = addRoundKey(cipherText, roundKeys[i]); - cipherText = mixColumnsDec(cipherText); - cipherText = shiftRowsDec(cipherText); - cipherText = subBytesDec(cipherText); - } - - // Invert initial round - cipherText = addRoundKey(cipherText, roundKeys[0]); - - return cipherText; - } - - public static void main(String[] args) { - try (Scanner input = new Scanner(System.in)) { - System.out.println("Enter (e) letter for encrypt or (d) letter for decrypt :"); - char choice = input.nextLine().charAt(0); - String in; - switch (choice) { - case 'E', 'e' -> { - System.out.println( - "Choose a plaintext block (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger plaintext = new BigInteger(in, 16); - System.out.println( - "Choose a Key (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger encryptionKey = new BigInteger(in, 16); - System.out.println( - "The encrypted message is: \n" - + encrypt(plaintext, encryptionKey).toString(16) - ); - } - case 'D', 'd' -> { - System.out.println( - "Enter your ciphertext block (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger ciphertext = new BigInteger(in, 16); - System.out.println( - "Choose a Key (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger decryptionKey = new BigInteger(in, 16); - System.out.println( - "The deciphered message is:\n" - + decrypt(ciphertext, decryptionKey).toString(16) - ); - } - default -> System.out.println("** End **"); - } - } - } -} -package com.thealgorithms.ciphers; - -import java.math.BigInteger; -import java.util.Scanner; - -/** - * This class is build to demonstrate the application of the AES-algorithm on a - * single 128-Bit block of data. - */ -public final class AES { - private AES() { - } - - /** - * Precalculated values for x to the power of 2 in Rijndaels galois field. - * Used as 'RCON' during the key expansion. - */ - private static final int[] RCON = { - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - 0x01, - 0x02, - 0x04, - 0x08, - 0x10, - 0x20, - 0x40, - 0x80, - 0x1b, - 0x36, - 0x6c, - 0xd8, - 0xab, - 0x4d, - 0x9a, - 0x2f, - 0x5e, - 0xbc, - 0x63, - 0xc6, - 0x97, - 0x35, - 0x6a, - 0xd4, - 0xb3, - 0x7d, - 0xfa, - 0xef, - 0xc5, - 0x91, - 0x39, - 0x72, - 0xe4, - 0xd3, - 0xbd, - 0x61, - 0xc2, - 0x9f, - 0x25, - 0x4a, - 0x94, - 0x33, - 0x66, - 0xcc, - 0x83, - 0x1d, - 0x3a, - 0x74, - 0xe8, - 0xcb, - 0x8d, - }; - - /** - * Rijndael S-box Substitution table used for encryption in the subBytes - * step, as well as the key expansion. - */ - private static final int[] SBOX = { - 0x63, - 0x7C, - 0x77, - 0x7B, - 0xF2, - 0x6B, - 0x6F, - 0xC5, - 0x30, - 0x01, - 0x67, - 0x2B, - 0xFE, - 0xD7, - 0xAB, - 0x76, - 0xCA, - 0x82, - 0xC9, - 0x7D, - 0xFA, - 0x59, - 0x47, - 0xF0, - 0xAD, - 0xD4, - 0xA2, - 0xAF, - 0x9C, - 0xA4, - 0x72, - 0xC0, - 0xB7, - 0xFD, - 0x93, - 0x26, - 0x36, - 0x3F, - 0xF7, - 0xCC, - 0x34, - 0xA5, - 0xE5, - 0xF1, - 0x71, - 0xD8, - 0x31, - 0x15, - 0x04, - 0xC7, - 0x23, - 0xC3, - 0x18, - 0x96, - 0x05, - 0x9A, - 0x07, - 0x12, - 0x80, - 0xE2, - 0xEB, - 0x27, - 0xB2, - 0x75, - 0x09, - 0x83, - 0x2C, - 0x1A, - 0x1B, - 0x6E, - 0x5A, - 0xA0, - 0x52, - 0x3B, - 0xD6, - 0xB3, - 0x29, - 0xE3, - 0x2F, - 0x84, - 0x53, - 0xD1, - 0x00, - 0xED, - 0x20, - 0xFC, - 0xB1, - 0x5B, - 0x6A, - 0xCB, - 0xBE, - 0x39, - 0x4A, - 0x4C, - 0x58, - 0xCF, - 0xD0, - 0xEF, - 0xAA, - 0xFB, - 0x43, - 0x4D, - 0x33, - 0x85, - 0x45, - 0xF9, - 0x02, - 0x7F, - 0x50, - 0x3C, - 0x9F, - 0xA8, - 0x51, - 0xA3, - 0x40, - 0x8F, - 0x92, - 0x9D, - 0x38, - 0xF5, - 0xBC, - 0xB6, - 0xDA, - 0x21, - 0x10, - 0xFF, - 0xF3, - 0xD2, - 0xCD, - 0x0C, - 0x13, - 0xEC, - 0x5F, - 0x97, - 0x44, - 0x17, - 0xC4, - 0xA7, - 0x7E, - 0x3D, - 0x64, - 0x5D, - 0x19, - 0x73, - 0x60, - 0x81, - 0x4F, - 0xDC, - 0x22, - 0x2A, - 0x90, - 0x88, - 0x46, - 0xEE, - 0xB8, - 0x14, - 0xDE, - 0x5E, - 0x0B, - 0xDB, - 0xE0, - 0x32, - 0x3A, - 0x0A, - 0x49, - 0x06, - 0x24, - 0x5C, - 0xC2, - 0xD3, - 0xAC, - 0x62, - 0x91, - 0x95, - 0xE4, - 0x79, - 0xE7, - 0xC8, - 0x37, - 0x6D, - 0x8D, - 0xD5, - 0x4E, - 0xA9, - 0x6C, - 0x56, - 0xF4, - 0xEA, - 0x65, - 0x7A, - 0xAE, - 0x08, - 0xBA, - 0x78, - 0x25, - 0x2E, - 0x1C, - 0xA6, - 0xB4, - 0xC6, - 0xE8, - 0xDD, - 0x74, - 0x1F, - 0x4B, - 0xBD, - 0x8B, - 0x8A, - 0x70, - 0x3E, - 0xB5, - 0x66, - 0x48, - 0x03, - 0xF6, - 0x0E, - 0x61, - 0x35, - 0x57, - 0xB9, - 0x86, - 0xC1, - 0x1D, - 0x9E, - 0xE1, - 0xF8, - 0x98, - 0x11, - 0x69, - 0xD9, - 0x8E, - 0x94, - 0x9B, - 0x1E, - 0x87, - 0xE9, - 0xCE, - 0x55, - 0x28, - 0xDF, - 0x8C, - 0xA1, - 0x89, - 0x0D, - 0xBF, - 0xE6, - 0x42, - 0x68, - 0x41, - 0x99, - 0x2D, - 0x0F, - 0xB0, - 0x54, - 0xBB, - 0x16, - }; - - /** - * Inverse Rijndael S-box Substitution table used for decryption in the - * subBytesDec step. - */ - private static final int[] INVERSE_SBOX = { - 0x52, - 0x09, - 0x6A, - 0xD5, - 0x30, - 0x36, - 0xA5, - 0x38, - 0xBF, - 0x40, - 0xA3, - 0x9E, - 0x81, - 0xF3, - 0xD7, - 0xFB, - 0x7C, - 0xE3, - 0x39, - 0x82, - 0x9B, - 0x2F, - 0xFF, - 0x87, - 0x34, - 0x8E, - 0x43, - 0x44, - 0xC4, - 0xDE, - 0xE9, - 0xCB, - 0x54, - 0x7B, - 0x94, - 0x32, - 0xA6, - 0xC2, - 0x23, - 0x3D, - 0xEE, - 0x4C, - 0x95, - 0x0B, - 0x42, - 0xFA, - 0xC3, - 0x4E, - 0x08, - 0x2E, - 0xA1, - 0x66, - 0x28, - 0xD9, - 0x24, - 0xB2, - 0x76, - 0x5B, - 0xA2, - 0x49, - 0x6D, - 0x8B, - 0xD1, - 0x25, - 0x72, - 0xF8, - 0xF6, - 0x64, - 0x86, - 0x68, - 0x98, - 0x16, - 0xD4, - 0xA4, - 0x5C, - 0xCC, - 0x5D, - 0x65, - 0xB6, - 0x92, - 0x6C, - 0x70, - 0x48, - 0x50, - 0xFD, - 0xED, - 0xB9, - 0xDA, - 0x5E, - 0x15, - 0x46, - 0x57, - 0xA7, - 0x8D, - 0x9D, - 0x84, - 0x90, - 0xD8, - 0xAB, - 0x00, - 0x8C, - 0xBC, - 0xD3, - 0x0A, - 0xF7, - 0xE4, - 0x58, - 0x05, - 0xB8, - 0xB3, - 0x45, - 0x06, - 0xD0, - 0x2C, - 0x1E, - 0x8F, - 0xCA, - 0x3F, - 0x0F, - 0x02, - 0xC1, - 0xAF, - 0xBD, - 0x03, - 0x01, - 0x13, - 0x8A, - 0x6B, - 0x3A, - 0x91, - 0x11, - 0x41, - 0x4F, - 0x67, - 0xDC, - 0xEA, - 0x97, - 0xF2, - 0xCF, - 0xCE, - 0xF0, - 0xB4, - 0xE6, - 0x73, - 0x96, - 0xAC, - 0x74, - 0x22, - 0xE7, - 0xAD, - 0x35, - 0x85, - 0xE2, - 0xF9, - 0x37, - 0xE8, - 0x1C, - 0x75, - 0xDF, - 0x6E, - 0x47, - 0xF1, - 0x1A, - 0x71, - 0x1D, - 0x29, - 0xC5, - 0x89, - 0x6F, - 0xB7, - 0x62, - 0x0E, - 0xAA, - 0x18, - 0xBE, - 0x1B, - 0xFC, - 0x56, - 0x3E, - 0x4B, - 0xC6, - 0xD2, - 0x79, - 0x20, - 0x9A, - 0xDB, - 0xC0, - 0xFE, - 0x78, - 0xCD, - 0x5A, - 0xF4, - 0x1F, - 0xDD, - 0xA8, - 0x33, - 0x88, - 0x07, - 0xC7, - 0x31, - 0xB1, - 0x12, - 0x10, - 0x59, - 0x27, - 0x80, - 0xEC, - 0x5F, - 0x60, - 0x51, - 0x7F, - 0xA9, - 0x19, - 0xB5, - 0x4A, - 0x0D, - 0x2D, - 0xE5, - 0x7A, - 0x9F, - 0x93, - 0xC9, - 0x9C, - 0xEF, - 0xA0, - 0xE0, - 0x3B, - 0x4D, - 0xAE, - 0x2A, - 0xF5, - 0xB0, - 0xC8, - 0xEB, - 0xBB, - 0x3C, - 0x83, - 0x53, - 0x99, - 0x61, - 0x17, - 0x2B, - 0x04, - 0x7E, - 0xBA, - 0x77, - 0xD6, - 0x26, - 0xE1, - 0x69, - 0x14, - 0x63, - 0x55, - 0x21, - 0x0C, - 0x7D, - }; - - /** - * Precalculated lookup table for galois field multiplication by 2 used in - * the MixColums step during encryption. - */ - private static final int[] MULT2 = { - 0x00, - 0x02, - 0x04, - 0x06, - 0x08, - 0x0a, - 0x0c, - 0x0e, - 0x10, - 0x12, - 0x14, - 0x16, - 0x18, - 0x1a, - 0x1c, - 0x1e, - 0x20, - 0x22, - 0x24, - 0x26, - 0x28, - 0x2a, - 0x2c, - 0x2e, - 0x30, - 0x32, - 0x34, - 0x36, - 0x38, - 0x3a, - 0x3c, - 0x3e, - 0x40, - 0x42, - 0x44, - 0x46, - 0x48, - 0x4a, - 0x4c, - 0x4e, - 0x50, - 0x52, - 0x54, - 0x56, - 0x58, - 0x5a, - 0x5c, - 0x5e, - 0x60, - 0x62, - 0x64, - 0x66, - 0x68, - 0x6a, - 0x6c, - 0x6e, - 0x70, - 0x72, - 0x74, - 0x76, - 0x78, - 0x7a, - 0x7c, - 0x7e, - 0x80, - 0x82, - 0x84, - 0x86, - 0x88, - 0x8a, - 0x8c, - 0x8e, - 0x90, - 0x92, - 0x94, - 0x96, - 0x98, - 0x9a, - 0x9c, - 0x9e, - 0xa0, - 0xa2, - 0xa4, - 0xa6, - 0xa8, - 0xaa, - 0xac, - 0xae, - 0xb0, - 0xb2, - 0xb4, - 0xb6, - 0xb8, - 0xba, - 0xbc, - 0xbe, - 0xc0, - 0xc2, - 0xc4, - 0xc6, - 0xc8, - 0xca, - 0xcc, - 0xce, - 0xd0, - 0xd2, - 0xd4, - 0xd6, - 0xd8, - 0xda, - 0xdc, - 0xde, - 0xe0, - 0xe2, - 0xe4, - 0xe6, - 0xe8, - 0xea, - 0xec, - 0xee, - 0xf0, - 0xf2, - 0xf4, - 0xf6, - 0xf8, - 0xfa, - 0xfc, - 0xfe, - 0x1b, - 0x19, - 0x1f, - 0x1d, - 0x13, - 0x11, - 0x17, - 0x15, - 0x0b, - 0x09, - 0x0f, - 0x0d, - 0x03, - 0x01, - 0x07, - 0x05, - 0x3b, - 0x39, - 0x3f, - 0x3d, - 0x33, - 0x31, - 0x37, - 0x35, - 0x2b, - 0x29, - 0x2f, - 0x2d, - 0x23, - 0x21, - 0x27, - 0x25, - 0x5b, - 0x59, - 0x5f, - 0x5d, - 0x53, - 0x51, - 0x57, - 0x55, - 0x4b, - 0x49, - 0x4f, - 0x4d, - 0x43, - 0x41, - 0x47, - 0x45, - 0x7b, - 0x79, - 0x7f, - 0x7d, - 0x73, - 0x71, - 0x77, - 0x75, - 0x6b, - 0x69, - 0x6f, - 0x6d, - 0x63, - 0x61, - 0x67, - 0x65, - 0x9b, - 0x99, - 0x9f, - 0x9d, - 0x93, - 0x91, - 0x97, - 0x95, - 0x8b, - 0x89, - 0x8f, - 0x8d, - 0x83, - 0x81, - 0x87, - 0x85, - 0xbb, - 0xb9, - 0xbf, - 0xbd, - 0xb3, - 0xb1, - 0xb7, - 0xb5, - 0xab, - 0xa9, - 0xaf, - 0xad, - 0xa3, - 0xa1, - 0xa7, - 0xa5, - 0xdb, - 0xd9, - 0xdf, - 0xdd, - 0xd3, - 0xd1, - 0xd7, - 0xd5, - 0xcb, - 0xc9, - 0xcf, - 0xcd, - 0xc3, - 0xc1, - 0xc7, - 0xc5, - 0xfb, - 0xf9, - 0xff, - 0xfd, - 0xf3, - 0xf1, - 0xf7, - 0xf5, - 0xeb, - 0xe9, - 0xef, - 0xed, - 0xe3, - 0xe1, - 0xe7, - 0xe5, - }; - - /** - * Precalculated lookup table for galois field multiplication by 3 used in - * the MixColums step during encryption. - */ - private static final int[] MULT3 = { - 0x00, - 0x03, - 0x06, - 0x05, - 0x0c, - 0x0f, - 0x0a, - 0x09, - 0x18, - 0x1b, - 0x1e, - 0x1d, - 0x14, - 0x17, - 0x12, - 0x11, - 0x30, - 0x33, - 0x36, - 0x35, - 0x3c, - 0x3f, - 0x3a, - 0x39, - 0x28, - 0x2b, - 0x2e, - 0x2d, - 0x24, - 0x27, - 0x22, - 0x21, - 0x60, - 0x63, - 0x66, - 0x65, - 0x6c, - 0x6f, - 0x6a, - 0x69, - 0x78, - 0x7b, - 0x7e, - 0x7d, - 0x74, - 0x77, - 0x72, - 0x71, - 0x50, - 0x53, - 0x56, - 0x55, - 0x5c, - 0x5f, - 0x5a, - 0x59, - 0x48, - 0x4b, - 0x4e, - 0x4d, - 0x44, - 0x47, - 0x42, - 0x41, - 0xc0, - 0xc3, - 0xc6, - 0xc5, - 0xcc, - 0xcf, - 0xca, - 0xc9, - 0xd8, - 0xdb, - 0xde, - 0xdd, - 0xd4, - 0xd7, - 0xd2, - 0xd1, - 0xf0, - 0xf3, - 0xf6, - 0xf5, - 0xfc, - 0xff, - 0xfa, - 0xf9, - 0xe8, - 0xeb, - 0xee, - 0xed, - 0xe4, - 0xe7, - 0xe2, - 0xe1, - 0xa0, - 0xa3, - 0xa6, - 0xa5, - 0xac, - 0xaf, - 0xaa, - 0xa9, - 0xb8, - 0xbb, - 0xbe, - 0xbd, - 0xb4, - 0xb7, - 0xb2, - 0xb1, - 0x90, - 0x93, - 0x96, - 0x95, - 0x9c, - 0x9f, - 0x9a, - 0x99, - 0x88, - 0x8b, - 0x8e, - 0x8d, - 0x84, - 0x87, - 0x82, - 0x81, - 0x9b, - 0x98, - 0x9d, - 0x9e, - 0x97, - 0x94, - 0x91, - 0x92, - 0x83, - 0x80, - 0x85, - 0x86, - 0x8f, - 0x8c, - 0x89, - 0x8a, - 0xab, - 0xa8, - 0xad, - 0xae, - 0xa7, - 0xa4, - 0xa1, - 0xa2, - 0xb3, - 0xb0, - 0xb5, - 0xb6, - 0xbf, - 0xbc, - 0xb9, - 0xba, - 0xfb, - 0xf8, - 0xfd, - 0xfe, - 0xf7, - 0xf4, - 0xf1, - 0xf2, - 0xe3, - 0xe0, - 0xe5, - 0xe6, - 0xef, - 0xec, - 0xe9, - 0xea, - 0xcb, - 0xc8, - 0xcd, - 0xce, - 0xc7, - 0xc4, - 0xc1, - 0xc2, - 0xd3, - 0xd0, - 0xd5, - 0xd6, - 0xdf, - 0xdc, - 0xd9, - 0xda, - 0x5b, - 0x58, - 0x5d, - 0x5e, - 0x57, - 0x54, - 0x51, - 0x52, - 0x43, - 0x40, - 0x45, - 0x46, - 0x4f, - 0x4c, - 0x49, - 0x4a, - 0x6b, - 0x68, - 0x6d, - 0x6e, - 0x67, - 0x64, - 0x61, - 0x62, - 0x73, - 0x70, - 0x75, - 0x76, - 0x7f, - 0x7c, - 0x79, - 0x7a, - 0x3b, - 0x38, - 0x3d, - 0x3e, - 0x37, - 0x34, - 0x31, - 0x32, - 0x23, - 0x20, - 0x25, - 0x26, - 0x2f, - 0x2c, - 0x29, - 0x2a, - 0x0b, - 0x08, - 0x0d, - 0x0e, - 0x07, - 0x04, - 0x01, - 0x02, - 0x13, - 0x10, - 0x15, - 0x16, - 0x1f, - 0x1c, - 0x19, - 0x1a, - }; - - /** - * Precalculated lookup table for galois field multiplication by 9 used in - * the MixColums step during decryption. - */ - private static final int[] MULT9 = { - 0x00, - 0x09, - 0x12, - 0x1b, - 0x24, - 0x2d, - 0x36, - 0x3f, - 0x48, - 0x41, - 0x5a, - 0x53, - 0x6c, - 0x65, - 0x7e, - 0x77, - 0x90, - 0x99, - 0x82, - 0x8b, - 0xb4, - 0xbd, - 0xa6, - 0xaf, - 0xd8, - 0xd1, - 0xca, - 0xc3, - 0xfc, - 0xf5, - 0xee, - 0xe7, - 0x3b, - 0x32, - 0x29, - 0x20, - 0x1f, - 0x16, - 0x0d, - 0x04, - 0x73, - 0x7a, - 0x61, - 0x68, - 0x57, - 0x5e, - 0x45, - 0x4c, - 0xab, - 0xa2, - 0xb9, - 0xb0, - 0x8f, - 0x86, - 0x9d, - 0x94, - 0xe3, - 0xea, - 0xf1, - 0xf8, - 0xc7, - 0xce, - 0xd5, - 0xdc, - 0x76, - 0x7f, - 0x64, - 0x6d, - 0x52, - 0x5b, - 0x40, - 0x49, - 0x3e, - 0x37, - 0x2c, - 0x25, - 0x1a, - 0x13, - 0x08, - 0x01, - 0xe6, - 0xef, - 0xf4, - 0xfd, - 0xc2, - 0xcb, - 0xd0, - 0xd9, - 0xae, - 0xa7, - 0xbc, - 0xb5, - 0x8a, - 0x83, - 0x98, - 0x91, - 0x4d, - 0x44, - 0x5f, - 0x56, - 0x69, - 0x60, - 0x7b, - 0x72, - 0x05, - 0x0c, - 0x17, - 0x1e, - 0x21, - 0x28, - 0x33, - 0x3a, - 0xdd, - 0xd4, - 0xcf, - 0xc6, - 0xf9, - 0xf0, - 0xeb, - 0xe2, - 0x95, - 0x9c, - 0x87, - 0x8e, - 0xb1, - 0xb8, - 0xa3, - 0xaa, - 0xec, - 0xe5, - 0xfe, - 0xf7, - 0xc8, - 0xc1, - 0xda, - 0xd3, - 0xa4, - 0xad, - 0xb6, - 0xbf, - 0x80, - 0x89, - 0x92, - 0x9b, - 0x7c, - 0x75, - 0x6e, - 0x67, - 0x58, - 0x51, - 0x4a, - 0x43, - 0x34, - 0x3d, - 0x26, - 0x2f, - 0x10, - 0x19, - 0x02, - 0x0b, - 0xd7, - 0xde, - 0xc5, - 0xcc, - 0xf3, - 0xfa, - 0xe1, - 0xe8, - 0x9f, - 0x96, - 0x8d, - 0x84, - 0xbb, - 0xb2, - 0xa9, - 0xa0, - 0x47, - 0x4e, - 0x55, - 0x5c, - 0x63, - 0x6a, - 0x71, - 0x78, - 0x0f, - 0x06, - 0x1d, - 0x14, - 0x2b, - 0x22, - 0x39, - 0x30, - 0x9a, - 0x93, - 0x88, - 0x81, - 0xbe, - 0xb7, - 0xac, - 0xa5, - 0xd2, - 0xdb, - 0xc0, - 0xc9, - 0xf6, - 0xff, - 0xe4, - 0xed, - 0x0a, - 0x03, - 0x18, - 0x11, - 0x2e, - 0x27, - 0x3c, - 0x35, - 0x42, - 0x4b, - 0x50, - 0x59, - 0x66, - 0x6f, - 0x74, - 0x7d, - 0xa1, - 0xa8, - 0xb3, - 0xba, - 0x85, - 0x8c, - 0x97, - 0x9e, - 0xe9, - 0xe0, - 0xfb, - 0xf2, - 0xcd, - 0xc4, - 0xdf, - 0xd6, - 0x31, - 0x38, - 0x23, - 0x2a, - 0x15, - 0x1c, - 0x07, - 0x0e, - 0x79, - 0x70, - 0x6b, - 0x62, - 0x5d, - 0x54, - 0x4f, - 0x46, - }; - - /** - * Precalculated lookup table for galois field multiplication by 11 used in - * the MixColums step during decryption. - */ - private static final int[] MULT11 = { - 0x00, - 0x0b, - 0x16, - 0x1d, - 0x2c, - 0x27, - 0x3a, - 0x31, - 0x58, - 0x53, - 0x4e, - 0x45, - 0x74, - 0x7f, - 0x62, - 0x69, - 0xb0, - 0xbb, - 0xa6, - 0xad, - 0x9c, - 0x97, - 0x8a, - 0x81, - 0xe8, - 0xe3, - 0xfe, - 0xf5, - 0xc4, - 0xcf, - 0xd2, - 0xd9, - 0x7b, - 0x70, - 0x6d, - 0x66, - 0x57, - 0x5c, - 0x41, - 0x4a, - 0x23, - 0x28, - 0x35, - 0x3e, - 0x0f, - 0x04, - 0x19, - 0x12, - 0xcb, - 0xc0, - 0xdd, - 0xd6, - 0xe7, - 0xec, - 0xf1, - 0xfa, - 0x93, - 0x98, - 0x85, - 0x8e, - 0xbf, - 0xb4, - 0xa9, - 0xa2, - 0xf6, - 0xfd, - 0xe0, - 0xeb, - 0xda, - 0xd1, - 0xcc, - 0xc7, - 0xae, - 0xa5, - 0xb8, - 0xb3, - 0x82, - 0x89, - 0x94, - 0x9f, - 0x46, - 0x4d, - 0x50, - 0x5b, - 0x6a, - 0x61, - 0x7c, - 0x77, - 0x1e, - 0x15, - 0x08, - 0x03, - 0x32, - 0x39, - 0x24, - 0x2f, - 0x8d, - 0x86, - 0x9b, - 0x90, - 0xa1, - 0xaa, - 0xb7, - 0xbc, - 0xd5, - 0xde, - 0xc3, - 0xc8, - 0xf9, - 0xf2, - 0xef, - 0xe4, - 0x3d, - 0x36, - 0x2b, - 0x20, - 0x11, - 0x1a, - 0x07, - 0x0c, - 0x65, - 0x6e, - 0x73, - 0x78, - 0x49, - 0x42, - 0x5f, - 0x54, - 0xf7, - 0xfc, - 0xe1, - 0xea, - 0xdb, - 0xd0, - 0xcd, - 0xc6, - 0xaf, - 0xa4, - 0xb9, - 0xb2, - 0x83, - 0x88, - 0x95, - 0x9e, - 0x47, - 0x4c, - 0x51, - 0x5a, - 0x6b, - 0x60, - 0x7d, - 0x76, - 0x1f, - 0x14, - 0x09, - 0x02, - 0x33, - 0x38, - 0x25, - 0x2e, - 0x8c, - 0x87, - 0x9a, - 0x91, - 0xa0, - 0xab, - 0xb6, - 0xbd, - 0xd4, - 0xdf, - 0xc2, - 0xc9, - 0xf8, - 0xf3, - 0xee, - 0xe5, - 0x3c, - 0x37, - 0x2a, - 0x21, - 0x10, - 0x1b, - 0x06, - 0x0d, - 0x64, - 0x6f, - 0x72, - 0x79, - 0x48, - 0x43, - 0x5e, - 0x55, - 0x01, - 0x0a, - 0x17, - 0x1c, - 0x2d, - 0x26, - 0x3b, - 0x30, - 0x59, - 0x52, - 0x4f, - 0x44, - 0x75, - 0x7e, - 0x63, - 0x68, - 0xb1, - 0xba, - 0xa7, - 0xac, - 0x9d, - 0x96, - 0x8b, - 0x80, - 0xe9, - 0xe2, - 0xff, - 0xf4, - 0xc5, - 0xce, - 0xd3, - 0xd8, - 0x7a, - 0x71, - 0x6c, - 0x67, - 0x56, - 0x5d, - 0x40, - 0x4b, - 0x22, - 0x29, - 0x34, - 0x3f, - 0x0e, - 0x05, - 0x18, - 0x13, - 0xca, - 0xc1, - 0xdc, - 0xd7, - 0xe6, - 0xed, - 0xf0, - 0xfb, - 0x92, - 0x99, - 0x84, - 0x8f, - 0xbe, - 0xb5, - 0xa8, - 0xa3, - }; - - /** - * Precalculated lookup table for galois field multiplication by 13 used in - * the MixColums step during decryption. - */ - private static final int[] MULT13 = { - 0x00, - 0x0d, - 0x1a, - 0x17, - 0x34, - 0x39, - 0x2e, - 0x23, - 0x68, - 0x65, - 0x72, - 0x7f, - 0x5c, - 0x51, - 0x46, - 0x4b, - 0xd0, - 0xdd, - 0xca, - 0xc7, - 0xe4, - 0xe9, - 0xfe, - 0xf3, - 0xb8, - 0xb5, - 0xa2, - 0xaf, - 0x8c, - 0x81, - 0x96, - 0x9b, - 0xbb, - 0xb6, - 0xa1, - 0xac, - 0x8f, - 0x82, - 0x95, - 0x98, - 0xd3, - 0xde, - 0xc9, - 0xc4, - 0xe7, - 0xea, - 0xfd, - 0xf0, - 0x6b, - 0x66, - 0x71, - 0x7c, - 0x5f, - 0x52, - 0x45, - 0x48, - 0x03, - 0x0e, - 0x19, - 0x14, - 0x37, - 0x3a, - 0x2d, - 0x20, - 0x6d, - 0x60, - 0x77, - 0x7a, - 0x59, - 0x54, - 0x43, - 0x4e, - 0x05, - 0x08, - 0x1f, - 0x12, - 0x31, - 0x3c, - 0x2b, - 0x26, - 0xbd, - 0xb0, - 0xa7, - 0xaa, - 0x89, - 0x84, - 0x93, - 0x9e, - 0xd5, - 0xd8, - 0xcf, - 0xc2, - 0xe1, - 0xec, - 0xfb, - 0xf6, - 0xd6, - 0xdb, - 0xcc, - 0xc1, - 0xe2, - 0xef, - 0xf8, - 0xf5, - 0xbe, - 0xb3, - 0xa4, - 0xa9, - 0x8a, - 0x87, - 0x90, - 0x9d, - 0x06, - 0x0b, - 0x1c, - 0x11, - 0x32, - 0x3f, - 0x28, - 0x25, - 0x6e, - 0x63, - 0x74, - 0x79, - 0x5a, - 0x57, - 0x40, - 0x4d, - 0xda, - 0xd7, - 0xc0, - 0xcd, - 0xee, - 0xe3, - 0xf4, - 0xf9, - 0xb2, - 0xbf, - 0xa8, - 0xa5, - 0x86, - 0x8b, - 0x9c, - 0x91, - 0x0a, - 0x07, - 0x10, - 0x1d, - 0x3e, - 0x33, - 0x24, - 0x29, - 0x62, - 0x6f, - 0x78, - 0x75, - 0x56, - 0x5b, - 0x4c, - 0x41, - 0x61, - 0x6c, - 0x7b, - 0x76, - 0x55, - 0x58, - 0x4f, - 0x42, - 0x09, - 0x04, - 0x13, - 0x1e, - 0x3d, - 0x30, - 0x27, - 0x2a, - 0xb1, - 0xbc, - 0xab, - 0xa6, - 0x85, - 0x88, - 0x9f, - 0x92, - 0xd9, - 0xd4, - 0xc3, - 0xce, - 0xed, - 0xe0, - 0xf7, - 0xfa, - 0xb7, - 0xba, - 0xad, - 0xa0, - 0x83, - 0x8e, - 0x99, - 0x94, - 0xdf, - 0xd2, - 0xc5, - 0xc8, - 0xeb, - 0xe6, - 0xf1, - 0xfc, - 0x67, - 0x6a, - 0x7d, - 0x70, - 0x53, - 0x5e, - 0x49, - 0x44, - 0x0f, - 0x02, - 0x15, - 0x18, - 0x3b, - 0x36, - 0x21, - 0x2c, - 0x0c, - 0x01, - 0x16, - 0x1b, - 0x38, - 0x35, - 0x22, - 0x2f, - 0x64, - 0x69, - 0x7e, - 0x73, - 0x50, - 0x5d, - 0x4a, - 0x47, - 0xdc, - 0xd1, - 0xc6, - 0xcb, - 0xe8, - 0xe5, - 0xf2, - 0xff, - 0xb4, - 0xb9, - 0xae, - 0xa3, - 0x80, - 0x8d, - 0x9a, - 0x97, - }; - - /** - * Precalculated lookup table for galois field multiplication by 14 used in - * the MixColums step during decryption. - */ - private static final int[] MULT14 = { - 0x00, - 0x0e, - 0x1c, - 0x12, - 0x38, - 0x36, - 0x24, - 0x2a, - 0x70, - 0x7e, - 0x6c, - 0x62, - 0x48, - 0x46, - 0x54, - 0x5a, - 0xe0, - 0xee, - 0xfc, - 0xf2, - 0xd8, - 0xd6, - 0xc4, - 0xca, - 0x90, - 0x9e, - 0x8c, - 0x82, - 0xa8, - 0xa6, - 0xb4, - 0xba, - 0xdb, - 0xd5, - 0xc7, - 0xc9, - 0xe3, - 0xed, - 0xff, - 0xf1, - 0xab, - 0xa5, - 0xb7, - 0xb9, - 0x93, - 0x9d, - 0x8f, - 0x81, - 0x3b, - 0x35, - 0x27, - 0x29, - 0x03, - 0x0d, - 0x1f, - 0x11, - 0x4b, - 0x45, - 0x57, - 0x59, - 0x73, - 0x7d, - 0x6f, - 0x61, - 0xad, - 0xa3, - 0xb1, - 0xbf, - 0x95, - 0x9b, - 0x89, - 0x87, - 0xdd, - 0xd3, - 0xc1, - 0xcf, - 0xe5, - 0xeb, - 0xf9, - 0xf7, - 0x4d, - 0x43, - 0x51, - 0x5f, - 0x75, - 0x7b, - 0x69, - 0x67, - 0x3d, - 0x33, - 0x21, - 0x2f, - 0x05, - 0x0b, - 0x19, - 0x17, - 0x76, - 0x78, - 0x6a, - 0x64, - 0x4e, - 0x40, - 0x52, - 0x5c, - 0x06, - 0x08, - 0x1a, - 0x14, - 0x3e, - 0x30, - 0x22, - 0x2c, - 0x96, - 0x98, - 0x8a, - 0x84, - 0xae, - 0xa0, - 0xb2, - 0xbc, - 0xe6, - 0xe8, - 0xfa, - 0xf4, - 0xde, - 0xd0, - 0xc2, - 0xcc, - 0x41, - 0x4f, - 0x5d, - 0x53, - 0x79, - 0x77, - 0x65, - 0x6b, - 0x31, - 0x3f, - 0x2d, - 0x23, - 0x09, - 0x07, - 0x15, - 0x1b, - 0xa1, - 0xaf, - 0xbd, - 0xb3, - 0x99, - 0x97, - 0x85, - 0x8b, - 0xd1, - 0xdf, - 0xcd, - 0xc3, - 0xe9, - 0xe7, - 0xf5, - 0xfb, - 0x9a, - 0x94, - 0x86, - 0x88, - 0xa2, - 0xac, - 0xbe, - 0xb0, - 0xea, - 0xe4, - 0xf6, - 0xf8, - 0xd2, - 0xdc, - 0xce, - 0xc0, - 0x7a, - 0x74, - 0x66, - 0x68, - 0x42, - 0x4c, - 0x5e, - 0x50, - 0x0a, - 0x04, - 0x16, - 0x18, - 0x32, - 0x3c, - 0x2e, - 0x20, - 0xec, - 0xe2, - 0xf0, - 0xfe, - 0xd4, - 0xda, - 0xc8, - 0xc6, - 0x9c, - 0x92, - 0x80, - 0x8e, - 0xa4, - 0xaa, - 0xb8, - 0xb6, - 0x0c, - 0x02, - 0x10, - 0x1e, - 0x34, - 0x3a, - 0x28, - 0x26, - 0x7c, - 0x72, - 0x60, - 0x6e, - 0x44, - 0x4a, - 0x58, - 0x56, - 0x37, - 0x39, - 0x2b, - 0x25, - 0x0f, - 0x01, - 0x13, - 0x1d, - 0x47, - 0x49, - 0x5b, - 0x55, - 0x7f, - 0x71, - 0x63, - 0x6d, - 0xd7, - 0xd9, - 0xcb, - 0xc5, - 0xef, - 0xe1, - 0xf3, - 0xfd, - 0xa7, - 0xa9, - 0xbb, - 0xb5, - 0x9f, - 0x91, - 0x83, - 0x8d, - }; - - /** - * Subroutine of the Rijndael key expansion. - */ - public static BigInteger scheduleCore(BigInteger t, int rconCounter) { - StringBuilder rBytes = new StringBuilder(t.toString(16)); - - // Add zero padding - while (rBytes.length() < 8) { - rBytes.insert(0, "0"); - } - - // rotate the first 16 bits to the back - String rotatingBytes = rBytes.substring(0, 2); - String fixedBytes = rBytes.substring(2); - - rBytes = new StringBuilder(fixedBytes + rotatingBytes); - - // apply S-Box to all 8-Bit Substrings - for (int i = 0; i < 4; i++) { - StringBuilder currentByteBits = new StringBuilder(rBytes.substring(i * 2, (i + 1) * 2)); - - int currentByte = Integer.parseInt(currentByteBits.toString(), 16); - currentByte = SBOX[currentByte]; - - // add the current RCON value to the first byte - if (i == 0) { - currentByte = currentByte ^ RCON[rconCounter]; - } - - currentByteBits = new StringBuilder(Integer.toHexString(currentByte)); - - // Add zero padding - while (currentByteBits.length() < 2) { - currentByteBits.insert(0, '0'); - } - - // replace bytes in original string - rBytes = new StringBuilder(rBytes.substring(0, i * 2) + currentByteBits + rBytes.substring((i + 1) * 2)); - } - - return new BigInteger(rBytes.toString(), 16); - } - - /** - * Returns an array of 10 + 1 round keys that are calculated by using - * Rijndael key schedule - * - * @return array of 10 + 1 round keys - */ - public static BigInteger[] keyExpansion(BigInteger initialKey) { - BigInteger[] roundKeys = { - initialKey, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - BigInteger.ZERO, - }; - - // initialize rcon iteration - int rconCounter = 1; - - for (int i = 1; i < 11; i++) { - // get the previous 32 bits the key - BigInteger t = roundKeys[i - 1].remainder(new BigInteger("100000000", 16)); - - // split previous key into 8-bit segments - BigInteger[] prevKey = { - roundKeys[i - 1].remainder(new BigInteger("100000000", 16)), - roundKeys[i - 1].remainder(new BigInteger("10000000000000000", 16)).divide(new BigInteger("100000000", 16)), - roundKeys[i - 1].remainder(new BigInteger("1000000000000000000000000", 16)).divide(new BigInteger("10000000000000000", 16)), - roundKeys[i - 1].divide(new BigInteger("1000000000000000000000000", 16)), - }; - - // run schedule core - t = scheduleCore(t, rconCounter); - rconCounter += 1; - - // Calculate partial round key - BigInteger t0 = t.xor(prevKey[3]); - BigInteger t1 = t0.xor(prevKey[2]); - BigInteger t2 = t1.xor(prevKey[1]); - BigInteger t3 = t2.xor(prevKey[0]); - - // Join round key segments - t2 = t2.multiply(new BigInteger("100000000", 16)); - t1 = t1.multiply(new BigInteger("10000000000000000", 16)); - t0 = t0.multiply(new BigInteger("1000000000000000000000000", 16)); - roundKeys[i] = t0.add(t1).add(t2).add(t3); - } - return roundKeys; - } - - /** - * representation of the input 128-bit block as an array of 8-bit integers. - * - * @param block of 128-bit integers - * @return array of 8-bit integers - */ - public static int[] splitBlockIntoCells(BigInteger block) { - int[] cells = new int[16]; - StringBuilder blockBits = new StringBuilder(block.toString(2)); - - // Append leading 0 for full "128-bit" string - while (blockBits.length() < 128) { - blockBits.insert(0, '0'); - } - - // split 128 to 8 bit cells - for (int i = 0; i < cells.length; i++) { - String cellBits = blockBits.substring(8 * i, 8 * (i + 1)); - cells[i] = Integer.parseInt(cellBits, 2); - } - - return cells; - } - - /** - * Returns the 128-bit BigInteger representation of the input of an array of - * 8-bit integers. - * - * @param cells that we need to merge - * @return block of merged cells - */ - public static BigInteger mergeCellsIntoBlock(int[] cells) { - StringBuilder blockBits = new StringBuilder(); - for (int i = 0; i < 16; i++) { - StringBuilder cellBits = new StringBuilder(Integer.toBinaryString(cells[i])); - - // Append leading 0 for full "8-bit" strings - while (cellBits.length() < 8) { - cellBits.insert(0, '0'); - } - - blockBits.append(cellBits); - } - - return new BigInteger(blockBits.toString(), 2); - } - - /** - * @return ciphertext XOR key - */ - public static BigInteger addRoundKey(BigInteger ciphertext, BigInteger key) { - return ciphertext.xor(key); - } - - /** - * substitutes 8-Bit long substrings of the input using the S-Box and - * returns the result. - * - * @return subtraction Output - */ - public static BigInteger subBytes(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - - for (int i = 0; i < 16; i++) { - cells[i] = SBOX[cells[i]]; - } - - return mergeCellsIntoBlock(cells); - } - - /** - * substitutes 8-Bit long substrings of the input using the inverse S-Box - * for decryption and returns the result. - * - * @return subtraction Output - */ - public static BigInteger subBytesDec(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - - for (int i = 0; i < 16; i++) { - cells[i] = INVERSE_SBOX[cells[i]]; - } - - return mergeCellsIntoBlock(cells); - } - - /** - * Cell permutation step. Shifts cells within the rows of the input and - * returns the result. - */ - public static BigInteger shiftRows(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] output = new int[16]; - - // do nothing in the first row - output[0] = cells[0]; - output[4] = cells[4]; - output[8] = cells[8]; - output[12] = cells[12]; - - // shift the second row backwards by one cell - output[1] = cells[5]; - output[5] = cells[9]; - output[9] = cells[13]; - output[13] = cells[1]; - - // shift the third row backwards by two cell - output[2] = cells[10]; - output[6] = cells[14]; - output[10] = cells[2]; - output[14] = cells[6]; - - // shift the forth row backwards by tree cell - output[3] = cells[15]; - output[7] = cells[3]; - output[11] = cells[7]; - output[15] = cells[11]; - - return mergeCellsIntoBlock(output); - } - - /** - * Cell permutation step for decryption . Shifts cells within the rows of - * the input and returns the result. - */ - public static BigInteger shiftRowsDec(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] output = new int[16]; - - // do nothing in the first row - output[0] = cells[0]; - output[4] = cells[4]; - output[8] = cells[8]; - output[12] = cells[12]; - - // shift the second row forwards by one cell - output[1] = cells[13]; - output[5] = cells[1]; - output[9] = cells[5]; - output[13] = cells[9]; - - // shift the third row forwards by two cell - output[2] = cells[10]; - output[6] = cells[14]; - output[10] = cells[2]; - output[14] = cells[6]; - - // shift the forth row forwards by tree cell - output[3] = cells[7]; - output[7] = cells[11]; - output[11] = cells[15]; - output[15] = cells[3]; - - return mergeCellsIntoBlock(output); - } - - /** - * Applies the Rijndael MixColumns to the input and returns the result. - */ - public static BigInteger mixColumns(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] outputCells = new int[16]; - - for (int i = 0; i < 4; i++) { - int[] row = { - cells[i * 4], - cells[i * 4 + 1], - cells[i * 4 + 2], - cells[i * 4 + 3], - }; - - outputCells[i * 4] = MULT2[row[0]] ^ MULT3[row[1]] ^ row[2] ^ row[3]; - outputCells[i * 4 + 1] = row[0] ^ MULT2[row[1]] ^ MULT3[row[2]] ^ row[3]; - outputCells[i * 4 + 2] = row[0] ^ row[1] ^ MULT2[row[2]] ^ MULT3[row[3]]; - outputCells[i * 4 + 3] = MULT3[row[0]] ^ row[1] ^ row[2] ^ MULT2[row[3]]; - } - return mergeCellsIntoBlock(outputCells); - } - - /** - * Applies the inverse Rijndael MixColumns for decryption to the input and - * returns the result. - */ - public static BigInteger mixColumnsDec(BigInteger ciphertext) { - int[] cells = splitBlockIntoCells(ciphertext); - int[] outputCells = new int[16]; - - for (int i = 0; i < 4; i++) { - int[] row = { - cells[i * 4], - cells[i * 4 + 1], - cells[i * 4 + 2], - cells[i * 4 + 3], - }; - - outputCells[i * 4] = MULT14[row[0]] ^ MULT11[row[1]] ^ MULT13[row[2]] ^ MULT9[row[3]]; - outputCells[i * 4 + 1] = MULT9[row[0]] ^ MULT14[row[1]] ^ MULT11[row[2]] ^ MULT13[row[3]]; - outputCells[i * 4 + 2] = MULT13[row[0]] ^ MULT9[row[1]] ^ MULT14[row[2]] ^ MULT11[row[3]]; - outputCells[i * 4 + 3] = MULT11[row[0]] ^ MULT13[row[1]] ^ MULT9[row[2]] ^ MULT14[row[3]]; - } - return mergeCellsIntoBlock(outputCells); - } - - /** - * Encrypts the plaintext with the key and returns the result - * - * @param plainText which we want to encrypt - * @param key the key for encrypt - * @return EncryptedText - */ - public static BigInteger encrypt(BigInteger plainText, BigInteger key) { - BigInteger[] roundKeys = keyExpansion(key); - - // Initial round - plainText = addRoundKey(plainText, roundKeys[0]); - - // Main rounds - for (int i = 1; i < 10; i++) { - plainText = subBytes(plainText); - plainText = shiftRows(plainText); - plainText = mixColumns(plainText); - plainText = addRoundKey(plainText, roundKeys[i]); - } - - // Final round - plainText = subBytes(plainText); - plainText = shiftRows(plainText); - plainText = addRoundKey(plainText, roundKeys[10]); - - return plainText; - } - - /** - * Decrypts the ciphertext with the key and returns the result - * - * @param cipherText The Encrypted text which we want to decrypt - * @return decryptedText - */ - public static BigInteger decrypt(BigInteger cipherText, BigInteger key) { - BigInteger[] roundKeys = keyExpansion(key); - - // Invert final round - cipherText = addRoundKey(cipherText, roundKeys[10]); - cipherText = shiftRowsDec(cipherText); - cipherText = subBytesDec(cipherText); - - // Invert main rounds - for (int i = 9; i > 0; i--) { - cipherText = addRoundKey(cipherText, roundKeys[i]); - cipherText = mixColumnsDec(cipherText); - cipherText = shiftRowsDec(cipherText); - cipherText = subBytesDec(cipherText); - } - - // Invert initial round - cipherText = addRoundKey(cipherText, roundKeys[0]); - - return cipherText; - } - - public static void main(String[] args) { - try (Scanner input = new Scanner(System.in)) { - System.out.println("Enter (e) letter for encrypt or (d) letter for decrypt :"); - char choice = input.nextLine().charAt(0); - String in; - switch (choice) { - case 'E', 'e' -> { - System.out.println( - "Choose a plaintext block (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger plaintext = new BigInteger(in, 16); - System.out.println( - "Choose a Key (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger encryptionKey = new BigInteger(in, 16); - System.out.println( - "The encrypted message is: \n" - + encrypt(plaintext, encryptionKey).toString(16) - ); - } - case 'D', 'd' -> { - System.out.println( - "Enter your ciphertext block (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger ciphertext = new BigInteger(in, 16); - System.out.println( - "Choose a Key (128-Bit Integer in base 16):" - ); - in = input.nextLine(); - BigInteger decryptionKey = new BigInteger(in, 16); - System.out.println( - "The deciphered message is:\n" - + decrypt(ciphertext, decryptionKey).toString(16) - ); - } - default -> System.out.println("** End **"); - } - } - } -}