diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 22774d6..93a06f7 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -8,9 +8,9 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 8785aed..1a78b84 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
de.caydenno1.xacrypto
xacrypto
- 2026.06.04_R2
+ 2026.06.19_R1
XACrypto
A multi-purpose Cryptography library in Java.
@@ -83,6 +83,19 @@
3.14.0
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.4.2
+
+
+
+ de.caydenno1.xacrypto.XACrypto
+
+
+
+
+
org.apache.maven.plugins
maven-surefire-plugin
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/ROT.java b/src/main/java/de/caydenno1/xacrypto/hash/ROT.java
index 98483e2..c6df092 100644
--- a/src/main/java/de/caydenno1/xacrypto/hash/ROT.java
+++ b/src/main/java/de/caydenno1/xacrypto/hash/ROT.java
@@ -4,6 +4,9 @@ public class ROT {
public static int ROTR(int x, int n){
return (x >>> n) | (x << (32 - n));
}
+ public static long ROTR64(long x, int n){
+ return (x >>> n) | (x << (64 - n));
+ }
public static int ROTL(int x, int n){
return (x << n) | (x >>> (32 - n));
}
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/sha224/SHA224.java b/src/main/java/de/caydenno1/xacrypto/hash/sha224/SHA224.java
index 136c061..0d42760 100644
--- a/src/main/java/de/caydenno1/xacrypto/hash/sha224/SHA224.java
+++ b/src/main/java/de/caydenno1/xacrypto/hash/sha224/SHA224.java
@@ -1,7 +1,5 @@
package de.caydenno1.xacrypto.hash.sha224;
-import static de.caydenno1.xacrypto.hash.ROT.ROTR;
-import static de.caydenno1.xacrypto.hash.ROT.ROTL;
import static de.caydenno1.xacrypto.hash.sha224.Helpers.ch;
import static de.caydenno1.xacrypto.hash.sha224.Helpers.maj;
import static de.caydenno1.xacrypto.hash.sha224.Helpers.bigSigma0;
@@ -13,7 +11,7 @@ import static de.caydenno1.xacrypto.misc.Constants.SHA224_K;
public class SHA224 {
public static byte[] digest(byte[] message) {
- long bl = ((long) message.length);
+ long bl = ((long) message.length) * 8L;
int paddingLength = 64 - (int) ((message.length + 9) % 64);
if (paddingLength == 64) paddingLength = 0;
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/sha384/SHA384.java b/src/main/java/de/caydenno1/xacrypto/hash/sha384/SHA384.java
new file mode 100644
index 0000000..a88c553
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/hash/sha384/SHA384.java
@@ -0,0 +1,117 @@
+package de.caydenno1.xacrypto.hash.sha384;
+
+import java.util.Arrays;
+
+import static de.caydenno1.xacrypto.misc.Constants.SHA384_H0;
+import static de.caydenno1.xacrypto.misc.Constants.SHA384_K;
+import static de.caydenno1.xacrypto.hash.ROT.ROTR64;
+import static de.caydenno1.xacrypto.hash.sha256.Hex.Byte2Hex;
+
+public class SHA384 {
+ // digest
+ // pad
+ public static byte[] digest(byte[] mesg) {
+ long[] h = Arrays.copyOf(SHA384_H0, SHA384_H0.length);
+ byte[] pd = pad(mesg);
+
+ int c = pd.length / 128;
+
+ long[] w = new long[80];
+
+ for (int blk = 0 ; blk < c ; blk++) {
+ int base = blk * 128;
+
+ for (int t = 0 ; t < 16 ; t++) w[t] = BYTE2LONG(pd, base + t * 8);
+
+ for (int t = 16 ; t < 80 ; t ++) {
+ long s0 = ROTR64(w[t - 15], 1)
+ ^ ROTR64(w[t - 15], 8)
+ ^ (w[t - 15] >>> 7);
+ long s1 = ROTR64(w[t - 2], 19)
+ ^ ROTR64(w[t - 2], 61)
+ ^ w[t - 2] >>> 6;
+ w[t] = w[t - 16] + s0 + w[t - 7] + s1;
+ }
+
+ // a = h[0]
+ // b = h[1]
+ // c = h[2]
+ // d = h[3]
+ // e = h[4]
+ // f = h[5]
+ // g = h[6]
+ // h = h[7]
+
+ long[] h0 = Arrays.copyOf(h, h.length);
+
+ for (int t = 0 ; t < 80 ; t++) {
+ long S1 = ROTR64(h[4], 14)
+ ^ ROTR64(h[4], 18)
+ ^ ROTR64(h[4], 41);
+ long ch = (h[4] & h[5]) ^ (~h[4] & h[6]);
+ long _0 = h[7] + S1 + ch + SHA384_K[t] + w[t];
+
+ long S0 = ROTR64(h[0], 28)
+ ^ ROTR64(h[0], 34)
+ ^ ROTR64(h[0], 39);
+
+ long maj = (h[0] & h[1]) ^ (h[0] & h[2]) ^ (h[1] & h[2]);
+
+ long _1 = S0 + maj;
+
+ h[7] = h[6];
+ h[6] = h[5];
+ h[5] = h[4];
+ h[4] = h[3] + _0;
+ h[3] = h[2];
+ h[2] = h[1];
+ h[1] = h[0];
+ h[0] = _0 + _1;
+ }
+
+ for (int i = 0 ; i < 8 ; i++) h[i] += h0[i];
+ }
+
+ byte[] res = new byte[48];
+ for (int i = 0 ; i < 6 ; i++) LONG2BYTE(h[i], res, i*8);
+
+ return res;
+ };
+
+ public static byte[] pad(byte[] mesg) {
+ long MLB = (long) mesg.length * 8L;
+
+ int mod = mesg.length % 128;
+ int pLen;
+ if (mod < 112) {
+ pLen = 112 - mod;
+ } else {
+ pLen = 240 - mod;
+ }
+
+ byte[] pd = new byte[mesg.length + pLen + 16];
+
+ System.arraycopy(mesg, 0, pd, 0, mesg.length);
+
+ pd[mesg.length] = (byte) 0x80;
+
+ int off = pd.length - 16;
+ LONG2BYTE(0L, pd, off);
+ LONG2BYTE(MLB, pd, off + 8);
+
+ return pd;
+ }
+
+ private static long BYTE2LONG(byte[] bytes, int off) {
+ long res = 0;
+ for (int i = 0 ; i < 8 ; i++) res = (res << 8) | (bytes[off + i] & 0xFFL);
+ return res;
+ }
+
+ private static void LONG2BYTE(long val, byte[] bytes, int off) {
+ for (int i = 7 ; i >= 0 ; i--) {
+ bytes[off + i] = (byte) (val & 0xFF);
+ val >>>= 8;
+ }
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/hash/sha512/SHA512.java b/src/main/java/de/caydenno1/xacrypto/hash/sha512/SHA512.java
new file mode 100644
index 0000000..ea1dac4
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/hash/sha512/SHA512.java
@@ -0,0 +1,95 @@
+package de.caydenno1.xacrypto.hash.sha512;
+
+import java.util.Arrays;
+
+import static de.caydenno1.xacrypto.hash.ROT.ROTR64;
+import static de.caydenno1.xacrypto.misc.Constants.SHA512_H0;
+import static de.caydenno1.xacrypto.misc.Constants.SHA512_K;
+
+public class SHA512 {
+ public static byte[] digest(byte[] mesg) {
+ long bitLen = (long) mesg.length * 8L;
+
+ int mod = mesg.length % 128;
+ int pLen;
+ if (mod < 112) {
+ pLen = 112 - mod;
+ } else {
+ pLen = 240 - mod;
+ }
+
+ byte[] pd = new byte[mesg.length + pLen + 16];
+ System.arraycopy(mesg, 0, pd, 0, mesg.length);
+ pd[mesg.length] = (byte) 0x80;
+
+ int off = pd.length - 16;
+ LONG2BYTE(0L, pd, off);
+ LONG2BYTE(bitLen, pd, off + 8);
+
+ long[] H = Arrays.copyOf(SHA512_H0, 8);
+ long[] W = new long[80];
+
+ for (int blk = 0; blk < pd.length / 128; blk++) {
+ int base = blk * 128;
+ long[] pH = Arrays.copyOf(H, 8);
+
+ for (int t = 0; t < 16; t++) W[t] = BYTE2LONG(pd, base + t * 8);
+
+ for (int t = 16; t < 80; t++) {
+ long s0 = ROTR64(W[t - 15], 1) ^ ROTR64(W[t - 15], 8) ^ (W[t - 15] >>> 7);
+ long s1 = ROTR64(W[t - 2], 19) ^ ROTR64(W[t - 2], 61) ^ (W[t - 2] >>> 6);
+ W[t] = W[t - 16] + s0 + W[t - 7] + s1;
+ }
+
+ for (int t = 0; t < 80; t++) {
+ long S1 = ROTR64(H[4], 14) ^ ROTR64(H[4], 18) ^ ROTR64(H[4], 41);
+ long ch = (H[4] & H[5]) ^ (~H[4] & H[6]);
+ long T1 = H[7] + S1 + ch + SHA512_K[t] + W[t];
+
+ long S0 = ROTR64(H[0], 28) ^ ROTR64(H[0], 34) ^ ROTR64(H[0], 39);
+ long maj = (H[0] & H[1]) ^ (H[0] & H[2]) ^ (H[1] & H[2]);
+ long T2 = S0 + maj;
+
+ H[7] = H[6];
+ H[6] = H[5];
+ H[5] = H[4];
+ H[4] = H[3] + T1;
+ H[3] = H[2];
+ H[2] = H[1];
+ H[1] = H[0];
+ H[0] = T1 + T2;
+ }
+
+ for (int i = 0; i < 8; i++) H[i] += pH[i];
+ }
+
+ byte[] o = new byte[64];
+ for (int i = 0; i < 8; i++) LONG2BYTE(H[i], o, i * 8);
+
+ return o;
+ }
+
+ private static long BYTE2LONG(byte[] bytes, int off) {
+ long res = 0;
+ for (int i = 0; i < 8; i++) res = (res << 8) | (bytes[off + i] & 0xFFL);
+ return res;
+ }
+
+ private static void LONG2BYTE(long val, byte[] bytes, int off) {
+ for (int i = 7; i >= 0; i--) {
+ bytes[off + i] = (byte) (val & 0xFF);
+ val >>>= 8;
+ }
+ }
+
+ public static String BYTE2STR(byte[] data) {
+ StringBuilder sb = new StringBuilder(data.length * 2);
+
+ for (byte b : data) {
+ sb.append(Character.forDigit((b >>> 4) & 0xF, 16));
+ sb.append(Character.forDigit(b & 0xF, 16));
+ }
+
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/misc/Constants.java b/src/main/java/de/caydenno1/xacrypto/misc/Constants.java
index 7ceb961..a19b8b9 100644
--- a/src/main/java/de/caydenno1/xacrypto/misc/Constants.java
+++ b/src/main/java/de/caydenno1/xacrypto/misc/Constants.java
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9f4f9d90a3ee0f6a1e37131e6a8056cf46b02e6c8f517a592fb0c06870bfca65
-size 2765
+oid sha256:2d541e2449129baa2404d62806eb0cbb4d1da29c2017ee9930d8fd346b9bbd8f
+size 7504
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AESECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AESECB.java
new file mode 100644
index 0000000..6a90c63
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AESECB.java
@@ -0,0 +1,68 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.AES;
+
+public class AESECB implements ECB {
+ private final AES engine;
+
+ public AESECB(byte[] key) throws XACryptoException {
+ int bits = switch (key.length){
+ case 16 -> 128;
+ case 24 -> 192;
+ case 32 -> 256;
+ default -> throw new XACryptoException("aes keys must be 16, 24, or 32 in length.");
+ };
+
+ this.engine = new AES(key, bits);
+ }
+
+ 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[] o = engine.encryptBlock(in);
+ System.arraycopy(o, 0, cip, i, 16);
+ }
+
+ return cip;
+ }
+
+ public byte[] decrypt(byte[] cip) throws XACryptoException {
+ if (cip.length % 16 != 0) throw new XACryptoException("ciptext length must be of a 16-byte size :[");
+
+ byte[] Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_ = 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[] o = engine.decryptBlock(in);
+ System.arraycopy(o, 0, Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_, i, 16);
+ }
+
+ int pLen = Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_[Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_.length - 1] & 0xFF;
+
+ if (pLen < 1 || pLen > 16) throw new XACryptoException("padding must be 1-16 exclusive in length", (int) pLen);
+
+ for (int i = Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_.length - pLen; i < Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_.length; i++) {
+ if (((Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_[i] & 0xFF) != pLen)) {
+ throw new XACryptoException("something up with yo padding.. :(");
+ }
+ }
+
+ byte[] pln = new byte[Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_.length - pLen];
+ System.arraycopy(Microsoft_Copilot_is_your_companion_to_inform__entertain_and_inspire__Get_advice__feedback_and_straightforward_answers__Try_Copilot_now_, 0, pln, 0, pln.length);
+
+ return pln;
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java
index 6060cc8..42bac6a 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/AriaECB.java
@@ -1,14 +1,10 @@
package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB;
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 {
+public class AriaECB implements ECB {
private final Aria engine;
public AriaECB(byte[] key) throws XACryptoException {
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java
index 244733f..a4ce3f4 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/BlowfishECB.java
@@ -2,13 +2,9 @@ package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
import de.caydenno1.xacrypto.misc.XACryptoException;
import de.caydenno1.xacrypto.zekerrijndael.ECB.Blowfish;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless;
-interface BlowfishCipher {
- public byte[] encrypt(byte[] pln);
- public byte[] decrypt(byte[] cip) throws XACryptoException;
-}
-
-public class BlowfishECB implements BlowfishCipher {
+public class BlowfishECB implements ECBExceptionless {
private final Blowfish engine;
public BlowfishECB(byte[] key) throws XACryptoException {
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/CamelliaECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/CamelliaECB.java
new file mode 100644
index 0000000..948e093
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/CamelliaECB.java
@@ -0,0 +1,49 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless;
+import de.caydenno1.xacrypto.zekerrijndael.Global.Camellia;
+
+public class CamelliaECB implements ECBExceptionless {
+ private final Camellia engine;
+
+ public CamelliaECB(byte[] key) throws XACryptoException {
+ this.engine = new Camellia(key);
+ }
+
+ 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];
+
+ for (int i = 0 ; i < pData.length ; i += 16) {
+ engine.encryptBlock(pData, i, cip, i);
+ }
+
+ return cip;
+ }
+
+ public byte[] decrypt(byte[] cip) throws XACryptoException {
+ if (cip.length % 16 != 0) throw new XACryptoException("something somewhere, for some reason, is broken. somthing with camelliaecb !",(int)cip.length);
+
+ byte[] He_s_from_British_Columbia = new byte[cip.length];
+
+ for (int i = 0 ; i < cip.length ; i += 16) {
+ engine.decryptBlock(cip, i, He_s_from_British_Columbia, i);
+ }
+
+ int pLen = He_s_from_British_Columbia[He_s_from_British_Columbia.length - 1] & 0xFF;
+
+ byte[] pln = new byte[He_s_from_British_Columbia.length - pLen];
+ System.arraycopy(He_s_from_British_Columbia, 0, pln, 0, pln.length);
+
+ return pln;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/RC6ECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/RC6ECB.java
new file mode 100644
index 0000000..8015316
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/RC6ECB.java
@@ -0,0 +1,101 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB;
+import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.*;
+import static de.caydenno1.xacrypto.zekerrijndael.Global.LE32.*;
+
+public class RC6ECB implements ECB {
+ private final int[] S;
+ // 20 rounds
+
+ public RC6ECB(byte[] key) throws XACryptoException {
+ if (key.length <= 0 || key.length > 255) throw new XACryptoException("keys must be 1-255 bytes inclusive :\\");
+
+ int c = Math.max(1, (key.length + 3) / 4);
+ int[] L = new int[c];
+ for (int i = 0 ; i < key.length ; i++) L[i / 4] |= (key[i] & 0xFF) << (8 * (i % 4));
+
+ S = new int[44 /* 2x 20 rounds = 40 rounds + 4 = 44. */];
+ S[0] = RC6_P;
+ for (int i = 1 ; i < S.length ; i++) S[i] = S[i - 1] + RC6_Q;
+
+ int A = 0, B = 0, i = 0, j = 0;
+ int v = 3 * Math.max(c, S.length);
+ for (int s = 0 ; s < v ; s++) {
+ A = S[i] = Integer.rotateLeft(S[i] + A + B, 3);
+ B = L[j] = Integer.rotateLeft(L[j] + A + B, A + B);
+ i = (i + 1)%S.length;
+ j = (j + 1)%c;
+ }
+ }
+
+ private void encryptBlock(byte[] in, int inOff, byte[] out, int outOff) {
+ int[] data = new int[4];
+ for (int i = 0; i < 4; i++) data[i] = read32LE(in, inOff + (i * 4));
+
+ data[1] += S[0];
+ data[3] += S[1];
+
+ for (int i = 1 ; i <= 20 ; i++) {
+ int t = Integer.rotateLeft(data[1] * (2 * data[1] + 1), 5);
+ int u = Integer.rotateLeft(data[3] * (2 * data[3] + 1), 5);
+
+ data[0] = Integer.rotateLeft(data[0] ^ t, u) + S[2 * i];
+ data[2] = Integer.rotateLeft(data[2] ^ u, t) + S[2 * i + 1];
+
+ int _0 = data[0]; data[0] = data[1]; data[1] = data[2]; data[2] = data[3]; data[3] = _0;
+ }
+
+ data[0] += S[42];
+ data[2] += S[43];
+
+ for (int i = 0; i < 4; i++) write32LE(data[i], out, outOff + (i * 4));
+ };
+
+ private void decryptBlock(byte[] in, int inOff, byte[] out, int outOff) {
+ int[] data = new int[4];
+ for (int i = 0; i < 4; i++) data[i] = read32LE(in, inOff + (i * 4));
+
+ data[2] -= S[43];
+ data[0] -= S[42];
+
+ for (int i = 20 ; i >= 1 ; i--) {
+ int _0 = data[3]; data[2] = data[1]; data[1] = data[0]; data[0] = _0;
+
+ int u = Integer.rotateLeft(data[3] * (2 * data[3] + 1), 5);
+ int t = Integer.rotateLeft(data[1] * (2 * data[1] + 1), 5);
+
+ data[2] = Integer.rotateRight(data[2] - S[2 * i + 1], t) ^ u;
+ data[0] = Integer.rotateRight(data[0] - S[2 * i], u) ^ t;
+ }
+
+ data[3] -= S[1];
+ data[1] -= S[0];
+ for (int i = 0; i < 4; i++) write32LE(data[i], out, outOff + (i * 4));
+ }
+
+ 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];
+ for (int i = 0 ; i < pData.length ; i += 16) encryptBlock(pData, i, cip, i);
+ return cip;
+ }
+
+ public byte[] decrypt(byte[] cip) throws XACryptoException {
+ if (cip.length % 16 != 0) throw new XACryptoException("ciptext length is not a multiple of 16");
+
+ byte[] de = new byte[cip.length];
+ for (int i = 0 ; i < cip.length ; i += 16) decryptBlock(cip, i, de, i);
+
+ int pLen = de[de.length - 1] & 0xFF;
+
+ byte[] pln = new byte[de.length - pLen];
+ System.arraycopy(de, 0, pln, 0, pln.length);
+ return pln;
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java
index d136d6f..c57ed16 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/SM4ECB.java
@@ -1,18 +1,14 @@
package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless;
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 class SM4ECB implements ECBExceptionless {
public final int[] encRK = new int[32];
public final int[] decRK = new int[32];
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/TwofishECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/TwofishECB.java
new file mode 100644
index 0000000..94d47c9
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/TwofishECB.java
@@ -0,0 +1,56 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB;
+import de.caydenno1.xacrypto.zekerrijndael.Global.Twofish;
+
+public class TwofishECB implements ECB {
+ private final Twofish engine;
+
+ public TwofishECB(byte[] key) throws XACryptoException {
+ this.engine = new Twofish(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[] o = engine.encryptBlock(in);
+
+ 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 ciptext must be 16-byte (multiple of 16)");
+
+ byte[] Less_Stress__More_Travel___Find___Compare_Options_and_You_Can_Save_Big_on_Expedia_com__Get___ = new byte[cip.length];
+ byte[] l = new byte[16];
+
+ for (int i = 0 ; i < cip.length ; i += 16) {
+ System.arraycopy(cip, i, l, 0, 16);
+
+ byte[] o = engine.decryptBlock(l);
+
+ System.arraycopy(o, 0, Less_Stress__More_Travel___Find___Compare_Options_and_You_Can_Save_Big_on_Expedia_com__Get___, i, 16);
+ }
+
+ int pLen = Less_Stress__More_Travel___Find___Compare_Options_and_You_Can_Save_Big_on_Expedia_com__Get___[Less_Stress__More_Travel___Find___Compare_Options_and_You_Can_Save_Big_on_Expedia_com__Get___.length - 1] & 0xFF;
+
+
+ byte[] pln = new byte[Less_Stress__More_Travel___Find___Compare_Options_and_You_Can_Save_Big_on_Expedia_com__Get___.length - pLen];
+ System.arraycopy(Less_Stress__More_Travel___Find___Compare_Options_and_You_Can_Save_Big_on_Expedia_com__Get___, 0, pln, 0, pln.length);
+ return pln;
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/interfaces/ECB.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/interfaces/ECB.java
new file mode 100644
index 0000000..1ec23a9
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/interfaces/ECB.java
@@ -0,0 +1,9 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+public interface ECB {
+ public byte[] encrypt(byte[] pln) throws XACryptoException;
+ public byte[] decrypt(byte[] cip) throws XACryptoException;
+}
+
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/interfaces/ECBExceptionless.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/interfaces/ECBExceptionless.java
new file mode 100644
index 0000000..941c583
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/ECB/ciphers/interfaces/ECBExceptionless.java
@@ -0,0 +1,8 @@
+package de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces;
+
+import de.caydenno1.xacrypto.misc.XACryptoException;
+
+public interface ECBExceptionless extends ECB {
+ public byte[] encrypt(byte[] pln);
+ public byte[] decrypt(byte[] cip) throws XACryptoException;
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Factories.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Factories.java
index c6ae2d5..2f6df82 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Factories.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Factories.java
@@ -1,22 +1,43 @@
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.ECB.ciphers.*;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB;
+import de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless;
import de.caydenno1.xacrypto.zekerrijndael.GCM.AES;
import de.caydenno1.xacrypto.zekerrijndael.GCM.GCM;
import de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers.*;
+import de.caydenno1.xacrypto.zekerrijndael.Global.Camellia;
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); }
+ public static class GCM {
+ public static de.caydenno1.xacrypto.zekerrijndael.GCM.GCM AES128(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new de.caydenno1.xacrypto.zekerrijndael.GCM.GCM(new AES(key, 128)); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.GCM.GCM SM4GCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new de.caydenno1.xacrypto.zekerrijndael.GCM.GCM(new SM4GCM(key)); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.GCM.GCM Camellia(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new de.caydenno1.xacrypto.zekerrijndael.GCM.GCM(new Camellia(key)); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.GCM.GCM AESGCM() throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new de.caydenno1.xacrypto.zekerrijndael.GCM.GCM(new AESGCM()); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.GCM.GCM ARIAGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new de.caydenno1.xacrypto.zekerrijndael.GCM.GCM(new ARIAGCM(key)); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.GCM.GCM SerpentGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException { return new de.caydenno1.xacrypto.zekerrijndael.GCM.GCM(new SerpentGCM(key)); }
+ }
+
+ public static class ECB {
+ public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless Blowfish(byte[] key) throws XACryptoException { return new BlowfishECB(key); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB Aria(byte[] key) throws XACryptoException { return new AriaECB(key); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless SM4(byte[] key) throws XACryptoException { return new SM4ECB(key); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB AES(byte[] key) throws XACryptoException { return new AESECB(key); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB Twofish(byte[] key) throws XACryptoException { return new TwofishECB(key); }
+
+ public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECB RC6ECB(byte[] key) throws XACryptoException { return new RC6ECB(key); }
+
+ //public static de.caydenno1.xacrypto.zekerrijndael.ECB.ciphers.interfaces.ECBExceptionless CamelliaECB(byte[] key) throws XACryptoException { return new CamelliaECB(key); }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java
index f31bee0..d9bcaea 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/AES.java
@@ -1,7 +1,7 @@
package de.caydenno1.xacrypto.zekerrijndael.GCM;
import de.caydenno1.xacrypto.misc.XACryptoException;
-
+import static de.caydenno1.xacrypto.zekerrijndael.Global.Galois.*;
import java.util.Arrays;
import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.*;
@@ -61,6 +61,64 @@ public final class AES implements BlockCipher {
return o;
}
+ public byte[] decryptBlock(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, m);
+
+ for (int r = m - 1 ; r > 0 ; r--) {
+ invShift(s);
+ invSub(s);
+ addRoundKey(s, r);
+ invMC(s);
+ }
+
+ invShift(s);
+ invSub(s);
+ addRoundKey(s, 0);
+
+ byte[] o = new byte[16];
+ for (int i = 0 ; i < 16 ; i++) o[i] = s[i & 3][i >> 2];
+
+
+ return o;
+ }
+
+ private static void invSub(byte[][] s) {
+ for (int _0 = 0 ; _0 < 4 ; _0++) for (int _1 = 0 ; _1 < 4 ; _1++) s[_0][_1] = (byte) ARIA_XB1 /*for some reason ARIA's Inverse 1 Box is the same as AES's Inverse SBOX?*/ [s[_0][_1] & 0xFF];
+ }
+
+ private static void invShift(byte[][] s) {
+ byte t;
+
+ for (int _0 = 1 ; _0 < 4 ; _0++) {
+ byte[] _1 = new byte[4];
+
+ for (int _2 = 0 ; _2 < 4 ; _2++) _1[(_2 + _0) % 4] = s[_0][_2];
+ for (int _2 = 0 ; _2 < 4 ; _2++) s[_0][_2] = _1[_2];
+ }
+ }
+
+ private static void invMC(byte[][] s) {
+ for (int _0 = 0; _0 < 4; _0++) {
+ byte a0 = s[0][_0]; byte a1 = s[1][_0]; byte a2 = s[2][_0]; byte a3 = s[3][_0];
+
+ s[0][_0] = (byte)(gm14(a0) ^ gm11(a1) ^ gm13(a2) ^ gm9(a3));
+ s[1][_0] = (byte)(gm9(a0) ^ gm14(a1) ^ gm11(a2) ^ gm13(a3));
+ s[2][_0] = (byte)(gm13(a0) ^ gm9(a1) ^ gm14(a2) ^ gm11(a3));
+ s[3][_0] = (byte)(gm11(a0) ^ gm13(a1) ^ gm9(a2) ^ gm14(a3));
+ }
+ }
+
// private void sub(byte[][] s) {
// for (int c = 0; c < 4; c++) {
// for (int r = 0; r < 4; r++) {
@@ -115,14 +173,7 @@ public final class AES implements BlockCipher {
}
}
- 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++) {
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java
index 1a7db74..0befc9c 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/GHASH.java
@@ -14,24 +14,23 @@ public class GHASH {
}
public byte[] compute(byte[] aad, byte[] cip){
- byte[] Y = new byte[16];
- Y = proc(Y, aad);
+ byte[] Y = proc(new byte[16], aad);
Y = proc(Y, cip);
byte[] lenBlock = buildLenBlock(
aad.length * 8L,
cip.length * 8L
);
- Y = xor(Y, lenBlock);
+ xor(Y, lenBlock);
Y = multi(Y,H);
return Y;
}
private byte[] proc(byte[] Y, byte[] in) {
+ byte[] bloc = new byte[16];
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);
+ xor(Y, bloc);
Y = multi(Y, H);
}
return Y;
@@ -43,13 +42,13 @@ public class GHASH {
int byindex = bit / 8;
int biindex = 7 - (bit%8);
- if (((X[byindex] >> biindex) & 1) == 1) Z = xor(Z,V);
+ if (((X[byindex] >> biindex) & 1) == 1) xor(Z,V);
boolean isLSB1 = (V[15] & 1) != 0;
RS(V);
- if (isLSB1) V = xor(V,UnchangingData.R);
+ if (isLSB1) xor(V,UnchangingData.R);
}
return Z;
}
@@ -64,7 +63,6 @@ public class GHASH {
}
}
public byte[] compNonce(byte[] H, byte[] nonce){
- byte[] Y = new byte[16];
byte[] blk = new byte[16];
int len = nonce.length;
@@ -90,9 +88,7 @@ public class GHASH {
blk[i] = (byte) ((bL >>> (8 * (15-i))) & 0xFF);
}
- Y = xor(Y,blk);
- Y = multi(Y, H);
- return Y;
+ return multi(blk, H);
}
private byte[] buildLenBlock(long aad, long cipb) {
ByteBuffer buf = ByteBuffer.allocate(16);
@@ -103,8 +99,7 @@ public class GHASH {
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;
+ for (int i = 0 ; i < 16 ; i++) a[i] ^= b[i];
+ return a;
}
}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java
index 5a96e25..716d8ee 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/AESGCM.java
@@ -18,16 +18,13 @@ interface AESCipher {
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);
+ byte[] H = aes.encryptBlock(new byte[16]);
GHASH gh = new GHASH(H);
+ byte[] J0;
if (nonce.length == 12) {
+ J0 = new byte[16];
System.arraycopy(nonce, 0, J0, 0, 12);
J0[15] = 1;
} else {
@@ -63,14 +60,13 @@ public class AESGCM implements AESCipher {
};
}
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);
+ byte[] H = aes.encryptBlock(new byte[16]);
GHASH gh = new GHASH(H);
+ byte[] J0;
if (nonce.length == 12) {
+ J0 = new byte[16];
System.arraycopy(nonce, 0, J0, 0, 12);
J0[15] = 1;
} else {
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/CamelliaGCM.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/CamelliaGCM.java
new file mode 100644
index 0000000..d9c290f
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/CamelliaGCM.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.Global.Camellia;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class CamelliaGCM extends GCM {
+ public CamelliaGCM(byte[] key) throws XACryptoException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ super(new Camellia(key));
+ }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java
index 6a33299..b114cb3 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/SerpentGCM.java
@@ -2,7 +2,7 @@ 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.Serpent;
+import de.caydenno1.xacrypto.zekerrijndael.Global.Serpent;
import java.lang.reflect.InvocationTargetException;
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java
index 1b24d58..f5fdda4 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/TwofishGCM.java
@@ -2,7 +2,7 @@ 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 de.caydenno1.xacrypto.zekerrijndael.Global.Twofish;
import java.lang.reflect.InvocationTargetException;
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java
index c8f86a1..b38013a 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Aria.java
@@ -53,33 +53,29 @@ public class Aria {
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);
+ A(encRK[i], decRK[round - i]);
}
}
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);
+ SL1(state, state);
} else {
- SL2(state, _0);
+ SL2(state, state);
}
- A(_0, state);
+ A(state, state);
}
AriaXOR(state, rK[round-1]);
if((round-1) % 2 == 0) {
- SL1(state, _0);
+ SL1(state, state);
} else {
- SL2(state, _0);
+ SL2(state, state);
}
- AriaXOR(_0, rK[round], state);
+ AriaXOR(state, rK[round], state);
}
private void AriaXOR(byte[] blk, byte[] key){
@@ -110,17 +106,15 @@ public class Aria {
}
// 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);
+ AriaXOR(i, ck, o);
+ SL1(o, o);
+ A(o, 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);
+ AriaXOR(i, ck, o);
+ SL2(o, o);
+ A(o, o);
}
private void SL1(byte[] i,byte[] o){
@@ -176,62 +170,59 @@ public class Aria {
FO(W[2], CK[3], W[3]);
AriaXOR(W[3], W[1], W[3]);
- byte[] _0 = new byte[16];
+ SROTR128(W[1], 19, encRK[0]);
+ AriaXOR(W[0], encRK[0], encRK[0]);
- SROTR128(W[1], 19, _0);
- AriaXOR(W[0], _0, encRK[0]);
+ SROTR128(W[2], 19, encRK[1]);
+ AriaXOR(W[1], encRK[1], encRK[1]);
- SROTR128(W[2], 19, _0);
- AriaXOR(W[1], _0, encRK[1]);
+ SROTR128(W[3], 19, encRK[2]);
+ AriaXOR(W[2], encRK[2], encRK[2]);
- SROTR128(W[3], 19, _0);
- AriaXOR(W[2], _0, encRK[2]);
+ SROTR128(W[0], 19, encRK[3]);
+ AriaXOR(encRK[3], W[3], encRK[3]);
- SROTR128(W[0], 19, _0);
- AriaXOR(_0, W[3], encRK[3]);
+ SROTR128(W[1], 31, encRK[4]);
+ AriaXOR(W[0], encRK[4], encRK[4]);
- SROTR128(W[1], 31, _0);
- AriaXOR(W[0], _0, encRK[4]);
+ SROTR128(W[2], 31, encRK[5]);
+ AriaXOR(W[1], encRK[5], encRK[5]);
- SROTR128(W[2], 31, _0);
- AriaXOR(W[1], _0, encRK[5]);
+ SROTR128(W[3], 31, encRK[6]);
+ AriaXOR(W[2], encRK[6], encRK[6]);
- SROTR128(W[3], 31, _0);
- AriaXOR(W[2], _0, encRK[6]);
+ SROTR128(W[0], 31, encRK[7]);
+ AriaXOR(encRK[7], W[3], encRK[7]);
- SROTR128(W[0], 31, _0);
- AriaXOR(_0, W[3], encRK[7]);
+ SROTR128(W[1], 128 - 61, encRK[8]);
+ AriaXOR(W[0], encRK[8], encRK[8]);
- SROTR128(W[1], 128 - 61, _0);
- AriaXOR(W[0], _0, encRK[8]);
+ SROTR128(W[2], 128 - 61, encRK[9]);
+ AriaXOR(W[1], encRK[9], encRK[9]);
- SROTR128(W[2], 128 - 61, _0);
- AriaXOR(W[1], _0, encRK[9]);
+ SROTR128(W[3], 128 - 61, encRK[10]);
+ AriaXOR(W[2], encRK[10], encRK[10]);
- SROTR128(W[3], 128 - 61, _0);
- AriaXOR(W[2], _0, encRK[10]);
+ SROTR128(W[0], 128 - 61, encRK[11]);
+ AriaXOR(encRK[11], W[3], encRK[11]);
- SROTR128(W[0], 128 - 61, _0);
- AriaXOR(_0, W[3], encRK[11]);
-
- SROTR128(W[1], 128 - 31, _0);
- AriaXOR(W[0], _0, encRK[12]);
+ SROTR128(W[1], 128 - 31, encRK[12]);
+ AriaXOR(W[0], encRK[12], encRK[12]);
if (round >= 14) {
- SROTR128(W[2], 128 - 31, _0);
- AriaXOR(W[1], _0, encRK[13]);
+ SROTR128(W[2], 128 - 31, encRK[13]);
+ AriaXOR(W[1], encRK[13], encRK[13]);
- // ek15 = W2 ^ (W3 <<< 31)
- SROTR128(W[3], 128 - 31, _0);
- AriaXOR(W[2], _0, encRK[14]);
+ SROTR128(W[3], 128 - 31, encRK[14]);
+ AriaXOR(W[2], encRK[14], encRK[14]);
}
if (round == 16) {
- SROTR128(W[0], 128 - 31, _0);
- AriaXOR(_0, W[3], encRK[15]);
+ SROTR128(W[0], 128 - 31, encRK[15]);
+ AriaXOR(encRK[15], W[3], encRK[15]);
- SROTR128(W[1], 128 - 19, _0);
- AriaXOR(W[0], _0, encRK[16]);
+ SROTR128(W[1], 128 - 19, encRK[16]);
+ AriaXOR(W[0], encRK[16], encRK[16]);
}
}
@@ -249,22 +240,24 @@ public class Aria {
}
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]);
+ byte[] _0 = o;
+ if (i == o) _0 = new byte[16];
+ _0[0] = (byte)(i[3] ^ i[4] ^ i[9] ^ i[14]);
+ _0[1] = (byte)(i[2] ^ i[5] ^ i[8] ^ i[15]);
+ _0[2] = (byte)(i[1] ^ i[6] ^ i[11] ^ i[12]);
+ _0[3] = (byte)(i[0] ^ i[7] ^ i[10] ^ i[13]);
+ _0[4] = (byte)(i[0] ^ i[5] ^ i[11] ^ i[14]);
+ _0[5] = (byte)(i[1] ^ i[4] ^ i[10] ^ i[15]);
+ _0[6] = (byte)(i[2] ^ i[7] ^ i[9] ^ i[12]);
+ _0[7] = (byte)(i[3] ^ i[6] ^ i[8] ^ i[13]);
+ _0[8] = (byte)(i[1] ^ i[7] ^ i[11] ^ i[13]);
+ _0[9] = (byte)(i[0] ^ i[6] ^ i[10] ^ i[12]);
+ _0[10] = (byte)(i[3] ^ i[5] ^ i[9] ^ i[15]);
+ _0[11] = (byte)(i[2] ^ i[4] ^ i[8] ^ i[14]);
+ _0[12] = (byte)(i[2] ^ i[6] ^ i[9] ^ i[14]);
+ _0[13] = (byte)(i[3] ^ i[7] ^ i[8] ^ i[15]);
+ _0[14] = (byte)(i[0] ^ i[4] ^ i[11] ^ i[12]);
+ _0[15] = (byte)(i[1] ^ i[5] ^ i[10] ^ i[13]);
+ if (i == o) System.arraycopy(_0, 0, o, 0, 16);
}
}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/Camellia.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Camellia.java
similarity index 95%
rename from src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/Camellia.java
rename to src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Camellia.java
index 01322ce..eaf31d6 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/ciphers/Camellia.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Camellia.java
@@ -1,4 +1,4 @@
-package de.caydenno1.xacrypto.zekerrijndael.GCM.ciphers;
+package de.caydenno1.xacrypto.zekerrijndael.Global;
import de.caydenno1.xacrypto.misc.XACryptoException;
import de.caydenno1.xacrypto.zekerrijndael.UnchangingData;
@@ -18,6 +18,10 @@ public class Camellia implements CamelliaCipher {
genKeySchedule(key);
}
+ public byte[] encryptBlock(byte[] in) {
+ return encryptBlock(in, 0, new byte[16], 0);
+ }
+
@Override
public byte[] encryptBlock(byte[] in, int inputOffset, byte[] out, int outOffset) {
long d1 = bytes2Long(in, inputOffset);
@@ -78,8 +82,12 @@ public class Camellia implements CamelliaCipher {
}
public byte[] decryptBlock(byte[] in) {
- long d1 = bytes2Long(in, 0);
- long d2 = bytes2Long(in, 8);
+ return decryptBlock(in, 0, new byte[16], 0);
+ }
+
+ public byte[] decryptBlock(byte[] in, int inputOffset, byte[] out, int outOffset) {
+ long d1 = bytes2Long(in, inputOffset);
+ long d2 = bytes2Long(in, inputOffset + 8);
if (subkeys.length == 34) {
d1 ^= subkeys[32];
@@ -129,10 +137,9 @@ public class Camellia implements CamelliaCipher {
d2 ^= subkeys[0];
d1 ^= subkeys[1];
- byte[] o = new byte[16];
- long2Bytes(d2, o, 0);
- long2Bytes(d1, o, 8);
- return o;
+ long2Bytes(d2, out, outOffset);
+ long2Bytes(d1, out, outOffset + 8);
+ return out;
}
private void genKeySchedule(byte[] key) {
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Galois.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Galois.java
new file mode 100644
index 0000000..3fd43c7
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Galois.java
@@ -0,0 +1,10 @@
+package de.caydenno1.xacrypto.zekerrijndael.Global;
+
+public class Galois {
+ public static byte gm2(byte b) { return (byte)(((((b & 0xFF) << 1) & 0xFF) ^ (((b & 0xFF) & 0x80) != 0 ? 0x1b : 0))); }
+ public static byte gm3(byte b) { return (byte)(gm2(b) ^ b); }
+ public static byte gm9(byte b) { byte g2 = gm2(b); byte g4 = gm2(g2); return (byte)(gm2(g4) ^ b); }
+ public static byte gm11(byte b) { byte g2 = gm2(b); byte g4 = gm2(g2); return (byte)(gm2(g4) ^ g2 ^ b); }
+ public static byte gm13(byte b) { byte g2 = gm2(b); byte g4 = gm2(g2); return (byte)(gm2((byte) (g4 ^ b)) ^ b); }
+ public static byte gm14(byte b) { byte g2 = gm2(b); byte g4 = gm2(g2); return (byte)(gm2((byte) (g4 ^ b)) ^ g2); }
+}
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/LE32.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/LE32.java
new file mode 100644
index 0000000..54429b5
--- /dev/null
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/LE32.java
@@ -0,0 +1,6 @@
+package de.caydenno1.xacrypto.zekerrijndael.Global;
+
+public class LE32 {
+ public 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); }
+ public static void write32LE(int v, byte[] b, int off) { for (int i = 0 ; i < 4 ; i++) b[off + i] = (byte) (v >>> (i * 8)); }
+}
\ No newline at end of file
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/Serpent.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Serpent.java
similarity index 96%
rename from src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/Serpent.java
rename to src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Serpent.java
index 47be5c7..9704315 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/Serpent.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Serpent.java
@@ -1,6 +1,7 @@
-package de.caydenno1.xacrypto.zekerrijndael.GCM;
+package de.caydenno1.xacrypto.zekerrijndael.Global;
import de.caydenno1.xacrypto.misc.XACryptoException;
+import de.caydenno1.xacrypto.zekerrijndael.GCM.BlockCipher;
import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SERPENT_SBOX;
import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.SERPENT_IBOX;
@@ -71,6 +72,7 @@ public class Serpent implements SerpentCipher {
w[i] = Integer.rotateLeft(_0, 11);
}
+ byte[] kb = new byte[16];
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] };
@@ -78,7 +80,6 @@ public class Serpent implements SerpentCipher {
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]);
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/Twofish.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Twofish.java
similarity index 81%
rename from src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/Twofish.java
rename to src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Twofish.java
index cf3900a..841ddca 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/GCM/Twofish.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/Global/Twofish.java
@@ -1,9 +1,10 @@
-package de.caydenno1.xacrypto.zekerrijndael.GCM;
+package de.caydenno1.xacrypto.zekerrijndael.Global;
import de.caydenno1.xacrypto.misc.XACryptoException;
import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.TWOFISH_Q0;
import static de.caydenno1.xacrypto.zekerrijndael.UnchangingData.TWOFISH_Q1;
+import static de.caydenno1.xacrypto.zekerrijndael.Global.LE32.*;
public class Twofish {
private final int[] K = new int[40];
@@ -79,9 +80,8 @@ public class Twofish {
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 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);
@@ -89,7 +89,7 @@ public class Twofish {
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;
+ X[3] = Integer.rotateLeft(X[3], 1) ^ f1;
t0 = h(X[2], S, kW);
t1 = h(Integer.rotateLeft(X[3], 8), S, kW);
@@ -106,8 +106,37 @@ public class Twofish {
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)); };
+ public byte[] decryptBlock(byte[] in) throws XACryptoException {
+ if (in.length != 16) throw new XACryptoException("min block size is 16 (twofish) :(",(int)in.length);
+ int[] X = new int[4];
+
+ X[2] = read32LE(in, 0) ^ K[4];
+ X[3] = read32LE(in, 4) ^ K[5];
+ X[0] = read32LE(in, 8) ^ K[6];
+ X[1] = read32LE(in, 12) ^ K[7];
+
+ for (int r = 14 ; r >= 0 ; r -= 2) {
+ int t0 = h(X[2], S, kW);
+ int t1 = h(Integer.rotateLeft(X[3], 8), S, kW);
+ int f0 = t0 + t1 + K[2 * r + 10];
+ int f1 = t0 + 2 * t1 + K[2 * r + 11];
+ X[0] = Integer.rotateLeft(X[0], 1) ^ f0;
+ X[1] = Integer.rotateRight(X[1] ^ f1, 1);
+
+ t0 = h(X[0], S, kW);
+ t1 = h(Integer.rotateLeft(X[1], 8), S, kW);
+ f0 = t0 + t1 + K[2 * r + 8];
+ f1 = t0 + 2 * t1 + K[2 * r + 9];
+ X[2] = Integer.rotateLeft(X[2], 1) ^ f0;
+ X[3] = Integer.rotateRight(X[3] ^ f1, 1);
+ }
+
+ byte[] o = new byte[16];
+ for (int i = 0 ; i < 4 ; i++) write32LE(X[i] ^ K[i], o, i*4);
+
+ return o;
+ }
+
private static int gfMultMDS(int a, int b) {
int p = 0;
for (int i = 0 ; i < 8 ; i++) {
diff --git a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java
index 3df3135..9fccaca 100644
--- a/src/main/java/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java
+++ b/src/main/java/de/caydenno1/xacrypto/zekerrijndael/UnchangingData.java
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b8b3cf3379dbb436a894945a7299a5e3be30844ac377df5a21f1c2cbb0a15b0b
-size 52205
+oid sha256:12a94c0f13fc7db573b00189bdb09c18a78a8e3540796df122d79321a5018aa2
+size 52301