diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..d3147c2
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+**/Constants.java filter=lfs diff=lfs merge=lfs -text
+**/UnchangingData.java filter=lfs diff=lfs merge=lfs -text
diff --git a/.gitignore b/.gitignore
index 09840c2..23d6846 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,12 @@ out/
!**/src/test/**/out/
.kotlin
XACrypto.jar
+<<<<<<< HEAD
+tests
+.idea/
+=======
.idea
+>>>>>>> main
### Eclipse ###
.apt_generated
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0417069..2e3c40a 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,9 @@
+<<<<<<< HEAD
+
+=======
+>>>>>>> main
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..35eb1dd 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 66fc926..dfa8b70 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,18 @@
A multi-purpose Cryptography library in Java. Working on it day by day, slowly. Someday this will be complete, today is not that day.
-To be clear, this is **NOT** mean't to be a replacement/alternative to BouncyCastle. Instead, it is meant to include what BouncyCastle does not have.
+To be clear, this is **NOT** mean't to be a replacement/alternative to BouncyCastle. Instead, it is meant to include what BouncyCastle does not have. I do not take any code whatsoever from OpenSSL or BouncyCastle for that reason.
+
+### Current Objective: ZekerRijndael (custom from-scratch AES-128 block cipher)
+### Note: i'm creating ZekerRijndael as it can be used for creating the following encryption ciphers: AES-CTR; AES-OFB; AES-CFB. Block modes include AES-CBC; AES-ECB. And of course AES-GCM + ASE-CCM
+### if i ever say 196-bit, i mean 192-bit my brain is just bugged lol
+## View the "zekerRijndael" branch to see inprogress work.
+
+(i keep confusing myself so here's a todo) TODO:
+### BLOWFISH-ECB
+### BLOWFISH-CBC
+### ARIA-ECB
+### ARIA-CBC
+### ARIA-CFB
+### ARIA-OFB
### Current Objective: ZekerRijndael (custom from-scratch AES-128 block cipher)
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/ECB/Blowfish.java b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/Blowfish.java
new file mode 100644
index 0000000..787cda5
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/Blowfish.java
@@ -0,0 +1,110 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.BLOWFISH_IP;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.BLOWFISH_IS;
+
+public class Blowfish {
+ private final int[] P = new int[18];
+ private final int[][] S = new int[4][256];
+ public Blowfish(byte[] key) throws XACryptoException {
+ if (key.length < 4 || key.length > 56) {
+ throw new XACryptoException("blowfish keys must be between 4-56 bytes :&", (int) key.length);
+ }
+ initSubkey(key);
+ }
+
+ private void initSubkey(byte[] key) {
+ System.arraycopy(BLOWFISH_IP, 0, this.P, 0, 18);
+ for (int i = 0 ; i < 4 ; i++) for (int j = 0 ; j < Math.min(BLOWFISH_IS[i].length, 256) ; j++) this.S[i][j] = BLOWFISH_IS[i][j];
+
+ int len = key.length;
+ int idx = 0;
+ for (int i = 0 ; i < 18 ; i++) {
+ int _0 = 0;
+
+ for (int j = 0 ; j < 4 ; j++) {
+ _0 = (_0 << 8) | (key[idx] & 0xFF);
+ idx = (idx + 1) % len;
+ }
+ P[i] ^= _0;
+ }
+
+ byte[] blk = new byte[8];
+ for (int s = 0 ; s < 4 ; s++) {
+ for (int i = 0 ; i < 18 ; i += 2){
+ encryptBlock(blk, 0, blk, 0);
+ S[s][i] = BYTE2INT(blk, 0);
+ S[s][i + 1] = BYTE2INT(blk, 4);
+ }
+ }
+ }
+ public void encryptBlock(byte[] in, int inOff, byte[] out, int outOff) {
+ int xl = BYTE2INT(in, inOff);
+ int xr = BYTE2INT(in, inOff + 4);
+
+ for (int i = 0 ; i < 16 ; i++) {
+ xl ^= P[i];
+ xr ^= F(xl);
+
+ int _0 = xl;
+ xl = xr;
+ xr = _0;
+ }
+
+ int _0 = xl;
+ xl = xr;
+ xr = _0;
+
+ xl ^= P[16];
+ xr ^= P[17];
+
+ INT2BYTE(xl, out, outOff);
+ INT2BYTE(xr, out, outOff + 4);
+ }
+ private int F(int x) {
+ int a = (x >>> 24) & 0xFF;
+ int b = (x >>> 16) & 0xFF;
+ int c = (x >>> 8) & 0xFF;
+ int d = x & 0xFF;
+
+ int val = (S[0][a] + S[1][b]) ^ S[2][c];
+ return val + S[3][d];
+ }
+ public void decryptBlock(byte[] in, int inOff, byte[] out, int outOff) {
+ int xl = BYTE2INT(in, inOff);
+ int xr = BYTE2INT(in, inOff + 4);
+
+ for (int i = 17 ; i > 1 ; i--) {
+ xl ^= P[i];
+ xr ^= F(xl);
+
+ int _0 = xl;
+ xl = xr;
+ xr = _0;
+ }
+
+ int _0 = xl;
+ xl = xr;
+ xr = _0;
+
+ xl ^= P[1];
+ xr ^= P[0];
+
+ INT2BYTE(xl, out, outOff);
+ INT2BYTE(xr, out, outOff + 4);
+ }
+ private int BYTE2INT(byte[] b, int off) {
+ return ((b[off] & 0xFF) << 24) |
+ ((b[off + 1] & 0xFF) << 16) |
+ ((b[off + 2] & 0xFF) << 8) |
+ (b[off + 3] & 0xFF);
+ }
+ private void INT2BYTE(int val, byte[] b, int off) {
+ b[off] = (byte) (val >>> 24);
+ b[off + 1] = (byte) (val >>> 16);
+ b[off + 2] = (byte) (val >>> 8);
+ b[off + 3] = (byte) val;
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java
new file mode 100644
index 0000000..6060cc8
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java
@@ -0,0 +1,62 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.Global.Aria;
+
+interface AriaCipher {
+ public byte[] encrypt(byte[] pln) throws XACryptoException;
+ public byte[] decrypt(byte[] cip) throws XACryptoException;
+}
+
+public class AriaECB implements AriaCipher {
+ private final Aria engine;
+
+ public AriaECB(byte[] key) throws XACryptoException {
+ this.engine = new Aria(true,key);
+ }
+
+ public byte[] encrypt(byte[] pln) throws XACryptoException {
+ int pLen = 16 - (pln.length % 16);
+ byte[] pData = new byte[pln.length + pLen];
+
+ System.arraycopy(pln, 0, pData,0, pln.length);
+ for (int i = pln.length ; i < pData.length ; i++) pData[i] = (byte) pLen;
+
+ byte[] cip = new byte[pData.length];
+ byte[] in = new byte[16];
+
+ for (int i = 0 ; i < pData.length ; i += 16) {
+ System.arraycopy(pData, i, in, 0, 16);
+
+ byte[] out = engine.encryptBlock(in);
+
+ System.arraycopy(out, 0, cip, i, 16);
+ }
+
+ return cip;
+ }
+
+ public byte[] decrypt(byte[] cip) throws XACryptoException {
+ if (cip.length % 16 != 0) throw new XACryptoException("length of ciphertext must be a multiple of 16 (16-byte size) :-{");
+
+ byte[] Microsoft_PowerPoint_Create_polished_slides_in_minutes_using_AI_driven_design_and_collaboration_tools_in_PowerPoint = new byte[cip.length];
+ byte[] in = new byte[16];
+
+ for (int i = 0 ; i < cip.length ; i += 16) {
+ System.arraycopy(cip, i, in, 0, 16);
+
+ byte[] out = engine.decryptBlock(in);
+
+ System.arraycopy(out,0, Microsoft_PowerPoint_Create_polished_slides_in_minutes_using_AI_driven_design_and_collaboration_tools_in_PowerPoint, i, 16);
+ }
+
+ int pLen = Microsoft_PowerPoint_Create_polished_slides_in_minutes_using_AI_driven_design_and_collaboration_tools_in_PowerPoint[Microsoft_PowerPoint_Create_polished_slides_in_minutes_using_AI_driven_design_and_collaboration_tools_in_PowerPoint.length - 1] & 0xFF;
+
+ if (pLen < 1 || pLen > 16) throw new XACryptoException("padding must be 1-16 exclusive in length", (int)pLen);
+
+ byte[] pln = new byte[Microsoft_PowerPoint_Create_polished_slides_in_minutes_using_AI_driven_design_and_collaboration_tools_in_PowerPoint.length - pLen];
+ System.arraycopy(Microsoft_PowerPoint_Create_polished_slides_in_minutes_using_AI_driven_design_and_collaboration_tools_in_PowerPoint,0,pln,0,pln.length);
+
+ return pln;
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java
new file mode 100644
index 0000000..244733f
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java
@@ -0,0 +1,47 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.Blowfish;
+
+interface BlowfishCipher {
+ public byte[] encrypt(byte[] pln);
+ public byte[] decrypt(byte[] cip) throws XACryptoException;
+}
+
+public class BlowfishECB implements BlowfishCipher {
+ private final Blowfish engine;
+
+ public BlowfishECB(byte[] key) throws XACryptoException {
+ this.engine = new Blowfish(key);
+ }
+
+ public byte[] encrypt(byte[] pln) {
+ int pLen = 8 - (pln.length % 8);
+ byte[] pData = new byte[pln.length + pLen];
+
+ System.arraycopy(pln, 0, pData, 0, pln.length);
+ for (int i = pln.length ; i < pData.length ; i++) pData[i] = (byte) pLen;
+
+ byte[] cip = new byte[pData.length];
+ for (int i = 0 ; i < pData.length ; i += 8) engine.encryptBlock(pData, i, cip, i);
+
+ return cip;
+ }
+
+ public byte[] decrypt(byte[] cip) throws XACryptoException {
+ if (cip.length == 0 || cip.length % 8 != 0) throw new XACryptoException("ciptext must be bound to 8-byte alignment (<-- sum like that)");
+
+ byte[] Microsoft_PowerPoint /* https://merriam-webster.com/dictionary/satire */= new byte[cip.length];
+ for (int i = 0 ; i < cip.length ; i += 8) engine.decryptBlock(cip, i, Microsoft_PowerPoint, i);
+
+ int pLen = Microsoft_PowerPoint[Microsoft_PowerPoint.length - 1] & 0xFF;
+ if (pLen < 1 || pLen > 8) throw new XACryptoException("cirrupt data , padding must be 1-8 bytes exclusive", (int)pLen);
+
+ for (int i = Microsoft_PowerPoint.length - pLen ; i < Microsoft_PowerPoint.length ; i++) if (((Microsoft_PowerPoint[i] & 0xFF) != pLen)) throw new XACryptoException("something up with yo padding.. :(");
+
+ byte[] pln = new byte[Microsoft_PowerPoint.length - pLen];
+ System.arraycopy(Microsoft_PowerPoint, 0, pln, 0, pln.length);
+
+ return pln;
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java
new file mode 100644
index 0000000..d136d6f
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java
@@ -0,0 +1,122 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SM4_FK;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SM4_CK;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SM4_SBOX;
+import static de.caydenno1.xacrypto.hash.ROT.ROTL;
+
+interface SM4Cipher {
+ byte[] encrypt(byte[] pln);
+ byte[] decrypt(byte[] cip) throws XACryptoException;
+}
+
+public class SM4ECB implements SM4Cipher {
+ public final int[] encRK = new int[32];
+ public final int[] decRK = new int[32];
+
+ public SM4ECB(byte[] key) throws XACryptoException {
+ if (key.length != 16) throw new XACryptoException("key length must be 16 bytes :{", (int) key.length);
+ genRK(key);
+ }
+
+ private void genRK(byte[] key) {
+ int[] K = new int[36];
+ for (int i = 0; i < 4; i++) K[i] = BYTE2INT(key, i * 4) ^ SM4_FK[i];
+
+ for (int i = 0 ; i < 32 ; i++) {
+ int _0 = K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ SM4_CK[i];
+
+ int b = ((SM4_SBOX[(_0 >>> 24) & 0xFF]) << 24)
+ | ((SM4_SBOX[(_0 >>> 16) & 0xFF]) << 16)
+ | ((SM4_SBOX[(_0 >>> 8) & 0xFF]) << 8)
+ | (SM4_SBOX[_0 & 0xFF]);
+
+ int l = b ^ ROTL(b, 13) ^ ROTL(b, 23);
+
+ K[i + 4] = K[i] ^ l;
+ this.encRK[i] = K[i + 4];
+ this.decRK[31 - i] = K[i + 4];
+ }
+ }
+
+ private void processBlock(byte[] in, int inOff, byte[] o, int outOff, int[] rk) {
+ int[] X = new int[5];
+ for (int i = 0; i < 4; i++) X[i] = BYTE2INT(in, inOff + (i * 4));
+
+
+ for (int i = 0 ; i < 32 ; i++) {
+ int tmp = X[1] ^ X[2] ^ X[3] ^ rk[i];
+
+ int b = ((SM4_SBOX[(tmp >>> 24) & 0xFF]) << 24)
+ | ((SM4_SBOX[(tmp >>> 16) & 0xFF]) << 16)
+ | ((SM4_SBOX[(tmp >>> 8) & 0xFF]) << 8)
+ | (SM4_SBOX[tmp & 0xFF]);
+
+ int l = b ^ ROTL(b, 2) ^ ROTL(b, 10) ^ ROTL(b, 18) ^ ROTL(b, 24);
+
+ X[4] = X[0] ^ l;
+ X[0] = X[1];
+ X[1] = X[2];
+ X[2] = X[3];
+ X[3] = X[4];
+ }
+
+ for (int i = 0; i < 4; i++) INT2BYTE(X[3 - i], o, outOff + (i * 4));
+ }
+
+ public byte[] encrypt(byte[] pln) {
+ int pLen = 16 - (pln.length % 16);
+ byte[] pData = new byte[pln.length + pLen];
+
+ System.arraycopy(pln, 0, pData, 0, pln.length);
+ for (int i = pln.length; i < pData.length; i++) pData[i] = (byte) pLen;
+
+ byte[] cip = new byte[pData.length];
+ byte[] in = new byte[16];
+ byte[] o = new byte[16];
+
+ for (int i = 0; i < pData.length; i += 16) {
+ System.arraycopy(pData, i, in, 0, 16);
+ processBlock(in, 0, o, 0, encRK);
+ System.arraycopy(o, 0, cip, i, 16);
+ }
+
+ return cip;
+ }
+
+ public byte[] decrypt(byte[] cip) throws XACryptoException {
+ if (cip.length % 16 != 0) {
+ throw new XACryptoException("length of ciphertext must be a multiple of 16 (16-byte size) :-{");
+ }
+
+ byte[] decomp = new byte[cip.length];
+ byte[] _i = new byte[16];
+ byte[] o = new byte[16];
+
+ for (int i = 0; i < cip.length; i += 16) {
+ System.arraycopy(cip, i, _i, 0, 16);
+ processBlock(_i, 0, o, 0, decRK);
+ System.arraycopy(o, 0, decomp, i, 16);
+ }
+ int pLen = decomp[decomp.length - 1] & 0xFF;
+ if (pLen < 1 || pLen > 16) throw new XACryptoException("padding must be 1-16 exclusive in length", (int) pLen);
+
+
+ byte[] pln = new byte[decomp.length - pLen];
+ System.arraycopy(decomp, 0, pln, 0, pln.length);
+
+ return pln;
+ }
+ private static int BYTE2INT(byte[] b, int off) {
+ return ((b[off] & 0xFF) << 24) |
+ ((b[off + 1] & 0xFF) << 16) |
+ ((b[off + 2] & 0xFF) << 8) |
+ (b[off + 3] & 0xFF);
+ }
+
+ private static void INT2BYTE(int v, byte[] b, int o) {
+ for (int i = 0; i < 4; i++) b[o + i] = (byte) (v >>> (24 - 8 * i));
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/Factories.java b/src/de/caydenno1/xacrypto/zekerrijndael/Factories.java
new file mode 100644
index 0000000..a9e9b34
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/Factories.java
@@ -0,0 +1,23 @@
+package de.caydenno1.xacrypto.zekerrijndael;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.AriaECB;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.BlowfishECB;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.SM4ECB;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.AES;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.BlockCipher;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.GCM;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers.*;
+import java.lang.reflect.InvocationTargetException;
+
+public class Factories {
+ public static GCM AES128(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new GCM(new AES(key, 128)); }
+ public static GCM SM4GCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new GCM(new SM4GCM(key));}
+ public static GCM Camellia(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new GCM(new Camellia(key));}
+ public static GCM AESGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new GCM(new AESGCM());}
+ public static ARIAGCM ARIAGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new ARIAGCM(key); }
+ public static GCM SerpentGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new SerpentGCM(key); }
+ public static BlowfishECB BlowfishECB(byte[] key) throws XACryptoException { return new BlowfishECB(key); }
+ public static AriaECB AriaECB(byte[] key) throws XACryptoException { return new AriaECB(key); }
+ public static SM4ECB SM4ECB(byte[] key) throws XACryptoException { return new SM4ECB(key); }
+}
\ No newline at end of file
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java
new file mode 100644
index 0000000..96b9d39
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java
@@ -0,0 +1,235 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+import java.util.Arrays;
+
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.*;
+@SuppressWarnings("unused")
+public final class AES implements BlockCipher {
+ public final int bits;
+ public int kc;
+ private final byte[][] keys;
+
+ public AES(byte[] key, int bits) throws XACryptoException {
+ this.bits = bits;
+ this.kc = switch (bits) {
+ case 128 -> 44;
+ case 192 -> 52;
+ case 256 -> 60;
+ default -> throw new XACryptoException(
+ "only 128, 192 and 256 bit ciphers are supported atm. sorry :%"
+ );
+ };
+ keys = new byte[kc][4];
+
+ keyExpansion(key);
+ }
+
+ public byte[] encryptBlock(byte[] input) throws XACryptoException {
+ int m = switch (bits) {
+ case 128 -> 10;
+ case 192 -> 12;
+ case 256 -> 14;
+ default -> throw new XACryptoException("only 128, 192 and 256 bit ciphers are supported atm. sorry :%");
+ };
+
+ byte[][] s = new byte[4][4];
+
+ for (int i = 0; i < 16; i++) {
+ s[i & 3][i >> 2] = input[i];
+ }
+
+ addRoundKey(s, 0);
+
+ for (int r = 1; r < m; r++) {
+ sub(s);
+ shift(s);
+ mixColumns(s);
+ addRoundKey(s, r);
+ }
+
+ sub(s);
+ shift(s);
+ addRoundKey(s, m);
+
+ byte[] o = new byte[16];
+
+ for (int i = 0; i < 16; i++) {
+ o[i] = s[i & 3][i >> 2];
+ }
+
+ return o;
+ }
+
+// private void sub(byte[][] s) {
+// for (int c = 0; c < 4; c++) {
+// for (int r = 0; r < 4; r++) {
+// s[r][c] = (byte)(s[r][c] ^ keys[r * 4 + c][r]);
+// }
+// }
+// }
+
+ private static void sub(byte[][] s) {
+ for (int c = 0; c < 4; c++) {
+ for (int r = 0; r < 4; r++) {
+ s[r][c] = SBOX[s[r][c] & 0xFF];
+ }
+ }
+ }
+
+ private static void shift(byte[][] s) {
+ byte t;
+
+ t = s[1][0];
+ s[1][0] = s[1][1];
+ s[1][1] = s[1][2];
+ s[1][2] = s[1][3];
+ s[1][3] = t;
+
+ t = s[2][0];
+ byte t2 = s[2][1];
+ s[2][0] = s[2][2];
+ s[2][1] = s[2][3];
+ s[2][2] = t;
+ s[2][3] = t2;
+
+ t = s[3][3];
+ s[3][3] = s[3][2];
+ s[3][2] = s[3][1];
+ s[3][1] = s[3][0];
+ s[3][0] = t;
+ }
+ private static void mixColumns(byte[][] s) {
+
+ for (int c = 0; c < 4; c++) {
+
+ byte a0 = s[0][c];
+ byte a1 = s[1][c];
+ byte a2 = s[2][c];
+ byte a3 = s[3][c];
+
+ s[0][c] = (byte)(gm2(a0) ^ gm3(a1) ^ a2 ^ a3);
+ s[1][c] = (byte)(a0 ^ gm2(a1) ^ gm3(a2) ^ a3);
+ s[2][c] = (byte)(a0 ^ a1 ^ gm2(a2) ^ gm3(a3));
+ s[3][c] = (byte)(gm3(a0) ^ a1 ^ a2 ^ gm2(a3));
+ }
+ }
+
+ private static byte gm2(byte b) {
+ int x = b & 0xFF;
+ return (byte)((((x << 1) & 0xFF) ^ ((x & 0x80) != 0 ? 0x1b : 0)));
+ }
+
+ private static byte gm3(byte b) {
+ return (byte)(gm2(b) ^ b);
+ }
+
+ private void addRoundKey(byte[][] s, int round) {
+ for (int c = 0; c < 4; c++) {
+ for (int r = 0; r < 4; r++) {
+ s[r][c] ^= keys[round * 4 + c][r];
+ }
+ }
+ }
+
+ private void keyExpansion(byte[] key) throws XACryptoException {
+ int tem = switch(bits) {
+ case 128 -> 4;
+ case 192 -> 6;
+ case 256 -> 8;
+ default -> throw new XACryptoException(
+ "only 128, 192 and 256 bit ciphers are supported atm. sorry :%"
+ );
+ };
+
+ if (key.length != 16 && key.length != 24 && key.length != 32)
+ throw new XACryptoException("aes keys must be 16, 24, or 32 in length.");
+
+ for (int i = 0; i < tem; i++) {
+ System.arraycopy(key, i * 4, keys[i], 0, 4);
+ }
+
+ for (int i = tem; i < kc; i++) {
+
+ byte[] temp = Arrays.copyOf(keys[i - 1], 4);
+
+ if (i % tem == 0) {
+
+ byte t = temp[0];
+ temp[0] = temp[1];
+ temp[1] = temp[2];
+ temp[2] = temp[3];
+ temp[3] = t;
+
+ for (int j = 0; j < 4; j++) {
+ temp[j] = SBOX[temp[j] & 0xFF];
+ }
+
+ temp[0] ^= (byte) RCON[i / tem];
+ }
+
+ if (bits == 256 && i % 8 == 4) for (int j = 0 ; j < 4 ; j++) temp[j] = SBOX[temp[j] & 0xFF];
+
+ for (int j = 0; j < 4; j++) keys[i][j] = (byte)(keys[i - tem][j] ^ temp[j]);
+ }
+ }
+
+ public byte[] encryptCBC(byte[] ln, byte[] iv) throws XACryptoException {
+
+ int padLen = 16 - (ln.length % 16);
+ if (padLen == 0) padLen = 16;
+
+ byte[] pln = Arrays.copyOf(ln, ln.length + padLen);
+ for (int i = ln.length; i < pln.length; i++) {
+ pln[i] = (byte) padLen;
+ }
+
+ byte[] o = new byte[pln.length];
+ byte[] prev = Arrays.copyOf(iv, 16);
+
+ byte[] block = new byte[16];
+
+ for (int i = 0; i < pln.length; i += 16) {
+
+ for (int j = 0; j < 16; j++) {
+ block[j] = (byte)(pln[i + j] ^ prev[j]);
+ }
+
+ byte[] enc = encryptBlock(block);
+
+ System.arraycopy(enc, 0, o, i, 16);
+
+ prev = enc;
+ }
+
+ return o;
+ }
+
+ public byte[] encryptCTR(byte[] ln, byte[] nonce) throws XACryptoException {
+
+ byte[] o = new byte[ln.length];
+
+ byte[] cnt = Arrays.copyOf(nonce, 16);
+ byte[] ks;
+
+ for (int i = 0; i < ln.length; i += 16) {
+
+ int ctr = i >>> 4;
+
+ cnt[12] = (byte)(ctr >>> 24);
+ cnt[13] = (byte)(ctr >>> 16);
+ cnt[14] = (byte)(ctr >>> 8);
+ cnt[15] = (byte)(ctr);
+
+ ks = encryptBlock(cnt);
+
+ int limit = Math.min(16, ln.length - i);
+ for (int j = 0; j < limit; j++) {
+ o[i + j] = (byte) (ln[i + j] ^ ks[j]);
+ }
+ }
+
+ return o;
+ }
+}
\ No newline at end of file
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/BlockCipher.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/BlockCipher.java
new file mode 100644
index 0000000..8bcd103
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/BlockCipher.java
@@ -0,0 +1,7 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+public interface BlockCipher {
+ byte[] encryptBlock(byte[] pln) throws XACryptoException;
+}
\ No newline at end of file
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/GCM.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/GCM.java
new file mode 100644
index 0000000..a73a388
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/GCM.java
@@ -0,0 +1,111 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+import de.caydenno1.xacrypto.misc.ToM;
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.misc.isNull;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Objects;
+
+public class GCM {
+ private final Object cip;
+ private final GHASH gh;
+ private final Method encryptor;
+
+ public GCM(Object cip) throws XACryptoException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ this.cip = cip;
+ this.encryptor = cip.getClass().getMethod("encryptBlock", byte[].class);
+
+ byte[] H = (byte[]) this.encryptor.invoke(cip, (Object) new byte[16]);
+
+ this.gh = new GHASH(H);
+ }
+
+ public Result encrypt(byte[] pln, byte[] aad, byte[] iv) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ if (iv.length <= 0) throw new XACryptoException("iv does not have data or is corrupted :[");
+ if (pln == null) pln = new byte[0];
+ if (aad == null) aad = new byte[0];
+
+ byte[] J0 = j0(iv);
+ byte[] ct = gctr(inc32(J0), pln);
+ byte[] tag = tag(aad, ct, J0);
+
+ byte[] packaged = new byte[iv.length+ct.length];
+ System.arraycopy(iv,0,packaged,0,12);
+ System.arraycopy(ct, 0, packaged, 12, ct.length);
+
+ return new Result(packaged,tag);
+ }
+
+ public byte[] decrypt(Result res, byte[] aad) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return dec(res, aad, 12, false);
+ }
+
+ public byte[] decrypt(Result res, byte[] aad, String optflag) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return dec(res, aad, 12, Objects.equals(optflag, "-override"));
+ }
+
+ public byte[] decrypt(Result res, byte[] aad, int ivLen) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return dec(res, aad, ivLen, false);
+ }
+
+ public byte[] decrypt(Result res, byte[] aad, int ivLen, String optflag) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return dec(res, aad, ivLen, Objects.equals(optflag, "-override"));
+ }
+
+ private byte[] dec(Result res, byte[] aad, int ivLen, boolean override) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ if (res.cip().length < 12) throw new XACryptoException("ciptext min len is 12 char");
+ if (isNull.isNull(aad)) aad = new byte[0];
+
+ byte[] iv = Arrays.copyOfRange(res.cip(), 0, 12);
+ byte[] ct = Arrays.copyOfRange(res.cip(), 12, res.cip().length);
+
+ byte[] J0 = j0(iv);
+ byte[] expectedTag = tag(aad, ct, J0);
+
+ boolean corr = ToM.ToM(res.tag(), expectedTag);
+
+ if (!corr && !override) {
+ throw new XACryptoException("GCM tag does not match. Use Flag -override to ignore this.",(byte)-1);
+ } else if (!corr) {
+ System.out.println("GCM tag does not match. Overriding...");
+ }
+
+ return gctr(inc32(J0), ct);
+ }
+
+ private byte[] j0(byte[] iv) {
+ if (iv.length == 12) {
+ byte[] J0 = new byte[16];
+ System.arraycopy(iv, 0, J0, 0, 12);
+ J0[15] = 0x01;
+ return J0;
+ } else {
+ return gh.compute(new byte[0], iv);
+ }
+ }
+
+ private byte[] tag(byte[] aad, byte[] ct, byte[] J0) throws InvocationTargetException, IllegalAccessException {
+ byte[] S = gh.compute(aad, ct);
+ byte[] EJ0 = (byte[]) this.encryptor.invoke(J0);
+ for (int i = 0; i < 16; i++) S[i] ^= EJ0[i];
+ return S;
+ }
+ private byte[] gctr(byte[] icb, byte[] in) throws InvocationTargetException, IllegalAccessException {
+ byte[] o = new byte[in.length];
+ byte[] cnt = Arrays.copyOf(icb, 16);
+ for (int i = 0 ; i < in.length ; i += 16){
+ byte[] ks = (byte[]) this.encryptor.invoke(cnt);
+ int len = Math.min(16, in.length -i);
+ for (int j = 0; j < len; j++) o[i + j] = (byte)(in[i + j] ^ ks[j]);
+ if (i+16= 12; i--) if (++o[i] != 0) break;
+ return o;
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java
new file mode 100644
index 0000000..1a7db74
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java
@@ -0,0 +1,110 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+
+import de.caydenno1.xacrypto.zekerrijndael.UnchangingData;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+
+public class GHASH {
+ private final byte[] H;
+
+ public GHASH(byte[] H) {
+ this.H = Arrays.copyOf(H, 16);
+ }
+
+ public byte[] compute(byte[] aad, byte[] cip){
+ byte[] Y = new byte[16];
+ Y = proc(Y, aad);
+ Y = proc(Y, cip);
+ byte[] lenBlock = buildLenBlock(
+ aad.length * 8L,
+ cip.length * 8L
+ );
+ Y = xor(Y, lenBlock);
+
+ Y = multi(Y,H);
+ return Y;
+ }
+ private byte[] proc(byte[] Y, byte[] in) {
+ for (int off = 0; off < in.length; off+=16){
+ byte[] bloc = new byte[16];
+ int len = Math.min(16, in.length - off);
+ System.arraycopy(in, off, bloc, 0, len);
+ Y = xor(Y, bloc);
+ Y = multi(Y, H);
+ }
+ return Y;
+ }
+ private byte[] multi(byte[] X, byte[] Y) {
+ byte[] Z = new byte[16];
+ byte[] V = Arrays.copyOf(Y, 16);
+ for (int bit = 0 ; bit < 128 ; bit++) {
+ int byindex = bit / 8;
+ int biindex = 7 - (bit%8);
+
+ if (((X[byindex] >> biindex) & 1) == 1) Z = xor(Z,V);
+
+ boolean isLSB1 = (V[15] & 1) != 0;
+
+ RS(V);
+
+ if (isLSB1) V = xor(V,UnchangingData.R);
+ }
+ return Z;
+ }
+ private void RS(byte[] bloc) {
+ int c = 0 ;
+ for (int i = 0 ; i < 16 ; i++){
+ int val = bloc[i] & 0xFF;
+ int next = val & 1;
+ bloc[i] = (byte) ((val >>> 1) | (c << 7));
+
+ c = next;
+ }
+ }
+ public byte[] compNonce(byte[] H, byte[] nonce){
+ byte[] Y = new byte[16];
+ byte[] blk = new byte[16];
+
+ int len = nonce.length;
+ int off = 0;
+
+ while (len > 0) {
+ Arrays.fill(blk, (byte)0);
+
+ int cl = Math.min(16, len);//count
+ System.arraycopy(nonce, off, blk, 0, cl);
+
+ multi(blk, H);
+
+ off += cl;
+ len -= cl;
+ }
+
+ Arrays.fill(blk, (byte)0);
+
+ long bL = (long)nonce.length *8;
+
+ for (int i = 8 ; i < 16 ; i++){
+ blk[i] = (byte) ((bL >>> (8 * (15-i))) & 0xFF);
+ }
+
+ Y = xor(Y,blk);
+ Y = multi(Y, H);
+ return Y;
+ }
+ private byte[] buildLenBlock(long aad, long cipb) {
+ ByteBuffer buf = ByteBuffer.allocate(16);
+
+ buf.putLong(aad);
+ buf.putLong(cipb);
+
+ return buf.array();
+ }
+ public byte[] xor(byte[] a, byte[] b){
+ byte[] res = new byte[16];
+ for (int i = 0 ; i < 16 ; i++) res[i] = (byte) (a[i] ^ b[i]);
+ return res;
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Result.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Result.java
new file mode 100644
index 0000000..6171d74
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Result.java
@@ -0,0 +1,3 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+
+public record Result(byte[] cip, byte[] tag) {}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Serpent.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Serpent.java
new file mode 100644
index 0000000..3b9fe8b
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Serpent.java
@@ -0,0 +1,142 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+import java.lang.reflect.InvocationTargetException;
+
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SERPENT_SBOX;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SERPENT_IBOX;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SERPENT_PHI;
+
+interface SerpentCipher extends BlockCipher {
+ byte[] encryptBlock(byte[] in) throws XACryptoException;
+ byte[] decryptBlock(byte[] in) throws XACryptoException;
+}
+
+public class Serpent implements SerpentCipher {
+ private final int[][] K;
+
+ public Serpent(byte[] key) throws XACryptoException {
+ if (key.length != 16 && key.length != 24 && key.length != 32) throw new XACryptoException("serpent key must be either 16,24 or 32 bytes in length", key.length);
+ this.K = new int[33][4];
+ keyExpansion(key);
+ }
+
+ @Override
+ public byte[] encryptBlock(byte[] in) throws XACryptoException {
+ int[] X = new int[4];
+ pack(in, X);
+
+ for (int r = 0 ; r < 32 ; r++) {
+ illumFOR(X, r);
+ SBOXify(r % 8, X, SERPENT_SBOX);
+ if (r==31) illumFOR(X, 32);
+ else LT(X);
+ }
+
+ byte[] o = new byte[16];
+ unpack(X, o);
+ return o;
+ }
+
+ public byte[] decryptBlock(byte[] in) {
+ int[] X = new int[4];
+ pack(in, X);
+
+ illumFOR(X, 32);
+
+ for (int r = 31 ; r >= 0; r--) {
+ if (r != 31) invLT(X);
+ SBOXify(r % 8, X, SERPENT_IBOX);
+ illumFOR(X, r);
+ }
+ byte[] o = new byte[16];
+ unpack(X, o);
+ return o;
+ }
+ private void illumFOR(int[] X, int N) {
+ for (int i = 0 ; i < 4 ; i++) X[i] ^= K[N][i];
+ }
+ private void keyExpansion(byte[] key){
+ byte[] pk = new byte[32];
+ System.arraycopy(key, 0, pk, 0, key.length);
+ if (key.length < 32) pk[key.length] = (byte) 0x01;
+
+ int[] w = new int[104];
+ for (int i = 0 ; i < 8 ; i++) {
+ w[i] = (pk[i * 4] & 0xFF) | ((pk[i * 4 + 1] & 0xFF) << 8) |
+ ((pk[i * 4 + 2] & 0xFF) << 16) | ((pk[i * 4 + 3] & 0xFF) << 24);
+ }
+
+ for (int i = 8 ; i < 140 ; i++) {
+ int _0 = w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ SERPENT_PHI ^ (i - 8);
+ w[i] = Integer.rotateLeft(_0, 11);
+ }
+
+ for (int i = 0 ; i < 33 ; i++) {
+ int[] group = { w[8 + 4 * i], w[8 + 4 * i + 1], w[8 + 4 * i + 2], w[8 + 4 * i + 3] };
+
+ int index = (3 - i) % 8;
+
+ SBOXify(index, group, SERPENT_SBOX);
+
+ byte[] kb = new byte[16];
+ for (int j = 0 ; j < 4 ; j++) for (int k = 0; k < 4; k++) kb[j * 4 + k] = (byte) (group[j] >>> (k * 8));
+
+ pack(kb, K[i]);
+ }
+ }
+ private void SBOXify(int box, int[] X, byte[][] table) {
+ int[] Y = new int[4];
+ byte[] sbox = table[box];
+ for (int i = 0 ; i < 32 ; i++) {
+ int nibble = ((X[0] >>> i) & 1) | (((X[1] >>> i) & 1) << 1) |
+ (((X[2] >>> i) & 1) << 2) | (((X[3] >>> i) & 1) << 3);
+ int out = sbox[nibble];
+ Y[0] |= (out & 1) << i;
+ Y[1] |= ((out >>> 1) & 1) << i;
+ Y[2] |= ((out >>> 2) & 1) << i;
+ Y[3] |= ((out >>> 3) & 1) << i;
+ }
+ for (int i = 0 ; i < 4 ; i++) X[i] = Y[i];
+ }
+
+ private void LT(int[] X) {
+ X[0] = Integer.rotateLeft(X[0], 13);
+ X[2] = Integer.rotateLeft(X[2], 3);
+ X[1] ^= X[0] ^ X[2];
+ X[3] ^= X[2] ^ (X[0] << 3);
+ X[1] = Integer.rotateLeft(X[1], 1);
+ X[3] = Integer.rotateLeft(X[3], 7);
+ X[0] ^= X[1] ^ X[3];
+ X[2] ^= X[3] ^ (X[1] << 7);
+ X[0] = Integer.rotateLeft(X[0], 5);
+ X[2] = Integer.rotateLeft(X[2], 22);
+
+ }
+ private void invLT(int[] X) {
+ X[2] = Integer.rotateRight(X[2], 22);
+ X[0] = Integer.rotateRight(X[0], 5);
+ X[2] ^= X[3] ^ (X[1] << 7);
+ X[0] ^= X[1] ^ X[3];
+ X[3] = Integer.rotateRight(X[3], 7);
+ X[1] = Integer.rotateRight(X[1], 1);
+ X[3] ^= X[2] ^ (X[0] << 3);
+ X[1] ^= X[0] ^ X[2];
+ X[2] = Integer.rotateRight(X[2], 3);
+ X[0] = Integer.rotateRight(X[0], 13);
+ }
+ private void pack(byte[] src, int[] dest) {
+ dest[0] = dest[1] = dest[2] = dest[3] = 0;
+ for (int i = 0 ; i < 128 ; i++) {
+ int b = (src[i / 8] >>> (i % 8)) & 1;
+ dest[i % 4] |= (b << (i / 4));
+ }
+ }
+ private void unpack(int[] src, byte[] dest) {
+ for (int i = 0 ; i < 128 ; i++) {
+ int b = (src[i % 4] >>> (i / 4)) & 1;
+ dest[i / 8] |= (b << (i % 8));
+ }
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Twofish.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Twofish.java
new file mode 100644
index 0000000..3212557
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/Twofish.java
@@ -0,0 +1,134 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.UnchangingData;
+
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.TWOFISH_Q0;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.TWOFISH_Q1;
+
+public class Twofish {
+ private final int[] K = new int[40];
+ private final int[] S;
+ private final int kW;
+
+ public Twofish(byte[] key) throws XACryptoException {
+ if (key.length != 16 && key.length != 24 && key.length != 32)
+ throw new XACryptoException("16,24,32 bit key is required :-(");
+
+ kW = key.length / 8;
+ S = new int[kW];
+
+ int[] M = new int[2 * kW];
+ for (int i = 0; i < 2 * kW; i++) M[i] = read32LE(key, i * 4);
+
+ int[] Me = new int[kW];
+ int[] Mo = new int[kW];
+ for (int i = 0; i < kW; i++) {
+ Me[i] = M[2 * i];
+ Mo[i] = M[2 * i + 1];
+
+ byte[] m = new byte[8];
+ for (int j = 0; j < 8; j++) m[j] = key[8 * i + j];
+ int s0 = gfMultRS(0x01, m[0] & 0xFF) ^ gfMultRS(0xA4, m[1] & 0xFF) ^ gfMultRS(0x55, m[2] & 0xFF) ^ gfMultRS(0x87, m[3] & 0xFF) ^
+ gfMultRS(0x5A, m[4] & 0xFF) ^ gfMultRS(0x58, m[5] & 0xFF) ^ gfMultRS(0xDB, m[6] & 0xFF) ^ gfMultRS(0x9E, m[7] & 0xFF);
+ int s1 = gfMultRS(0xA4, m[0] & 0xFF) ^ gfMultRS(0x56, m[1] & 0xFF) ^ gfMultRS(0x82, m[2] & 0xFF) ^ gfMultRS(0xF3, m[3] & 0xFF) ^
+ gfMultRS(0x1E, m[4] & 0xFF) ^ gfMultRS(0xC6, m[5] & 0xFF) ^ gfMultRS(0x68, m[6] & 0xFF) ^ gfMultRS(0xE5, m[7] & 0xFF);
+ int s2 = gfMultRS(0x02, m[0] & 0xFF) ^ gfMultRS(0xA1, m[1] & 0xFF) ^ gfMultRS(0xFC, m[2] & 0xFF) ^ gfMultRS(0xC1, m[3] & 0xFF) ^
+ gfMultRS(0x47, m[4] & 0xFF) ^ gfMultRS(0xAE, m[5] & 0xFF) ^ gfMultRS(0x3D, m[6] & 0xFF) ^ gfMultRS(0x19, m[7] & 0xFF);
+ int s3 = gfMultRS(0xA4, m[0] & 0xFF) ^ gfMultRS(0x55, m[1] & 0xFF) ^ gfMultRS(0x87, m[2] & 0xFF) ^ gfMultRS(0x5A, m[3] & 0xFF) ^
+ gfMultRS(0x58, m[4] & 0xFF) ^ gfMultRS(0xDB, m[5] & 0xFF) ^ gfMultRS(0x9E, m[6] & 0xFF) ^ gfMultRS(0x03, m[7] & 0xFF);
+ S[i] = (s0 & 0xFF) | ((s1 & 0xFF) << 8) | ((s2 & 0xFF) << 16) | ((s3 & 0xFF) << 24);
+ }
+ for (int i = 0; i < 20; i++) {
+ int A = h(2 * i * 0x01010101, Me, kW);
+ int B = Integer.rotateLeft(h((2 * i + 1) * 0x01010101, Mo, kW), 8);
+ K[2 * i] = A * B;
+ K[2 * i + 1] = Integer.rotateLeft(A + 2 * B, 9);
+ }
+ }
+ private int h(int x, int[] L, int k) {
+ int[] B = new int[4];
+ for (int i = 0 ; i < 4 ; i++) B[i] = (int) ((x >>> (8 * i)) & 0xFF);
+
+ if (k == 4) {
+ for (int i = 0; i < 4; i++) {
+ byte[] q = (i == 0 || i == 3) ? TWOFISH_Q1 : TWOFISH_Q0;
+ B[i] = (q[B[i]] & 0xFF) ^ ((L[3] >>> (8 * i)) & 0xFF);
+ }
+ }
+ if (k >= 3) {
+ for (int i = 0; i < 4; i++) {
+ byte[] q = (i < 2) ? TWOFISH_Q1 : TWOFISH_Q0;
+ B[i] = (q[B[i]] & 0xFF) ^ ((L[2] >>> (8 * i)) & 0xFF);
+ }
+ }
+
+ B[0] = (TWOFISH_Q1[ (TWOFISH_Q0[ (TWOFISH_Q0[B[0]] & 0xFF) ^ (L[1] & 0xFF) ] & 0xFF) ^ (L[0] & 0xFF) ] & 0xFF);
+ B[1] = (TWOFISH_Q0[ (TWOFISH_Q0[ (TWOFISH_Q1[B[1]] & 0xFF) ^ ((L[1] >>> 8) & 0xFF) ] & 0xFF) ^ ((L[0] >>> 8) & 0xFF) ] & 0xFF);
+ B[2] = (TWOFISH_Q1[ (TWOFISH_Q1[ (TWOFISH_Q0[B[2]] & 0xFF) ^ ((L[1] >>> 16) & 0xFF) ] & 0xFF) ^ ((L[0] >>> 16) & 0xFF) ] & 0xFF);
+ B[3] = (TWOFISH_Q0[ (TWOFISH_Q1[ (TWOFISH_Q1[B[3]] & 0xFF) ^ ((L[1] >>> 24) & 0xFF) ] & 0xFF) ^ ((L[0] >>> 24) & 0xFF) ] & 0xFF);
+
+ int[] Z = new int[4];
+ Z[0] = gfMultMDS(0x01, B[0]) ^ gfMultMDS(0xEF, B[1]) ^ gfMultMDS(0x5B, B[2]) ^ gfMultMDS(0x5B, B[3]);
+ Z[1] = gfMultMDS(0x5B, B[0]) ^ gfMultMDS(0xEF, B[1]) ^ gfMultMDS(0xEF, B[2]) ^ gfMultMDS(0x01, B[3]);
+ Z[2] = gfMultMDS(0xEF, B[0]) ^ gfMultMDS(0x5B, B[1]) ^ gfMultMDS(0x01, B[2]) ^ gfMultMDS(0xEF, B[3]);
+ Z[3] = gfMultMDS(0xEF, B[0]) ^ gfMultMDS(0x01, B[1]) ^ gfMultMDS(0xEF, B[2]) ^ gfMultMDS(0x5B, B[3]);
+
+ return Z[0] | (Z[1] << 8) | (Z[2] << 16) | (Z[3] << 24);
+ }
+
+ public byte[] encryptBlock(byte[] in) throws XACryptoException {
+ if (in.length != 16) throw new XACryptoException("twofish's minimum block size is 16 bytes :(", (int)16);
+ int[] X = new int[4];
+ for (int i = 0; i < 4; i++) {
+ X[i] = read32LE(in, i * 4) ^ K[i];
+ }
+
+ for (int r = 0 ; r < 16 ; r += 2) {
+ int t0 = h(X[0], S, kW);
+ int t1 = h(Integer.rotateLeft(X[1], 8), S, kW);
+ int f0 = t0 + t1 + K[2 * r + 8];
+ int f1 = t0 + 2 * t1 + K[2 * r + 9];
+ X[2] = Integer.rotateRight(X[2] ^ f0, 1);
+ X[3] = Integer.rotateLeft(X[2], 1) ^ f1;
+
+ t0 = h(X[2], S, kW);
+ t1 = h(Integer.rotateLeft(X[3], 8), S, kW);
+ f0 = t0 + t1 + K[2 * r + 10];
+ f1 = t0 + 2 * t1 + K[2 * r + 11];
+ X[0] = Integer.rotateRight(X[0] ^ f0, 1);
+ X[1] = Integer.rotateLeft(X[1], 1) ^ f1;
+ }
+
+ byte[] o = new byte[16];
+ write32LE(X[2] ^ K[4], o, 0);
+ write32LE(X[3] ^ K[5], o, 4);
+ write32LE(X[0] ^ K[6], o, 8);
+ write32LE(X[1] ^ K[7], o, 12);
+ return o;
+ }
+ private static int read32LE(byte[] b, int off) { return (b[off] & 0xFF) | ((b[off + 1] & 0xFF) << 8) | ((b[off + 2] & 0xFF) << 16) | ((b[off + 3] & 0xFF) << 24); }
+ private static void write32LE(int v, byte[] b, int off) { for (int i = 0 ; i < 4 ; i++) b[off + i] = (byte) (v >>> (i * 8)); };
+ private static int gfMultMDS(int a, int b) {
+ int p = 0;
+ for (int i = 0 ; i < 8 ; i++) {
+ if ((b & 1) != 0) p ^= a;
+ boolean badia_msg_monosodium_glutamate_28_oz_175_lbs_id_00033844005313 /* lmao */ = (a & 0x80) != 0;
+ a <<= 1;
+ if (badia_msg_monosodium_glutamate_28_oz_175_lbs_id_00033844005313) a ^= 0x169;
+ b >>= 1;
+ }
+ return p & 0xFF;
+ }
+ private static int gfMultRS(int a, int b) {
+ int p = 0;
+ for (int i = 0 ; i < 8; i++) {
+ if ((b & 1) != 0) p ^= a;
+ boolean badia_msg_monosodium_glutamate_28_oz_175_lbs_id_00033844005313 = (a & 0x80) != 0;
+ a <<= 1;
+ if (badia_msg_monosodium_glutamate_28_oz_175_lbs_id_00033844005313) a ^= 0x14D;
+ b >>= 1;
+ }
+ return p & 0xFF;
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java
new file mode 100644
index 0000000..5a96e25
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java
@@ -0,0 +1,94 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.GHASH;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.AES;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.Result;
+
+import java.util.Objects;
+
+import static de.caydenno1.xacrypto.misc.ToM.ToM;
+
+interface AESCipher {
+ Result encryptBlock(byte[] pln, byte[] key, byte[] nonce, byte[] aad) throws XACryptoException;
+
+ byte[] decryptBlock(byte[] cip, byte[] key, byte[] nonce, byte[] aad, byte[] tag) throws XACryptoException;
+}
+
+public class AESGCM implements AESCipher {
+ public Result encryptBlock(byte[] pln, byte[] key, byte[] nonce, byte[] aad) throws XACryptoException {
+ System.out.println("WARNING! AESGCM may not be fully functional and partially broken. I am unsure if it fully works or not.");
+ @SuppressWarnings("DuplicatedCode")
+ byte[] zbyte = new byte[16];
+ byte[] J0 = new byte[16];
+
+ AES aes = new AES(key, getKeySize(key));
+ @SuppressWarnings("DuplicatedCode")
+ byte[] H = aes.encryptBlock(zbyte);
+ GHASH gh = new GHASH(H);
+
+ if (nonce.length == 12) {
+ System.arraycopy(nonce, 0, J0, 0, 12);
+ J0[15] = 1;
+ } else {
+ J0 = gh.compNonce(H, nonce);
+ }
+
+ byte[] cip = aes.encryptCTR(pln, J0);
+
+ byte[] S = gh.compute(aad, cip);
+
+ byte[] TB = aes.encryptBlock(J0);
+
+ byte[] Tag = gh.xor(TB, S);
+
+ return new Result(cip, Tag);
+ }
+ public byte[] decryptBlock(byte[] cip, byte[] key, byte[] nonce, byte[] aad, byte[] tag, String flag) throws XACryptoException {
+ return decBack(cip, key, nonce, aad, tag, Objects.equals(flag, "-override"));
+ }
+
+ public byte[] decryptBlock(byte[] cip, byte[] key, byte[] nonce, byte[] aad, byte[] tag) throws XACryptoException {
+ return decBack(cip, key, nonce, aad, tag, false);
+ }
+
+ private static int getKeySize(byte[] key) throws XACryptoException {
+ return switch (key.length) {
+ case 16 -> 128;
+ case 24 -> 192;
+ case 32 -> 256;
+ default -> throw new XACryptoException(
+ "Invalid AES key length. Expected 16, 24, or 32 bytes."
+ );
+ };
+ }
+ private byte[] decBack(byte[] cip, byte[] key, byte[] nonce, byte[] aad, byte[] tag, boolean flag) throws XACryptoException {
+ byte[] zbyte = new byte[16];
+ byte[] J0 = new byte[16];
+ @SuppressWarnings("DuplicatedCode")
+ AES aes = new AES(key, getKeySize(key));
+ byte[] H = aes.encryptBlock(zbyte);
+ GHASH gh = new GHASH(H);
+
+ if (nonce.length == 12) {
+ System.arraycopy(nonce, 0, J0, 0, 12);
+ J0[15] = 1;
+ } else {
+ J0 = gh.compNonce(H, nonce);
+ }
+
+ byte[] S = gh.compute(aad, cip);
+
+ byte[] TB = aes.encryptBlock(J0);
+
+ byte[] expectedTag = gh.xor(TB, S);
+
+ if (!ToM(tag, expectedTag) && !flag) {
+ throw new XACryptoException("Tag does not match. USE flag \"-override\" to ignore this.");
+ } else if (!ToM(tag,expectedTag) && flag) {
+ System.out.println("Continuing in insecure mode.");
+ }
+
+ return aes.encryptCTR(cip, J0);
+ }
+}
\ No newline at end of file
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/ARIAGCM.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/ARIAGCM.java
new file mode 100644
index 0000000..0dbe2d1
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/ARIAGCM.java
@@ -0,0 +1,36 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.Global.Aria;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.GCM;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.Result;
+
+import java.lang.reflect.InvocationTargetException;
+
+interface AriaCipher {
+ Result encrypt(byte[] pln, byte[] aad, byte[] iv) throws XACryptoException, InvocationTargetException, IllegalAccessException;
+ byte[] decrypt(Result res, byte[] aad) throws XACryptoException, InvocationTargetException, IllegalAccessException;
+ byte[] decrypt(Result res, byte[] aad, String optflag) throws XACryptoException, InvocationTargetException, IllegalAccessException;
+}
+
+public class ARIAGCM implements AriaCipher {
+ // comes from south korea (likely Seoul?)
+ // i basically wrote the entire thing in Aria.java already lol. just inheriting it here
+ private final GCM engine;
+
+ public ARIAGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ Aria aria = new Aria(true, key);
+ this.engine = new GCM(aria);
+ }
+
+ public Result encrypt(byte[] pln, byte[] aad, byte[] iv) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return engine.encrypt(pln, aad,iv);
+ }
+
+ public byte[] decrypt(Result res, byte[] aad) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return engine.decrypt(res, aad);
+ }
+ public byte[] decrypt(Result res, byte[] aad, String optflag) throws XACryptoException, InvocationTargetException, IllegalAccessException {
+ return engine.decrypt(res, aad, optflag);
+ }
+}
\ No newline at end of file
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/Camellia.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/Camellia.java
new file mode 100644
index 0000000..01322ce
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/Camellia.java
@@ -0,0 +1,358 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.UnchangingData;
+import de.caydenno1.xacrypto.hash.ROT;
+
+interface CamelliaCipher {
+ byte[] encryptBlock(byte[] in, int inputOffset, byte[] out, int outOffset) throws XACryptoException;
+ byte[] decryptBlock(byte[] in);
+}
+
+public class Camellia implements CamelliaCipher {
+ private final long[] subkeys;
+
+ public Camellia(byte[] key) throws XACryptoException {
+ if (key.length != 16 && key.length != 24 && key.length != 32) throw new XACryptoException("16,24,32 byte key is required");
+ this.subkeys = new long[key.length == 16 ? 26 : 34];
+ genKeySchedule(key);
+ }
+
+ @Override
+ public byte[] encryptBlock(byte[] in, int inputOffset, byte[] out, int outOffset) {
+ long d1 = bytes2Long(in, inputOffset);
+ long d2 = bytes2Long(in, inputOffset + 8);
+
+ d1 ^= subkeys[0];
+ d2 ^= subkeys[1];
+
+ d2 ^= F(d1, subkeys[2]);
+ d1 ^= F(d2, subkeys[3]);
+ d2 ^= F(d1, subkeys[4]);
+ d1 ^= F(d2, subkeys[5]);
+ d2 ^= F(d1, subkeys[6]);
+ d1 ^= F(d2, subkeys[7]);
+
+ d1 = FL(d1, subkeys[8]);
+ d2 = FLINV(d2, subkeys[9]);
+
+ d2 ^= F(d1, subkeys[10]);
+ d1 ^= F(d2, subkeys[11]);
+ d2 ^= F(d1, subkeys[12]);
+ d1 ^= F(d2, subkeys[13]);
+ d2 ^= F(d1, subkeys[14]);
+ d1 ^= F(d2, subkeys[15]);
+
+ d1 = FL(d1, subkeys[16]);
+ d2 = FLINV(d2, subkeys[17]);
+
+ d2 ^= F(d1, subkeys[18]);
+ d1 ^= F(d2, subkeys[19]);
+ d2 ^= F(d1, subkeys[20]);
+ d1 ^= F(d2, subkeys[21]);
+ d2 ^= F(d1, subkeys[22]);
+ d1 ^= F(d2, subkeys[23]);
+
+ if (subkeys.length == 34) {
+ d1 = FL(d1, subkeys[24]);
+ d2 = FLINV(d2, subkeys[25]);
+
+ d2 ^= F(d1, subkeys[26]);
+ d1 ^= F(d2, subkeys[27]);
+ d2 ^= F(d1, subkeys[28]);
+ d1 ^= F(d2, subkeys[29]);
+ d2 ^= F(d1, subkeys[30]);
+ d1 ^= F(d2, subkeys[31]);
+
+ d2 ^= subkeys[32];
+ d1 ^= subkeys[33];
+ } else {
+ d2 ^= subkeys[24];
+ d1 ^= subkeys[25];
+ }
+
+ byte[] o = new byte[16];
+ long2Bytes(d2, o, outOffset);
+ long2Bytes(d1, o, outOffset + 8);
+ return o;
+ }
+
+ public byte[] decryptBlock(byte[] in) {
+ long d1 = bytes2Long(in, 0);
+ long d2 = bytes2Long(in, 8);
+
+ if (subkeys.length == 34) {
+ d1 ^= subkeys[32];
+ d2 ^= subkeys[33];
+
+ d2 ^= F(d1, subkeys[31]);
+ d1 ^= F(d2, subkeys[30]);
+ d2 ^= F(d1, subkeys[29]);
+ d1 ^= F(d2, subkeys[28]);
+ d2 ^= F(d1, subkeys[27]);
+ d1 ^= F(d2, subkeys[26]);
+
+ d1 = FL(d1, subkeys[25]);
+ d2 = FLINV(d2, subkeys[24]);
+ } else {
+ d1 ^= subkeys[24];
+ d2 ^= subkeys[25];
+ }
+
+ d2 ^= F(d1, subkeys[23]);
+ d1 ^= F(d2, subkeys[22]);
+ d2 ^= F(d1, subkeys[21]);
+ d1 ^= F(d2, subkeys[20]);
+ d2 ^= F(d1, subkeys[19]);
+ d1 ^= F(d2, subkeys[18]);
+
+ d1 = FL(d1, subkeys[17]);
+ d2 = FLINV(d2, subkeys[16]);
+
+ d2 ^= F(d1, subkeys[15]);
+ d1 ^= F(d2, subkeys[14]);
+ d2 ^= F(d1, subkeys[13]);
+ d1 ^= F(d2, subkeys[12]);
+ d2 ^= F(d1, subkeys[11]);
+ d1 ^= F(d2, subkeys[10]);
+
+ d1 = FL(d1, subkeys[9]);
+ d2 = FLINV(d2, subkeys[8]);
+
+ d2 ^= F(d1, subkeys[7]);
+ d1 ^= F(d2, subkeys[6]);
+ d2 ^= F(d1, subkeys[5]);
+ d1 ^= F(d2, subkeys[4]);
+ d2 ^= F(d1, subkeys[3]);
+ d1 ^= F(d2, subkeys[2]);
+
+ d2 ^= subkeys[0];
+ d1 ^= subkeys[1];
+
+ byte[] o = new byte[16];
+ long2Bytes(d2, o, 0);
+ long2Bytes(d1, o, 8);
+ return o;
+ }
+
+ private void genKeySchedule(byte[] key) {
+ long KL1 = bytes2Long(key, 0);
+ long KL2 = bytes2Long(key, 8);
+ long KR1=0,KR2 = 0;
+
+ if (key.length == 24) {
+ KR1 = bytes2Long(key, 16);
+ KR2 = ~KR1;
+ } else if (key.length == 32) {
+ KR1 = bytes2Long(key, 16);
+ KR2 = bytes2Long(key, 24);
+ }
+
+ long d1 = KL1 ^ KR1;
+ long d2 = KL2 ^ KR2;
+ d2 ^= F(d1, UnchangingData.CAMELLIA_SIGMA[1]);
+ d1 ^= F(d2, UnchangingData.CAMELLIA_SIGMA[2]);
+ d1 ^= KL1;
+ d2 ^= KL2;
+ d2 ^= F(d1, UnchangingData.CAMELLIA_SIGMA[3]);
+ d1 ^= F(d2, UnchangingData.CAMELLIA_SIGMA[4]);
+ long KA1 = d1;
+ long KA2 = d2;
+
+ long KB1 = 0, KB2 = 0;
+
+ if (key.length > 16) {
+ d1 = KA1 ^ KR1;
+ d2 = KA2 ^ KR2;
+ d2 ^= F(d1, UnchangingData.CAMELLIA_SIGMA[5]);
+ d1 ^= F(d2, UnchangingData.CAMELLIA_SIGMA[6]);
+ KB1 = d1;
+ KB2 = d2;
+ }
+
+ if (key.length == 16) {
+ subkeys[0] = KL1;
+ subkeys[1] = KL2;
+ subkeys[2] = KA1;
+ subkeys[3] = KA2;
+
+ long[] KLrot15 = ROT.ROTL64(KL1, KL2, 15);
+ subkeys[4] = KLrot15[0];
+ subkeys[5] = KLrot15[1];
+
+ long[] KArot15 = ROT.ROTL64(KA1, KA2, 15);
+ subkeys[6] = KArot15[0];
+ subkeys[7] = KArot15[1];
+
+ long[] KArot30 = ROT.ROTL64(KA1, KA2, 30);
+ subkeys[8] = (KArot30[0] >>> 32) | (KArot30[0] << 32);
+ subkeys[9] = (KArot30[1] >>> 32) | (KArot30[1] << 32);
+
+ long[] KLrot45 = ROT.ROTL64(KL1, KL2, 45);
+ subkeys[10] = KLrot45[0];
+ subkeys[11] = KLrot45[1];
+
+ long[] KArot45 = ROT.ROTL64(KA1, KA2, 45);
+ subkeys[12] = KArot45[0];
+ subkeys[13] = KArot45[1];
+
+ long[] KLrot60 = ROT.ROTL64(KL1, KL2, 60);
+ subkeys[14] = KLrot60[0];
+ subkeys[15] = KLrot60[1];
+
+ long[] KLrot77 = ROT.ROTL64(KL1, KL2, 77);
+ subkeys[16] = (KLrot77[0] >>> 32) | (KLrot77[0] << 32);
+ subkeys[17] = (KLrot77[1] >>> 32) | (KLrot77[1] << 32);
+
+ long[] KLrot94 = ROT.ROTL64(KL1, KL2, 94);
+ subkeys[18] = KLrot94[0];
+ subkeys[19] = KLrot94[1];
+
+ long[] KArot94 = ROT.ROTL64(KA1, KA2, 94);
+ subkeys[20] = KArot94[0];
+ subkeys[21] = KArot94[1];
+
+ long[] KLrot111 = ROT.ROTL64(KL1, KL2, 111);
+ subkeys[22] = KLrot111[0];
+ subkeys[23] = KLrot111[1];
+
+ long[] KArot111 = ROT.ROTL64(KA1, KA2, 111);
+ subkeys[24] = KArot111[0];
+ subkeys[25] = KArot111[1];
+ } else {
+ subkeys[0] = KL1;
+ subkeys[1] = KL2;
+
+ subkeys[2] = KB1;
+ subkeys[3] = KB2;
+
+ long[] KRrot15 = ROT.ROTL64(KR1, KR2, 15);
+ subkeys[4] = KRrot15[0];
+ subkeys[5] = KRrot15[1];
+
+ long[] KArot15 = ROT.ROTL64(KA1, KA2, 15);
+ subkeys[6] = KArot15[0];
+ subkeys[7] = KArot15[1];
+
+ long[] KRrot30 = ROT.ROTL64(KR1, KR2, 30);
+ subkeys[8] = (KRrot30[0] >>> 32) | (KRrot30[0] << 32);
+ subkeys[9] = (KRrot30[1] >>> 32) | (KRrot30[1] << 32);
+
+ long[] KBrot30 = ROT.ROTL64(KB1, KB2, 30);
+ subkeys[10] = KBrot30[0];
+ subkeys[11] = KBrot30[1];
+
+ long[] KLrot45 = ROT.ROTL64(KL1, KL2, 45);
+ subkeys[12] = KLrot45[0];
+ subkeys[13] = KLrot45[1];
+
+ long[] KArot45 = ROT.ROTL64(KA1, KA2, 45);
+ subkeys[14] = KArot45[0];
+ subkeys[15] = KArot45[1];
+
+ long[] KLrot60 = ROT.ROTL64(KL1, KL2, 60);
+ subkeys[16] = (KLrot60[0] >>> 32) | (KLrot60[0] << 32);
+ subkeys[17] = (KLrot60[1] >>> 32) | (KLrot60[1] << 32);
+
+ long[] KRrot60 = ROT.ROTL64(KR1, KR2, 60);
+ subkeys[18] = KRrot60[0];
+ subkeys[19] = KRrot60[1];
+
+ long[] KBrot60 = ROT.ROTL64(KB1, KB2, 60);
+ subkeys[20] = KBrot60[0];
+ subkeys[21] = KBrot60[1];
+
+ long[] KLrot77 = ROT.ROTL64(KL1, KL2, 77);
+ subkeys[22] = KLrot77[0];
+ subkeys[23] = KLrot77[1];
+
+ long[] KArot77 = ROT.ROTL64(KA1, KA2, 77);
+ subkeys[24] = (KArot77[0] >>> 32) | (KArot77[0] << 32);
+ subkeys[25] = (KArot77[1] >>> 32) | (KArot77[1] << 32);
+
+ long[] KRrot94 = ROT.ROTL64(KR1, KR2, 94);
+ subkeys[26] = KRrot94[0];
+ subkeys[27] = KRrot94[1];
+
+ long[] KArot94 = ROT.ROTL64(KA1, KA2, 94);
+ subkeys[28] = KArot94[0];
+ subkeys[29] = KArot94[1];
+
+ long[] KLrot111 = ROT.ROTL64(KL1, KL2, 111);
+ subkeys[30] = KLrot111[0];
+ subkeys[31] = KLrot111[1];
+
+ long[] KBrot111 = ROT.ROTL64(KB1, KB2, 111);
+ subkeys[32] = KBrot111[0];
+ subkeys[33] = KBrot111[1];
+ }
+ }
+
+ private long F(long F_IN, long KE) {
+ long x = F_IN ^ KE;
+
+ int[] t = new int[9];
+ for (int i = 1; i <= 8; i++) t[i] = (int) ((x >>> (64 - (i * 8))) & 0xFFL);
+
+ t[1] = UnchangingData.CAMELLIA_SBOX1[t[1]];
+ t[2] = UnchangingData.CAMELLIA_SBOX2[t[2]];
+ t[3] = UnchangingData.CAMELLIA_SBOX3[t[3]];
+ t[4] = UnchangingData.CAMELLIA_SBOX4[t[4]];
+ t[5] = UnchangingData.CAMELLIA_SBOX2[t[5]];
+ t[6] = UnchangingData.CAMELLIA_SBOX3[t[6]];
+ t[7] = UnchangingData.CAMELLIA_SBOX4[t[7]];
+ t[8] = UnchangingData.CAMELLIA_SBOX1[t[8]];
+
+ int y1 = t[1] ^ t[3] ^ t[4] ^ t[6] ^ t[7] ^ t[8];
+ int y2 = t[1] ^ t[2] ^ t[4] ^ t[5] ^ t[7] ^ t[8];
+ int y3 = t[1] ^ t[2] ^ t[3] ^ t[5] ^ t[6] ^ t[8];
+ int y4 = t[2] ^ t[3] ^ t[4] ^ t[5] ^ t[6] ^ t[7];
+ int y5 = t[1] ^ t[2] ^ t[6] ^ t[7] ^ t[8];
+ int y6 = t[2] ^ t[3] ^ t[5] ^ t[7] ^ t[8];
+ int y7 = t[3] ^ t[4] ^ t[5] ^ t[6] ^ t[8];
+ int y8 = t[1] ^ t[4] ^ t[5] ^ t[6] ^ t[7];
+
+ return ((long) y1 << 56) | ((long) y2 << 48) | ((long) y3 << 40) | ((long) y4 << 32) |
+ ((long) y5 << 24) | ((long) y6 << 16) | ((long) y7 << 8) | (long) y8;
+ }
+
+ private long FL(long FL_IN, long KE) {
+ long x1 = FL_IN >>> 32;
+ long x2 = FL_IN & 0xFFFFFFFFL;
+ long k1 = KE >>> 32;
+ long k2 = KE & 0xFFFFFFFFL;
+
+ long y2 = x2 ^ ROT.ROTL32((x1 & k1), 1);
+ long y1 = x1 ^ (y2 | k2);
+
+ return (y1 << 32) | (y2 & 0xFFFFFFFFL);
+ }
+
+ // <- im expert dev/programmer!
+ private long FLINV(long FLINV_IN, long KE) {
+ long y1 = FLINV_IN >>> 32;
+ long y2 = FLINV_IN & 0xFFFFFFFFL;
+ long k1 = KE >>> 32;
+ long k2 = KE & 0xFFFFFFFFL;
+
+ long x1 = y1 ^ (y2 | k2);
+ long x2 = y2 ^ ROT.ROTL32((x1 & k1), 1);
+
+ return (x1 << 32) | (x2 & 0xFFFFFFFFL);
+ }
+
+ private long bytes2Long(byte[] b, int off) {
+ long res = 0;
+ for (int i = 0; i < 8; i++) {
+ int shift = 56 - (i * 8);
+ res |= ((long) (b[off + i] & 0xFF) << shift);
+ }
+ return res;
+ }
+
+ private void long2Bytes(long v, byte[] b, int off) {
+ for (int i = 0; i < 8; i++) {
+ b[off + i] = (byte) (v >>> (56 - (i * 8)));
+ }
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SM4GCM.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SM4GCM.java
new file mode 100644
index 0000000..d838c18
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SM4GCM.java
@@ -0,0 +1,68 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.BlockCipher;
+import de.caydenno1.xacrypto.zekerrijndael.UnchangingData;
+
+public final class SM4GCM implements BlockCipher {
+ // mainland china encryption! ;) (GB/T 32907-2016)
+ private final int[] rk = new int[32];
+
+ public SM4GCM(byte[] key) throws XACryptoException {
+ if (key.length != 16) throw new XACryptoException("16 byte key required. :L");
+ int[] K = new int[4];
+ for (int i = 0 ; i < 4 ; i++)K[i] = read(key, i*4) ^ UnchangingData.SM4_FK[i];
+ for (int i = 0 ; i < 32 ; i++) {
+ K[i&3] ^= p(K[(i+1)&3]
+ ^ K[(i+2)&3]
+ ^ K[(i+3)&3]
+ ^ UnchangingData.SM4_CK[i]
+ );
+ rk[i] = K[i & 3];
+ }
+ }
+
+ @Override
+ public byte[] encryptBlock(byte[] in) {
+ int[] x = new int[4];
+ for (int i = 0 ; i < 4 ; i++) x[i] = read(in, i*4);
+ for (int i = 0 ; i < 32 ; i++) {
+ int nx = x[0] ^ t(x[1] ^ x[2] ^ x[3] ^ rk[i]);
+ for (int j = 0 ; j < 3 ; j++) x[j] = x[j+1];
+ x[3] = nx;
+ }
+ byte[] o = new byte[16];
+ for (int i = 0 ; i < 4 ; i++) write(x[3-i], o, i*4);
+ return o;
+ }
+
+ private static int tau(int w) {
+ return (UnchangingData.SBOX[(w >>> 24) & 0xFF] << 24) |
+ (UnchangingData.SBOX[(w >>> 8) & 0xFF] << 24);
+ }
+
+ private static int t(int w) {
+ int b = tau(w);
+ return b ^ de.caydenno1.xacrypto.hash.ROT.ROTL(b, 2)
+ ^ de.caydenno1.xacrypto.hash.ROT.ROTL(b, 10)
+ ^ de.caydenno1.xacrypto.hash.ROT.ROTL(b, 18)
+ ^ de.caydenno1.xacrypto.hash.ROT.ROTL(b, 24);
+ }
+
+ private static int p(int w) {
+ int b = tau(w);
+ return b ^ de.caydenno1.xacrypto.hash.ROT.ROTL(b,13)
+ ^ de.caydenno1.xacrypto.hash.ROT.ROTL(b,23);
+ }
+
+ private static int read(byte[] b, int o){
+ return ((b[o] & 0xFF) << 24)
+ | ((b[o+1]&0xFF)<<16)
+ | ((b[o+2]&0xFF)<<8)
+ | (b[o+3]&0xFF);
+ }
+
+ private static void write(int v, byte[] b, int o) {
+ for (int i = 0; i < 4; i++) b[o + i] = (byte)(v >>> (24 - i * 8));
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java
new file mode 100644
index 0000000..8b4f02a
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java
@@ -0,0 +1,14 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.BlockCipher;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.GCM;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.Serpent;
+
+import java.lang.reflect.InvocationTargetException;
+
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SERPENT_SBOX;
+
+public class SerpentGCM extends GCM {
+ public SerpentGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { super(new Serpent(key)); }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java
new file mode 100644
index 0000000..1b24d58
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java
@@ -0,0 +1,13 @@
+package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.GCM;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.Twofish;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class TwofishGCM extends GCM {
+ public TwofishGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ super(new Twofish(key));
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java b/src/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java
new file mode 100644
index 0000000..c8f86a1
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java
@@ -0,0 +1,270 @@
+package de.caydenno1.xacrypto.zekerrijndael.Global;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.UnchangingData;
+
+public class Aria {
+ // this is NOT a cipher, more or less and encryption type/method
+ private final int round;
+ private final byte[][] encRK;
+ private final byte[][] decRK;
+
+ public Aria(boolean enc, byte[] key) throws XACryptoException {
+ int kb = key.length * 8;
+ round = switch(kb) {
+ case 128 -> 12;
+ case 192 -> 14;
+ case 256 -> 16;
+ default -> throw new XACryptoException(
+ "only 128, 192 and 256 bit ciphers are supported atm. sorry :%"
+ );
+ };
+
+ encRK = new byte[round + 1][16];
+ decRK = new byte[round + 1][16];
+
+ encRK(key);
+ SDK();
+ }
+
+ public byte[] encryptBlock(byte[] in) throws XACryptoException{
+ if (in.length != 16) throw new XACryptoException("input length is required to be 16 bytes", (byte)0x16);
+
+ byte[] currentState = new byte[16];
+ System.arraycopy(in, 0, currentState, 0, 16);
+
+ procRound(currentState, this.encRK);
+
+ return currentState;
+ }
+
+ public byte[] decryptBlock(byte[] in) throws XACryptoException {
+ if (in.length != 16) throw new XACryptoException("input length is required to be 16 bytes", (byte)0x16);
+
+ byte[] state = new byte[16];
+ System.arraycopy(in,0,state,0,16);
+
+ procRound(state, this.decRK);
+
+ return state;
+ }
+
+ private void SDK() {
+ System.arraycopy(encRK[0], 0, decRK[round], 0, 16);
+ System.arraycopy(encRK[round], 0, decRK[0], 0, 16);
+
+ byte[] _0 = new byte[16];
+ for (int i = 1 ; i < round ; i++){
+ A(encRK[i], _0);
+ System.arraycopy(_0, 0, decRK[round-i], 0, 16);
+ }
+ }
+ private void procRound(byte[] state, byte[][] rK){
+ byte[] _0 = new byte[16];
+
+ for (int r = 0 ; r < round - 1 ; r++){
+ AriaXOR(state,rK[r]);
+ if (r % 2 == 0) {
+ SL1(state, _0);
+ } else {
+ SL2(state, _0);
+ }
+ A(_0, state);
+ }
+
+ AriaXOR(state, rK[round-1]);
+ if((round-1) % 2 == 0) {
+ SL1(state, _0);
+ } else {
+ SL2(state, _0);
+ }
+
+ AriaXOR(_0, rK[round], state);
+ }
+
+ private void AriaXOR(byte[] blk, byte[] key){
+ for (int i = 0 ; i < 16 ; i++){
+ blk[i] ^= key[i];
+ }
+ }
+
+ private void AriaXOR(byte[] a, byte[] b, byte[] o) {
+ for (int i = 0 ; i < 16 ; i++) {
+ o[i] = (byte)(a[i] ^ b[i]);
+ }
+ }
+
+ public void SROTR128(byte[] i, int bits, byte[] o) {
+ int byS = bits / 8;
+ int biS = bits % 8;
+
+ for (int _0 = 0 ; _0 < 16 ; _0++){
+ int idx1 = (_0 - byS + 32) % 16;
+ int idx2 = (_0 - byS - 1 + 32) % 16;
+
+ int b1 = i[idx1] & 0xFF;
+ int b2 = i[idx2] & 0xFF;
+
+ o[_0] = (byte) ((b1 >>> biS) | (b2 << (8 - biS)));
+ }
+ }
+ // feistel odd
+ private void FO(byte[] i, byte[] ck, byte[] o) {
+ byte[] _0 = new byte[16];
+ AriaXOR(i, ck, _0);
+ SL1(_0, _0);
+ A(_0, o);
+ }
+ //feistel even
+ private void FE(byte[] i, byte[] ck, byte[] o) {
+ byte[] _0 = new byte[16];
+ AriaXOR(i, ck, _0);
+ SL2(_0, _0);
+ A(_0, o);
+ }
+
+ private void SL1(byte[] i,byte[] o){
+ byte[][] tables = {
+ UnchangingData.ARIA_SB1,
+ UnchangingData.ARIA_SB2,
+ UnchangingData.ARIA_XB1,
+ UnchangingData.ARIA_XB2
+ };
+
+ for (int k = 0; k < 16; k++) {
+ o[k] = tables[k & 3][i[k] & 0xff];
+ }
+
+ }
+
+ private void encRK(byte[] key) throws XACryptoException {
+ int size = key.length;
+
+ byte[] KL = new byte[16];
+ byte[] KR = new byte[16];
+ byte[][] CK = new byte[4][16];
+
+ if (size == 16 || size == 24 || size == 32) System.arraycopy(key,0,KL,0,16);
+ switch(size) {
+ case 16: CK[1]=UnchangingData.ARIA_C1;CK[2]=UnchangingData.ARIA_C2;CK[3]=UnchangingData.ARIA_C3; break;
+
+ case 24: {
+ System.arraycopy(key, 16, KR, 0, 8);
+ CK[1] = UnchangingData.ARIA_C2; CK[2] = UnchangingData.ARIA_C3; CK[3] = UnchangingData.ARIA_C1;
+ break;
+ }
+
+ case 32: {
+ System.arraycopy(key,16,KR,0,16);
+ CK[1] = UnchangingData.ARIA_C3; CK[2] = UnchangingData.ARIA_C1 ; CK[3] = UnchangingData.ARIA_C2;
+ break;
+ }
+
+ default: throw new XACryptoException("only keysizes of 16,24,32 are supported atm :|");
+ }
+
+ byte[][] W = new byte[4][16];
+
+ System.arraycopy(KL, 0, W[0], 0, 16);
+
+ FO(W[0], CK[1], W[1]);
+ AriaXOR(W[1], KR, W[1]); // W1 = FO(W0, CK1) ^ KR
+
+ FE(W[1], CK[2], W[2]);
+ AriaXOR(W[2], W[0], W[2]); // W2 = FE(W1, CK2) ^ W0
+
+ FO(W[2], CK[3], W[3]);
+ AriaXOR(W[3], W[1], W[3]);
+
+ byte[] _0 = new byte[16];
+
+ SROTR128(W[1], 19, _0);
+ AriaXOR(W[0], _0, encRK[0]);
+
+ SROTR128(W[2], 19, _0);
+ AriaXOR(W[1], _0, encRK[1]);
+
+ SROTR128(W[3], 19, _0);
+ AriaXOR(W[2], _0, encRK[2]);
+
+ SROTR128(W[0], 19, _0);
+ AriaXOR(_0, W[3], encRK[3]);
+
+ SROTR128(W[1], 31, _0);
+ AriaXOR(W[0], _0, encRK[4]);
+
+ SROTR128(W[2], 31, _0);
+ AriaXOR(W[1], _0, encRK[5]);
+
+ SROTR128(W[3], 31, _0);
+ AriaXOR(W[2], _0, encRK[6]);
+
+ SROTR128(W[0], 31, _0);
+ AriaXOR(_0, W[3], encRK[7]);
+
+ SROTR128(W[1], 128 - 61, _0);
+ AriaXOR(W[0], _0, encRK[8]);
+
+ SROTR128(W[2], 128 - 61, _0);
+ AriaXOR(W[1], _0, encRK[9]);
+
+ SROTR128(W[3], 128 - 61, _0);
+ AriaXOR(W[2], _0, encRK[10]);
+
+ SROTR128(W[0], 128 - 61, _0);
+ AriaXOR(_0, W[3], encRK[11]);
+
+ SROTR128(W[1], 128 - 31, _0);
+ AriaXOR(W[0], _0, encRK[12]);
+
+ if (round >= 14) {
+ SROTR128(W[2], 128 - 31, _0);
+ AriaXOR(W[1], _0, encRK[13]);
+
+ // ek15 = W2 ^ (W3 <<< 31)
+ SROTR128(W[3], 128 - 31, _0);
+ AriaXOR(W[2], _0, encRK[14]);
+ }
+
+ if (round == 16) {
+ SROTR128(W[0], 128 - 31, _0);
+ AriaXOR(_0, W[3], encRK[15]);
+
+ SROTR128(W[1], 128 - 19, _0);
+ AriaXOR(W[0], _0, encRK[16]);
+ }
+ }
+
+ private void SL2(byte[] i,byte[] o){
+ byte[][] tables = {
+ UnchangingData.ARIA_XB1,
+ UnchangingData.ARIA_XB2,
+ UnchangingData.ARIA_SB1,
+ UnchangingData.ARIA_SB2
+ };
+
+ for (int k = 0; k < 16; k++) {
+ o[k] = tables[k & 3][i[k] & 0xff];
+ }
+
+ }
+ private void A(byte[] i, byte[] o) {
+ // "diffusion layer" Matrix A
+ o[0] = (byte)(i[3] ^ i[4] ^ i[9] ^ i[14]);
+ o[1] = (byte)(i[2] ^ i[5] ^ i[8] ^ i[15]);
+ o[2] = (byte)(i[1] ^ i[6] ^ i[11] ^ i[12]);
+ o[3] = (byte)(i[0] ^ i[7] ^ i[10] ^ i[13]);
+ o[4] = (byte)(i[0] ^ i[5] ^ i[11] ^ i[14]);
+ o[5] = (byte)(i[1] ^ i[4] ^ i[10] ^ i[15]);
+ o[6] = (byte)(i[2] ^ i[7] ^ i[9] ^ i[12]);
+ o[7] = (byte)(i[3] ^ i[6] ^ i[8] ^ i[13]);
+ o[8] = (byte)(i[1] ^ i[7] ^ i[11] ^ i[13]);
+ o[9] = (byte)(i[0] ^ i[6] ^ i[10] ^ i[12]);
+ o[10] = (byte)(i[3] ^ i[5] ^ i[9] ^ i[15]);
+ o[11] = (byte)(i[2] ^ i[4] ^ i[8] ^ i[14]);
+ o[12] = (byte)(i[2] ^ i[6] ^ i[9] ^ i[14]);
+ o[13] = (byte)(i[3] ^ i[7] ^ i[8] ^ i[15]);
+ o[14] = (byte)(i[0] ^ i[4] ^ i[11] ^ i[12]);
+ o[15] = (byte)(i[1] ^ i[5] ^ i[10] ^ i[13]);
+ }
+}
diff --git a/src/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java b/src/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java
new file mode 100644
index 0000000..3df3135
--- /dev/null
+++ b/src/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b8b3cf3379dbb436a894945a7299a5e3be30844ac377df5a21f1c2cbb0a15b0b
+size 52205
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/ROT.java b/src/main/java/de/caydenno1/xacrypto/hash/ROT.java
index da265f4..98483e2 100644
--- a/src/main/java/de/caydenno1/xacrypto/hash/ROT.java
+++ b/src/main/java/de/caydenno1/xacrypto/hash/ROT.java
@@ -7,4 +7,17 @@ public class ROT {
public static int ROTL(int x, int n){
return (x << n) | (x >>> (32 - n));
}
+ public static long ROTL32(long v, int shift) { return ((v & 0xFFFFFFFFL << shift) | (v & 0xFFFFFFFFL >>> (32 - shift))) & 0xFFFFFFFFL; }
+ public static long[] ROTL64(long l, long r, int shift) {
+ long[] res = new long[2];
+ if (shift < 64) {
+ res[0] = (l << shift) | (r >>> (64 - shift));
+ res[1] = (r << shift) | (l >>> (64 - shift));
+ } else {
+ int s = shift - 64;
+ res[0] = (r << s) | (l >>> (64 - s));
+ res[1] = (l << s) | (r >>> (64 - s));
+ }
+ return res;
+ }
}
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/sha/SHA1.java b/src/main/java/de/caydenno1/xacrypto/hash/sha/SHA1.java
index 41c1dd8..8438895 100644
--- a/src/main/java/de/caydenno1/xacrypto/hash/sha/SHA1.java
+++ b/src/main/java/de/caydenno1/xacrypto/hash/sha/SHA1.java
@@ -77,6 +77,4 @@ public class SHA1 {
byte[] result = hash(data.getBytes(StandardCharsets.UTF_8));
return hex(result);
}
-
-
}
\ No newline at end of file
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/sha256/SHA256.java b/src/main/java/de/caydenno1/xacrypto/hash/sha256/SHA256.java
index 455d413..70a2d77 100644
--- a/src/main/java/de/caydenno1/xacrypto/hash/sha256/SHA256.java
+++ b/src/main/java/de/caydenno1/xacrypto/hash/sha256/SHA256.java
@@ -9,6 +9,7 @@ import java.util.concurrent.RecursiveTask;
import static de.caydenno1.xacrypto.hash.sha256.Hex.hash;
import static de.caydenno1.xacrypto.hash.sha256.Hex.doubleHash;
import static de.caydenno1.xacrypto.hash.ROT.ROTR;
+import de.caydenno1.xacrypto.misc.ToM;
public final class SHA256 {
private SHA256(){}
@@ -88,14 +89,6 @@ public final class SHA256 {
return o;
}
- public static boolean ToM(byte[] a, byte[] b) {
- if (a == null || b == null) return a == b;
- if (a.length != b.length) return false;
- int diff = 0;
- for (int i = 0; i < a.length; i++) diff |= (a[i] ^ b[i]);
- return diff == 0;
- }
-
public static final class HashTask extends RecursiveTask{
private final java.util.List leaves;
private int from,to;
diff --git a/src/main/java/de/caydenno1/xacrypto/misc/Constants.java b/src/main/java/de/caydenno1/xacrypto/misc/Constants.java
index 36dd26d..b281cbf 100644
--- a/src/main/java/de/caydenno1/xacrypto/misc/Constants.java
+++ b/src/main/java/de/caydenno1/xacrypto/misc/Constants.java
@@ -1,39 +1,3 @@
-package de.caydenno1.xacrypto.misc;
-
-public class Constants {
- public static final int[] SHA1_K = {
- 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
- };
- public static final int[] SHA0_K = {
- 0x00000000,
- 0x5a827999,
- 0x6ed9eba1,
- 0x8f1bbcdc
- };
- public static final int[] SHA256_K = {
- 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,
- 0x59f111f1,0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,
- 0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,
- 0xc19bf174,0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
- 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,0x983e5152,
- 0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,
- 0x06ca6351,0x14292967,0x27b70a85,0x2e1b2138,0x4d2c6dfc,
- 0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
- 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,
- 0xd6990624,0xf40e3585,0x106aa070,0x19a4c116,0x1e376c08,
- 0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,
- 0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
- 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
- };
-
- public static final int[] SHA256_H = {
- 0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,
- 0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19
- };
-
- public static final int[] SHA_H = {
- 0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0
- };
-
- // (no longer a placeholder)
-}
+version https://git-lfs.github.com/spec/v1
+oid sha256:bc4782acf20fb2dfe37bdaf88a22fc42816a72839597a17afed0d6984b5569d5
+size 1549
diff --git a/src/main/java/de/caydenno1/xacrypto/misc/ToM.java b/src/main/java/de/caydenno1/xacrypto/misc/ToM.java
new file mode 100644
index 0000000..e8d48cb
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/misc/ToM.java
@@ -0,0 +1,11 @@
+package de.caydenno1.xacrypto.misc;
+
+public class ToM {
+ public static boolean ToM(byte[] a, byte[] b) {
+ if (a == null || b == null) return a == b;
+ if (a.length != b.length) return false;
+ int diff = 0;
+ for (int i = 0; i < a.length; i++) diff |= (a[i] ^ b[i]);
+ return diff == 0;
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/misc/XACryptoException.java b/src/main/java/de/caydenno1/xacrypto/misc/XACryptoException.java
index ba3cdf9..a04b5a3 100644
--- a/src/main/java/de/caydenno1/xacrypto/misc/XACryptoException.java
+++ b/src/main/java/de/caydenno1/xacrypto/misc/XACryptoException.java
@@ -15,6 +15,10 @@ public class XACryptoException extends Exception {
super(res);
this.id = id & 0xFF;
}
+ public XACryptoException(String res, int iid) {
+ super(res);
+ this.id = iid;
+ }
public XACryptoException(String[] pnts, byte id){
super(String.join("|", pnts));
this.id = id & 0xFF;
diff --git a/src/main/java/de/caydenno1/xacrypto/misc/isNull.java b/src/main/java/de/caydenno1/xacrypto/misc/isNull.java
new file mode 100644
index 0000000..4437892
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/misc/isNull.java
@@ -0,0 +1,22 @@
+package de.caydenno1.xacrypto.misc;
+
+import java.util.Objects;
+
+public class isNull {
+ public static boolean isNull(Object v) {
+ return Objects.isNull(v) || v == null;
+ }
+ public boolean isNull(Object v, Object alt) {
+ return Objects.isNull(v) || v == null || v == alt;
+ }
+ public static boolean isValidText(String s) {
+ if (s.isBlank() || s.trim().isEmpty()) return false;
+ switch (s) {
+ case "":
+ case null:
+ return false;
+ default:
+ return true;
+ }
+ };
+}