mirror of
https://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto.git
synced 2026-08-21 13:36:21 -04:00
Zeker rijndael (#10)
* Update README.md (#2) * AES128.java + UnchangedData.java * Several ciphers, alot of ZekerRijndael progress * maak de j0-functie aan * maak een inc32-functie aan * progress! * GCM.java complete! * my dementia .. lol * SM4 COMPLET! * decryption bugfix * easy making these were so easy, just had to copy and paste AES128 and change like 5 numbers * read desc i feel sick. i made the rest of the functions dummy functions and will finish them in the future. i am unsure if i will continue working on this tomorrow, i may take a break or i may not, who knows. * F func finished in Camellia. several bugfixes feel much better btw, took a shower and slept :) * FL don would recommend deleting .idea when you clone. FL done * Camellia Camellia complete * add factory * bugfix,more consise * Fixed very annoying seperate AES<bitcount>.java files into one unified AES.java file :D (#4) * AES.java potential * Update AES.java bufxie * remove old libs removed old AES$.java files as they are deprecated now that AES.java is created. (AES.java should be 100% functional.) * Update Factories.java aaand rename the AES128 factory to use AES with bits:128 instead of AES128 * Update AES.java Performance Enhancements PKCS#7 OK! Safety (missing bounds protection) * Update README.md (#5) * Update AES.java ah yes i love things magically stop working after PR ! :P * something idk my head is hurting again! :D so fun. i might make AESGCM.java use GHASH.java's xor function if i can figure out why its not working. also AESGCM.java (in its current state) sucks. i need to work on it a bit but just not now. * update gitignore * uh how did it break? i didnt even change either of those files since they were working * very legit solution 4realz1 * useless * fix (#7) * GHASH compnonce + fixed AESGCM bugs * Update AES.java some fixes. * Update AESGCM.java add warning * Camelia performance enhancements + decryption (i forgot to add it before lol) + several bugfixes * "It's not a disaster, It's innovation!" * decryption + bufixes * Update Project_Default.xml * this isnt English class * Update README.md it duplicated itself lol * desc Aria.java progress, next commit will have GRK finished * Aria.java complete! * desc added support for Camelia 192 + 256 bit operation, perf enhancements and bugfixes * add ARIAGCM factory my wrapper in ARIAGCM handles GCM :) * Update README.md add TODO * added 128,192,256 support for AESGCM * desc soo... did you know sometimes you actually do want to reuse code without getting 68 warnings from intellij? * note+camellia tab * began Serpant.java * Serpent COMPLET! * desc add dummy functions to twofish * Update Twofish.java progrses on twofish + HUMOR * twofish done + readme upd * HOLY i actually finished Blowfish.java lol, almost done with ECB, just neeed 2 functions * Bfish ECB done! :D * desc - fix typo - add Aria.java support for Aria-ECB - move Aria.java to globalpackaeg * Create AriaECB.java will finish this tmr. im so tired lol * desc ariaecb complete, also forgot to add factories for blowfish too * Update AriaECB.java * sm4ecb complete
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
**/Constants.java filter=lfs diff=lfs merge=lfs -text
|
||||||
|
**/UnchangingData.java filter=lfs diff=lfs merge=lfs -text
|
||||||
@@ -4,7 +4,12 @@ out/
|
|||||||
!**/src/test/**/out/
|
!**/src/test/**/out/
|
||||||
.kotlin
|
.kotlin
|
||||||
XACrypto.jar
|
XACrypto.jar
|
||||||
|
<<<<<<< HEAD
|
||||||
|
tests
|
||||||
|
.idea/
|
||||||
|
=======
|
||||||
.idea
|
.idea
|
||||||
|
>>>>>>> main
|
||||||
|
|
||||||
### Eclipse ###
|
### Eclipse ###
|
||||||
.apt_generated
|
.apt_generated
|
||||||
|
|||||||
Generated
+4
@@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<<<<<<< HEAD
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_26_PREVIEW" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
|
||||||
|
=======
|
||||||
<component name="MavenProjectsManager">
|
<component name="MavenProjectsManager">
|
||||||
<option name="originalFiles">
|
<option name="originalFiles">
|
||||||
<list>
|
<list>
|
||||||
@@ -9,6 +12,7 @@
|
|||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" default="true" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" default="true" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
|
||||||
|
>>>>>>> main
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -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.
|
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)
|
### Current Objective: ZekerRijndael (custom from-scratch AES-128 block cipher)
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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); }
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<in.length) cnt = inc32(cnt);
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
private static byte[] inc32(byte[] b) {
|
||||||
|
byte[] o = Arrays.copyOf(b,16);
|
||||||
|
for (int i = 15; i >= 12; i--) if (++o[i] != 0) break;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.caydenno1.xacrypto.zekerrijndael.GCM;
|
||||||
|
|
||||||
|
public record Result(byte[] cip, byte[] tag) {}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)); }
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -7,4 +7,17 @@ public class ROT {
|
|||||||
public static int ROTL(int x, int n){
|
public static int ROTL(int x, int n){
|
||||||
return (x << n) | (x >>> (32 - 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,6 +77,4 @@ public class SHA1 {
|
|||||||
byte[] result = hash(data.getBytes(StandardCharsets.UTF_8));
|
byte[] result = hash(data.getBytes(StandardCharsets.UTF_8));
|
||||||
return hex(result);
|
return hex(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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.hash;
|
||||||
import static de.caydenno1.xacrypto.hash.sha256.Hex.doubleHash;
|
import static de.caydenno1.xacrypto.hash.sha256.Hex.doubleHash;
|
||||||
import static de.caydenno1.xacrypto.hash.ROT.ROTR;
|
import static de.caydenno1.xacrypto.hash.ROT.ROTR;
|
||||||
|
import de.caydenno1.xacrypto.misc.ToM;
|
||||||
|
|
||||||
public final class SHA256 {
|
public final class SHA256 {
|
||||||
private SHA256(){}
|
private SHA256(){}
|
||||||
@@ -88,14 +89,6 @@ public final class SHA256 {
|
|||||||
return o;
|
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<byte[][]>{
|
public static final class HashTask extends RecursiveTask<byte[][]>{
|
||||||
private final java.util.List<byte[]> leaves;
|
private final java.util.List<byte[]> leaves;
|
||||||
private int from,to;
|
private int from,to;
|
||||||
|
|||||||
Binary file not shown.
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,10 @@ public class XACryptoException extends Exception {
|
|||||||
super(res);
|
super(res);
|
||||||
this.id = id & 0xFF;
|
this.id = id & 0xFF;
|
||||||
}
|
}
|
||||||
|
public XACryptoException(String res, int iid) {
|
||||||
|
super(res);
|
||||||
|
this.id = iid;
|
||||||
|
}
|
||||||
public XACryptoException(String[] pnts, byte id){
|
public XACryptoException(String[] pnts, byte id){
|
||||||
super(String.join("|", pnts));
|
super(String.join("|", pnts));
|
||||||
this.id = id & 0xFF;
|
this.id = id & 0xFF;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user