Author SHA1 Message Date
Xiao X 24053527b1 Ciphers (#17)
* add AES.java additions + Galois.java

* desc

used ECB and ECBExceptionless instead of seperate interfaces. AESECB done

* Twofish ECB developments, moved some files

* twofishecb done

* Update Factories.java

factories.java topology rewrite 👍

* Update Factories.java

fix whitespace + forgot to add AriaGCM + SerpentGCM

* desc

RC6ECB.java placeholders,
LE32.java

* encblk+decblk funcs

* RC6 done

* desc

- move Camellia to seperate
- create CamelliaECB (it sucks, will fix it more after)

* good fixes!

* Rmv 16bfix (#14)

* progress

some progress was made. next commit will be working on Aria.java (its large so may take some time)

* "invalid config"

* Update Aria.java

potential working!

* bugfix

* Sha224 fix (#15)

* Update SHA224.java

potential fix

* Update pom.xml

tested - works now!
the entire fix was adding * 8L to the padding calculator thing xD

* SHA384 is working

LESGO!

* Create SHA512.java

* Sha512 impl (#16)

* desc
* Update SHA512.java

* Update SHA512.java

oookay a bit of opencode and a lot of time later its solved!
2026-06-19 14:44:12 -04:00
Xiao X 91586225c5 Implement SHA224 (#11)
* start of sha224 implements, tho quite simple

* Update pom.xml

just to make it compile main for testing, simplifies the process
2026-06-04 18:12:34 -04:00
xiao da2dd6c11f Delete release.yml
so it compiles completely fine on my computer but not on the github one? very cool
2026-06-04 16:42:22 -04:00
xiao 2619172c48 oh my god please work 2026-06-04 16:39:21 -04:00
Xiao X 30bd9e78a0 intelligence on my part 2026-06-04 16:37:43 -04:00
xiao 0315a8b3ef update ver 2026-06-04 16:32:50 -04:00
xiao 3d203f9a15 Add release workflow 2026-06-04 07:19:13 -04:00
xiao 08d0c0be83 Update pom.xml
more config fix
2026-06-04 07:16:46 -04:00
Xiao X c8f6b63e60 fix pom 2026-06-04 07:13:46 -04:00
xiao cd3fae4eb0 fix file directories after merge + config changes 2026-06-03 06:44:40 -04:00
xiao b01b8cf8df desc
i have no idea why it kept the headers there even though i fixed them. should be all good now tho
2026-06-02 12:42:44 -04:00
Xiao X b0adddf70f READMe update 2026-06-02 12:36:59 -04:00
Xiao X 413b038b8a 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
2026-06-02 12:34:10 -04:00
xiao 8561029b26 updates 2026-06-02 12:03:54 -04:00
denis e53c8d02af Maven (#9) 2026-06-02 11:58:08 -04:00
xiao 3051825098 Update README.md 2026-05-27 22:06:30 -04:00
xiao 5eb5cc6096 Update README.md 2026-05-27 21:37:48 -04:00
xiao 4f159c68be SHA1 fully tested + working 2026-05-27 21:33:31 -04:00
xiao 3eb755bc90 read note in readme 2026-05-27 20:51:32 -04:00
xiao 981f3ea46e Update README.md 2026-05-27 19:40:58 -04:00
xiao 58d5a74c89 Update README.md 2026-05-27 19:03:04 -04:00
Xiao X 44859407cf Sha256 > Main (#1)
* Update SHA256Advanced.java

ByteFromHex function

* OH MY GOD

45 mins of coding. my brain hurts lol. its likely i will move sha256 to its own package inside of hash as Digest and several other classes will be included in it so instead of plopping them inside of misc i think ill use a standalone package. thanks for reading my rant

* several sha components

finally made sha256 standalone package, added classes:
HMAC
HKDF (placeholder for now)
Hex
Digest too but i did that last night

* desc

maybe it done

* Update README.md

* COMPLETION!

XACrypto\SHA256 is officially finished in its entirety. I might still make more modifications tho lol

* Update XACrypto.java

yippie! i made a dumb mistake

* bug fix

TWO. GOD. DAMN. CHARACTERS. completely messed up the end hash. i used 0 instead of i inside a for loop. i want to die :)

* remove tests + update README + good riddance garbage messagedigest sha256

yip
2026-05-27 19:01:40 -04:00
xiao 00d816ad17 i love rushing and making stupid mistakes!! 2026-05-26 16:13:07 -04:00
xiao eb8d304950 add Byte2Hex function 2026-05-26 13:13:17 -04:00
Xiao X 42707d9aa2 Update README to reflect project completion status 2026-05-26 08:43:08 -04:00
xiao bb8e69b8f6 Merge branch 'main' of https://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto 2026-05-26 07:58:48 -04:00
Xiao X 6e1424b6c4 README.md aktualisieren
README.md aktualisieren

fix linebreak

README.md aktualisieren

README modifications
2026-05-26 07:56:36 -04:00
Xiao X 6fabe84e69 README.md aktualisieren 2026-05-26 07:42:43 -04:00
Xiao X 984d2e057d README.md aktualisieren
fix linebreak
2026-05-26 07:34:58 -04:00
Xiao X 6ac42fd6ed README.md aktualisieren 2026-05-26 07:31:48 -04:00
xiao f2b4e1600a Update SHA256Advanced.java
made some progress, planning to add several hash functions + Digest(ion)
2026-05-26 07:24:12 -04:00
Xiao X acb4c3715d Constants.java aktualisieren 2026-05-25 23:25:39 -04:00
xiao bce829a4cc read desc for info
SHA256.java is the MessageDigest usage, it sucks, don't use it.

SHA256Advanced.java is my custom interpretation but i don't have the time right now to finish it so for now it will sadly be a placeholder.
2026-05-25 23:19:27 -04:00
xiao 40cfcd3fdf Update README.md
i rushed to do this in 5 minutes before having to leave lmao, fixing it now !!
2026-05-25 22:59:42 -04:00
Xiao X eba17f0a7e README.md aktualisieren 2026-05-25 22:36:14 -04:00
Xiao X bc3809f2f5 add instructions for compilation 2026-05-25 22:29:01 -04:00
xiao 6983056feb Merge branch 'main' of https://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto 2026-05-25 22:21:54 -04:00
xiao 177b406746 Update .gitignore 2026-05-25 22:21:50 -04:00
Xiao X aab1592b67 Create README.md 2026-05-25 22:21:26 -04:00
58 changed files with 3643 additions and 86 deletions
+2
View File
@@ -0,0 +1,2 @@
**/Constants.java filter=lfs diff=lfs merge=lfs -text
**/UnchangingData.java filter=lfs diff=lfs merge=lfs -text
+7 -1
View File
@@ -3,6 +3,9 @@ out/
!**/src/main/**/out/
!**/src/test/**/out/
.kotlin
XACrypto.jar
tests
.idea
### Eclipse ###
.apt_generated
@@ -27,4 +30,7 @@ bin/
.vscode/
### Mac OS ###
.DS_Store
.DS_Store
### Maven ###
target/
+16
View File
@@ -0,0 +1,16 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="XACrypto-Primair Profiel" value="XACrypto Primair" />
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,java.lang.foreign.Arena,ofAuto,java.lang.foreign.Arena,global,java.util.concurrent.ForkJoinPool,commonPool" />
</inspection_tool>
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
<inspection_tool class="GrazieStyle" enabled="false" level="STYLE_SUGGESTION" enabled_by_default="false" />
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>
+15 -1
View File
@@ -1,6 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" default="true" project-jdk-name="openjdk-26" project-jdk-type="JavaSDK">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager"
version="2"
languageLevel="JDK_26_PREVIEW"
project-jdk-name="openjdk-26"
project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
Generated
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
</component>
</project>
+18
View File
@@ -0,0 +1,18 @@
A multi-purpose Cryptography library in Java. Working on it day by day, slowly. Someday this will be complete, today is not that day.
To be clear, this is **NOT** mean't to be a replacement/alternative to BouncyCastle. Instead, it is meant to include what BouncyCastle does not have. No code was taken from OpenSSL or BouncyCastle for that reason.
### Current Objective: ZekerRijndael (custom encryption sub-library)
Use `setopt interactivecomments` (zsh only) to allow using `#` for comments if you see errors like `zsh: command not found: #`
Ensure Java + javac are installed, on MacOS it can be installed with Homebrew by running `brew install openjdk`
You will also need maven installed. With Homebrew, this can be installed with `brew install maven`.
To compile (these commands should work universally):
1. git clone https://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto.git # download the git repository
2. cd XACrypto # enter the directory
3. mvn clean package # compile the package cleanly
You should find the built jar at target/XACrypto-1.0-SNAPSHOT.jar
+3 -6
View File
@@ -1,11 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+147
View File
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.caydenno1.xacrypto</groupId>
<artifactId>xacrypto</artifactId>
<version>2026.06.19_R1</version>
<name>XACrypto</name>
<description>A multi-purpose Cryptography library in Java.</description>
<url>https://ga-bv.mathai.cloud/</url>
<licenses>
<license>
<name>MIT License</name>
<url>https://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>QXIoa</id>
<name>Xiao Xiong</name>
</developer>
</developers>
<scm>
<connection>scm:git:https://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto.git</connection>
<developerConnection>scm:git:ssh://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto.git</developerConnection>
<url>https://github.com/Geprivilegieerde-Anonimiteit-BV/XACrypto</url>
<tag>HEAD</tag>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>25</maven.compiler.release>
<junit.version>5.11.0</junit.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.14.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>de.caydenno1.xacrypto.XACrypto</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.11.2</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.9.0</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
<autoPublish>true</autoPublish>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,52 +0,0 @@
package de.caydenno1.xacrypto.encryption;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.SecureRandom;
import java.util.Base64;
public class AES_GCM {
private static final String AES = "AES";
private static final String AES_GCM = "AES/GCM/NoPadding";
private AES_GCM() {}
public static SecretKey genKey(int bits) throws Exception {
KeyGenerator g = KeyGenerator.getInstance(AES);
g.init(bits);
return g.generateKey();
}
public static String encrypt(String pln, SecretKey k, int TAG, int IV) throws Exception {
byte[] iv = new byte[IV];
new SecureRandom().nextBytes(iv);
Cipher c = Cipher.getInstance(AES_GCM);
c.init(Cipher.ENCRYPT_MODE, k, new GCMParameterSpec(TAG, iv));
byte[] citext = c.doFinal(pln.getBytes());
byte[] comb = new byte[iv.length + citext.length];
System.arraycopy(iv, 0, comb, 0, iv.length);
System.arraycopy(citext, 0, comb, iv.length, citext.length);
return Base64.getEncoder().encodeToString(comb);
}
public static String decrypt(String enc, SecretKey k, int TAG, int IV) throws Exception {
byte[] dat = Base64.getDecoder().decode(enc);
byte[] iv = new byte[IV];
byte[] cit = new byte[dat.length - IV];
System.arraycopy(dat, 0, iv, 0, IV);
System.arraycopy(dat, IV, cit, 0, cit.length);
Cipher ci = Cipher.getInstance(AES_GCM);
ci.init(Cipher.DECRYPT_MODE, k, new GCMParameterSpec(TAG, iv));
return new String(ci.doFinal(cit));
}
}
@@ -1,25 +0,0 @@
package de.caydenno1.xacrypto.misc;
public class Constants {
public int[] SHA256_K = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,
0x59f111f1,0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,
0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,
0xc19bf174,0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,
0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,0x983e5152,
0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,
0x06ca6351,0x14292967,0x27b70a85,0x2e1b2138,0x4d2c6dfc,
0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,
0xd6990624,0xf40e3585,0x106aa070,0x19a4c116,0x1e376c08,
0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,
0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,
0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
public int[] SHA256_H = {
0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,
0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19
};
// placeholder ,ignore
}
@@ -2,4 +2,6 @@ package de.caydenno1.xacrypto;
public class XACrypto {
private XACrypto() {}
static void main(String[] args) {}
}
@@ -0,0 +1,26 @@
package de.caydenno1.xacrypto.hash;
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));
}
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;
}
}
@@ -0,0 +1,79 @@
package de.caydenno1.xacrypto.hash.sha;
import de.caydenno1.xacrypto.misc.Constants;
import java.nio.charset.StandardCharsets;
import static de.caydenno1.xacrypto.hash.sha.Shared.INT2BYTE;
import static de.caydenno1.xacrypto.hash.sha.Shared.hex;
public class SHA0 {
// we really only need one file. very simple code
public static byte[] hash(byte[] data){
System.out.println("Beware, SHA0 is deprecated and cryptographically broken. Use at your own risk.");
byte[] padded = Shared.pad(data);
int a0 = Constants.SHA_H[0], a1 = Constants.SHA_H[1], a2 = Constants.SHA_H[2], a3 = Constants.SHA_H[3], a4 = Constants.SHA_H[4];
int[] w = new int[80];
for (int i = 0 ; i < padded.length ; i += 64) {
for (int j = 0 ; j < 16 ; j++) {
int o = i + j * 4;
w[j] = ((padded[o] & 0xff) << 24)
| ((padded[o + 1] & 0xff) << 16)
| ((padded[o + 2] & 0xff) << 8)
| (padded[o + 3] & 0xff);
}
for (int t = 16; t < 80; t++) {
w[t] = w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16];
}
int a = a0, b = a1, c = a2, d = a3, e = a4;
for (int t = 0 ; t < 80 ; t++) {
int f, k;
if (t < 20) {
f = (b & c);
k = Constants.SHA0_K[0];
} else if (t < 40) {
f = b ^ c ^ d;
k = Constants.SHA0_K[1];
} else if (t < 60) {
f = (b & c) | (b & d) | (c & d);
k = Constants.SHA0_K[2];
} else {
f = b ^ c ^ d;
k = Constants.SHA0_K[3];
}
int temp = de.caydenno1.xacrypto.hash.ROT.ROTL(a, 5);
temp += f;
temp += e;
temp += k;
temp += w[t];
e = d;
d = c;
c = de.caydenno1.xacrypto.hash.ROT.ROTL(b, 30);
b = a;
a = temp;
}
a0 += a;
a1 += b;
a2 += c;
a3 += d;
a4 += e;
}
return INT2BYTE(a0, a1, a2, a3, a4);
}
public static String hash(String data) {
byte[] result = hash(data.getBytes(StandardCharsets.UTF_8));
return hex(result);
}
}
@@ -0,0 +1,80 @@
package de.caydenno1.xacrypto.hash.sha;
import de.caydenno1.xacrypto.misc.Constants;
import de.caydenno1.xacrypto.hash.sha.Shared;
import java.nio.charset.StandardCharsets;
import static de.caydenno1.xacrypto.hash.sha.Shared.hex;
public class SHA1 {
public static byte[] hash(byte[] data){
byte[] padded = Shared.pad(data);
int a0 = Constants.SHA_H[0], a1 = Constants.SHA_H[1], a2 = Constants.SHA_H[2], a3 = Constants.SHA_H[3], a4 = Constants.SHA_H[4];
int[] w = new int[80];
for (int i = 0 ; i < padded.length ; i += 64) {
for (int j = 0 ; j < 16 ; j++) {
int o = i + j * 4;
w[j] = ((padded[o] & 0xff) << 24)
| ((padded[o + 1] & 0xff) << 16)
| ((padded[o + 2] & 0xff) << 8)
| (padded[o + 3] & 0xff);
}
for (int t = 16; t < 80; t++) {
w[t] = de.caydenno1.xacrypto.hash.ROT.ROTL(
w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16], 1
);
}
int a = a0, b = a1, c = a2, d = a3, e = a4;
for (int t = 0 ; t < 80 ; t++) {
int f, k;
if (t < 20) {
f = (b & c) | ((~b) & d);
k = Constants.SHA1_K[0];
} else if (t < 40) {
f = b ^ c ^ d;
k = Constants.SHA1_K[1];
} else if (t < 60) {
f = (b & c) | (b & d) | (c & d);
k = Constants.SHA1_K[2];
} else {
f = b ^ c ^ d;
k = Constants.SHA1_K[3];
}
int temp = de.caydenno1.xacrypto.hash.ROT.ROTL(a, 5);
temp += f;
temp += e;
temp += k;
temp += w[t];
e = d;
d = c;
c = de.caydenno1.xacrypto.hash.ROT.ROTL(b, 30);
b = a;
a = temp;
}
a0 += a;
a1 += b;
a2 += c;
a3 += d;
a4 += e;
}
return Shared.INT2BYTE(a0, a1, a2, a3, a4);
}
public static String hash(String data) {
byte[] result = hash(data.getBytes(StandardCharsets.UTF_8));
return hex(result);
}
}
@@ -0,0 +1,42 @@
package de.caydenno1.xacrypto.hash.sha;
public class Shared {
public static byte[] INT2BYTE(int a,int b,int c,int d,int e) {
byte[] out = new byte[20];
write(a, out, 0);
write(b, out, 4);
write(c, out, 8);
write(d, out, 12);
write(e, out, 16);
return out;
}
public static void write(int v, byte[] o, int i) {
o[i ] = (byte)(v >>> 24);
o[i+1] = (byte)(v >>> 16);
o[i+2] = (byte)(v >>> 8);
o[i+3] = (byte)(v );
}
public static byte[] pad(byte[] mesg) {
int len = mesg.length;
long bit = (long) len * 8;
int padL = (64 - ((len + 9) % 64)) % 64;
byte[] o = new byte[len+padL+9];
System.arraycopy(mesg,0,o,0,len);
o[len] = (byte) 0x80;
for (int i = 0; i < 8; i++) {
o[o.length - (i+1)] = (byte) (bit >>> (8*i));
}
return o;
}
public static String hex(byte[] data) {
StringBuilder builder = new StringBuilder();
for (byte b : data) builder.append(String.format("%02x", b));
return builder.toString();
}
}
@@ -0,0 +1,17 @@
package de.caydenno1.xacrypto.hash.sha224;
import java.nio.charset.StandardCharsets;
import static de.caydenno1.xacrypto.hash.sha224.SHA224.digest;
public class Digest {
public static String digestHex(String text) {
byte[] hash = digest(text.getBytes(StandardCharsets.UTF_8));
StringBuilder builder = new StringBuilder(hash.length * 2);
for (byte b : hash) builder.append(String.format("%02x", b & 0xFF));
return builder.toString();
}
}
@@ -0,0 +1,29 @@
package de.caydenno1.xacrypto.hash.sha224;
import static de.caydenno1.xacrypto.hash.ROT.ROTR;
public class Helpers {
public static int ch(int x, int y, int z) {
return (x & y) ^ (~x & z);
}
public static int maj(int x, int y, int z) {
return (x & y) ^ (x & z) ^ (y & z);
}
public static int bigSigma0(int x) {
return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22);
}
public static int bigSigma1(int x) {
return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25);
}
public static int smallSigma0(int x) {
return ROTR(x, 7) ^ ROTR(x, 18) ^ (x >>> 3);
}
public static int smallSigma1(int x) {
return ROTR(x, 17) ^ ROTR(x, 19) ^ (x >>> 10);
}
}
@@ -0,0 +1,86 @@
package de.caydenno1.xacrypto.hash.sha224;
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;
import static de.caydenno1.xacrypto.hash.sha224.Helpers.bigSigma1;
import static de.caydenno1.xacrypto.hash.sha224.Helpers.smallSigma0;
import static de.caydenno1.xacrypto.hash.sha224.Helpers.smallSigma1;
import static de.caydenno1.xacrypto.misc.Constants.SHA224_H0;
import static de.caydenno1.xacrypto.misc.Constants.SHA224_K;
public class SHA224 {
public static byte[] digest(byte[] message) {
long bl = ((long) message.length) * 8L;
int paddingLength = 64 - (int) ((message.length + 9) % 64);
if (paddingLength == 64) paddingLength = 0;
byte[] pd = new byte[message.length + 1 + paddingLength + 8];
System.arraycopy(message, 0, pd, 0, message.length);
pd[message.length] = (byte) 0x80;
for (int i = 0 ; i < 8 ; i++) pd[pd.length - 1 - i] = (byte) (bl >>> (8 * i));
int[] h = SHA224_H0.clone();
int[] w = new int[64];
for (int off = 0 ; off < pd.length ; off += 64) {
for (int i = 0 ; i < 16 ; i++) {
int pos = off + i * 4;
w[i] = ((pd[pos] & 0xff) << 24) |
((pd[pos + 1] & 0xff) << 16) |
((pd[pos + 2] & 0xff) << 8) |
(pd[pos + 3] & 0xff);
}
for (int i = 16 ; i < 64 ; i++) {
w[i] = smallSigma1(w[i - 2]) +
w[i - 7] +
smallSigma0(w[i - 15]) +
w[i - 16];
}
int ha = h[0];
int hb = h[1];
int hc = h[2];
int hd = h[3];
int he = h[4];
int hf = h[5];
int hg = h[6];
int hh = h[7];
for (int i = 0 ; i < 64 ; i++) {
int t1 = hh + bigSigma1(he) + ch(he, hf, hg) + SHA224_K[i] + w[i];
int t2 = bigSigma0(ha) + maj(ha, hb, hc);
hh = hg;
hg = hf;
hf = he;
he = hd + t1;
hd = hc;
hc = hb;
hb = ha;
ha = t1 + t2;
}
h[0] += ha;
h[1] += hb;
h[2] += hc;
h[3] += hd;
h[4] += he;
h[5] += hf;
h[6] += hg;
h[7] += hh;
}
byte[] res = new byte[28];
for (int i = 0 ; i < 7 ; i++) for (int j = 0; j < 4; j++) res[i * 4 + j] = (byte) (h[i] >>> (24 - j * 8));
return res;
}
}
@@ -0,0 +1,97 @@
package de.caydenno1.xacrypto.hash.sha256;
import de.caydenno1.xacrypto.misc.Constants;
import de.caydenno1.xacrypto.misc.XACryptoException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import static de.caydenno1.xacrypto.hash.sha256.SHA256.Word2Byte;
import static de.caydenno1.xacrypto.hash.sha256.SHA256.compress;
public final class Digest {
private final int[] s = Constants.SHA256_H.clone();
private final byte[] buf = new byte[64];
private int bufLen = 0;
private long total = 0L;
public Digest(){};
public Digest upd(byte[] d) throws XACryptoException {
return upd(d, 0, d.length);
}
/**
* i have never used javadoc before ;-; just using google for javadoc format lol
* @param d data
* @param o Offset
* @param l count
* @return {@code this} end data after modification
*/
public Digest upd(byte[] d, int o, int l) throws XACryptoException {
if(o<0||l<0||o+l>d.length) throw new XACryptoException("take a look at your code :)");
total += l;
if (bufLen > 0) {
int fil = Math.min(64 - bufLen, l);
System.arraycopy(d,o,buf,bufLen,fil);
bufLen += fil;o+=fil;l-=fil;
if (bufLen == 64) { compress(s, buf, 0); bufLen=0; }
}
while(l >= 64){
compress(s,d,o);
o += 64;
l -= 64;
};
// save whats remaining i suppose..
if (l>0) {
System.arraycopy(d, o, buf, 0, l);
bufLen = l;
};
return this; // we returned "this" !1
}
public Digest upd(String text) throws XACryptoException { return upd(text.getBytes(StandardCharsets.UTF_8) );};
public Digest upd(ByteBuffer buf) throws XACryptoException {
if (buf.hasArray()) { return upd(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining()); }
byte[] temp = new byte[buf.remaining()];
buf.get(temp);
return upd(temp);
};
@SuppressWarnings("ConstantValue")
public byte[] digest() {
byte[] t = new byte[bufLen];
System.arraycopy(buf,0,t,0,bufLen);
long bit = total * 8L;
int pad = 64 - (int)((bufLen+1+8) % 64)%64;
if (pad<0) pad += 64;
int total = bufLen + 1 + pad + 8;
byte[] last = new byte[total];
System.arraycopy(t, 0, last, 0, bufLen);
last[bufLen] = (byte) 0x80;
for (int i = 7; i >= 0; i--) {
last[total - 8 + i] = (byte) (bit & 0xff);
bit >>>= 8;
}
int[] sa = s.clone();
for (int off = 0; off < last.length; off += 64) { compress(sa, last, off); }
byte[] o = Word2Byte(sa);
reset();
return o;
}
public void reset() {
System.arraycopy(Constants.SHA256_H, 0, s, 0, 8);
Arrays.fill(buf, (byte) 0);
bufLen = 0;
total = 0L;
}
public long get() {
return total;
}
}
@@ -0,0 +1,66 @@
package de.caydenno1.xacrypto.hash.sha256;
import de.caydenno1.xacrypto.misc.XACryptoException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import static de.caydenno1.xacrypto.hash.sha256.HMAC.*;
import static de.caydenno1.xacrypto.hash.sha256.SHA256.*;
public class HKDF {
private HKDF(){}
public static byte[] extract(byte[] salt, byte[] ikm) throws XACryptoException {
byte[] effectivity = (salt == null || salt.length == 0) ? new byte[32] : salt;
return hmac(effectivity, ikm);
}
public static byte[] expand(byte[] prk, byte[] inf, int len) throws XACryptoException {
if (len <= 0 || len > 255 * 64) throw new XACryptoException(new String[]{"prk=" + java.util.Arrays.toString(prk), "inf=" + java.util.Arrays.toString(inf), "len=" + String.valueOf(len)}, (byte) 0);
int n = (len + 32 - 1) / 32;
byte[] okm = new byte[n*32];
byte[] t = new byte[0];
for (int i=1;i<=n;i++){
byte[] in = new byte[t.length + inf.length + 1];
System.arraycopy(t, 0, in, 0, t.length);
System.arraycopy(inf, 0, in, t.length, inf.length);
in[t.length+inf.length] = (byte) i;
t = hmac(prk,in);
System.arraycopy(t,0,okm,(i-1) * 32, 32);
}
return Arrays.copyOf(okm,len);
}
public static byte[] hkdf(byte[] ikm, byte[] sal, byte[] inf, int len) throws XACryptoException {
byte[] prk = extract(sal, ikm);
return expand(prk, inf, len);
}
public static byte[] pbkdf2(byte[] pass, byte[] sal, int it, int dk) throws XACryptoException {
if (it<1) throw new XACryptoException("interations too low. given:".concat(" ").concat(String.valueOf(it)));
int blk = (dk + 32 - 1) / 32;
byte[] d = new byte[blk * 32];
for (int i = 1; i<=blk; i++) {
byte[] II = { (byte)(i >> 24), (byte)(i >> 16), (byte)(i >> 8), (byte) i };
byte[] SI = conc(sal, II);
byte[] u = hmac(pass, SI);
byte[] f = u.clone();
for (int j = 1; j<it; j++) {
u=hmac(pass,u);
xor(f,u);
}
System.arraycopy(f,0,d, (i-1) * 32, 32);
}
return Arrays.copyOf(d,dk);
}
public static byte[] pbkdf2(String pass, byte[] sal, int it, int dk) throws XACryptoException {
return pbkdf2(pass.getBytes(StandardCharsets.UTF_8), sal, it, dk);
}
}
@@ -0,0 +1,32 @@
package de.caydenno1.xacrypto.hash.sha256;
import de.caydenno1.xacrypto.misc.XACryptoException;
import java.nio.charset.StandardCharsets;
import static de.caydenno1.xacrypto.hash.sha256.Hex.hash;
public class HMAC {
private HMAC(){}
public static byte[] hmac(byte[] key, byte[] mesg) throws XACryptoException {
byte[] k = (key.length > 64) ? hash(key) : key;
byte[] i = new byte[64];
byte[] o = new byte[64];
for (int l=0;l<64;l++) {
byte k_ = (l < k.length) ? k[l] : 0;
i[l] = (byte)(k_^0x36);
o[l] = (byte)(k_^0x5c);
}
byte[] in = new Digest().upd(i).upd(mesg).digest();
return new Digest().upd(o).upd(in).digest();
}
public static byte[] hmac(String key, String mesg) throws XACryptoException {
return hmac(key.getBytes(StandardCharsets.UTF_8),
mesg.getBytes(StandardCharsets.UTF_8));
}
}
@@ -0,0 +1,60 @@
package de.caydenno1.xacrypto.hash.sha256;
import de.caydenno1.xacrypto.misc.XACryptoException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Hex {
public static byte[] hash(byte[] data) throws XACryptoException {
return new Digest().upd(data).digest();
}
public static byte[] hash(String text) throws XACryptoException {
return hash(text.getBytes(StandardCharsets.UTF_8));
}
public static String hashPlain(String text) throws XACryptoException {
byte[] res = new Digest().upd(text).digest();
StringBuilder builder = new StringBuilder();
for (byte b :res) {
builder.append(String.format("%02x", b & 0xFF));
}
return builder.toString();
}
public static String hashHex(String text) throws XACryptoException {
return Byte2Hex(hash(text));
}
public static String hashHex(byte[] data) throws XACryptoException {
return Byte2Hex(hash(data));
}
public static ByteBuffer Hash2Buffer(byte[] data) throws XACryptoException {
return ByteBuffer.wrap(hash(data)).asReadOnlyBuffer();
}
public static byte[] doubleHash(byte[] data) throws XACryptoException {
return hash(hash(data));
}
public static byte[] HashFile(String loc) throws java.io.IOException, XACryptoException {
byte[] bytes = Files.readAllBytes(Paths.get(loc));
return hash(bytes);
}
public static String Byte2Hex(byte[] b) {
StringBuilder o = new StringBuilder(b.length * 2);
for (byte bi : b) {
o.append(String.format("%02x",bi&0xff));
}
return o.toString();
}
}
@@ -0,0 +1,183 @@
package de.caydenno1.xacrypto.hash.sha256;
import de.caydenno1.xacrypto.misc.Constants;
import de.caydenno1.xacrypto.misc.XACryptoException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import static de.caydenno1.xacrypto.hash.sha256.Hex.hash;
import static de.caydenno1.xacrypto.hash.sha256.Hex.doubleHash;
import static de.caydenno1.xacrypto.hash.ROT.ROTR;
import de.caydenno1.xacrypto.misc.ToM;
public final class SHA256 {
private SHA256(){}
public static void compress(int[] h, byte[] b, int offline){
int[] w = new int [64];
for (int i =0; i< 16;i++){
int base = offline + (i<<2);
w[i] = ((b[base]&0xff) << 24)
| ((b[base+1]&0xff) << 16)
| ((b[base+2]&0xff) << 8)
| (b[base+3]&0xff);
}
for (int i=16;i<64;i++){
int s0 = ROTR(w[i - 15], 7) ^ ROTR(w[i - 15], 18) ^ (w[i - 15] >>> 3);
int s1 = ROTR(w[i - 2], 17) ^ ROTR(w[i - 2], 19) ^ (w[i - 2] >>> 10);
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
}
int Va = h[0], Vb = h[1], Vc = h[2], Vd = h[3];
int Ve = h[4], Vf = h[5], Vg = h[6], Vh = h[7];
for (int i = 0; i<64; i++){
int S1 = ROTR(Ve, 6)^ROTR(Ve,11)^ROTR(Ve, 25);
int ch = (Ve&Vf)^(~Ve&Vg);
int tv1 = Vh+S1+ch+Constants.SHA256_K[i]+w[i];
int S0 = ROTR(Va, 2)^ROTR(Va,13)^ROTR(Va,22);
int maj = (Va&Vb)^(Va&Vc)^(Vb&Vc);
int tv2 = S0+maj;
Vh = Vg; Vg = Vf; Vf = Ve; Ve = Vd + tv1;
Vd = Vc; Vc = Vb; Vb = Va; Va = tv1+ tv2;
}
h[0] += Va; h[1] += Vb; h[2] += Vc; h[3] += Vd;
h[4] += Ve; h[5] += Vf; h[6] += Vg; h[7] += Vh;
}
@SuppressWarnings("ConstantValue")
static byte[] pad(byte[] data) {
long b = (long) data.length * 8L;
int p = 64 - (int)((data.length + 8) % 64);
if (p<1) p += 64;
int t = data.length + p + 8;
byte[] pd = new byte[t];
System.arraycopy(data, 0, pd, 0, data.length);
pd[data.length] = (byte) 0x80;
for (int i =7; i>=0;i--) {
pd[t - 8 + i] = (byte) (b & 0xff);
b >>>= 8;
}
return pd;
}
public static byte[] Word2Byte(int[] w){
byte[] o = new byte[w.length * 4];
for (int i=0;i<w.length;i++) {
o[i * 4] = (byte)(w[i] >>> 24);
o[i * 4 + 1] = (byte)(w[i] >>> 16);
o[i * 4 + 2] = (byte)(w[i] >>> 8);
o[i * 4 + 3] = (byte) w[i];
}
return o;
}
private static byte[] cc(byte[] a, byte[] b){
byte[] o = new byte[a.length + b.length];
System.arraycopy(a, 0, o, 0, a.length);
System.arraycopy(b, 0, o, a.length, b.length);
return o;
}
public static final class HashTask extends RecursiveTask<byte[][]>{
private final java.util.List<byte[]> leaves;
private int from,to;
private final boolean Double;
HashTask(java.util.List<byte[]> leaves, int from, int to, boolean Double) {
this.leaves = leaves;
this.from = from;
this.to = to;
this.Double = Double;
}
@Override
protected byte[][] compute() {
int len = this.to-this.from;
if (len <= 128) {
byte[][] res = new byte[len][];
for (int i=0;i<len;i++){
try {
res[i] = Double ? doubleHash(leaves.get(from + i))
: hash(leaves.get(from + i));
} catch (XACryptoException e) {};
}
return res;
}
int m = from + len/2;
HashTask l = new HashTask(leaves,from,m,Double);
HashTask r = new HashTask(leaves,m,to,Double);
l.fork();
byte[][] br = r.compute();
byte[][] bl = l.join();
byte[][] mergd = new byte[br.length+bl.length][];
System.arraycopy(bl,0,mergd,0,bl.length);
System.arraycopy(br,0,mergd,bl.length,br.length);
return mergd;
}
}
public static byte[] merkRoot(java.util.List<byte[]> leaves) throws XACryptoException {
if (leaves.isEmpty()) throw new XACryptoException("leaves List is empty!");
byte[][] lvl = ForkJoinPool.commonPool().invoke(new HashTask(leaves, 0, leaves.size(), false));
return mergeUp(lvl, (int)1);
};
public static byte[] merkRootDuo(java.util.List<byte[]> leaves) throws XACryptoException {
if (leaves.isEmpty()) throw new XACryptoException("leaves List is empty!");
byte[][] lvl = ForkJoinPool.commonPool().invoke(new HashTask(leaves, 0, leaves.size(), false));
return mergeUp(lvl, (int)2);
};
private static byte[] mergeUp(byte[][] lvl, int ext) throws XACryptoException {
while (lvl.length > 1) {
int nx = (lvl.length + 1) / 2;
byte[][] up = new byte[nx][];
for (int i = 0; i < lvl.length - 1; i += 2) {
up[i / 2] = (ext == 1)
? hash(conc(lvl[i], lvl[i + 1]))
: doubleHash(conc(lvl[i], lvl[i + 1]));
}
if (lvl.length % 2 == 1) up[nx-1] = lvl[lvl.length - 1];
}
return lvl[0];
}
static byte[] conc(byte[] a, byte[] b) {
byte[] out = new byte[a.length+b.length];
System.arraycopy(a,0,out,0,a.length);
System.arraycopy(b,0,out,a.length,b.length);
return out;
}
public static byte[] tagHash(String tag, byte[] dat) throws XACryptoException {
byte[] hasdat = hash(tag.getBytes());
byte[] load = new byte[hasdat.length * 2 + dat.length];
System.arraycopy(hasdat, 0, load, 0, hasdat.length);
System.arraycopy(hasdat, 0, load, hasdat.length, hasdat.length);
System.arraycopy(dat, 0, load, hasdat.length * 2, dat.length);
return hash(load);
}
static void xor(byte[] dest, byte[] src) {
for (int i = 0 ; i < dest.length ; i++) dest[i]^=src[i];
}
public static byte[] ByteFromHex(String hex) {
byte[] out = new byte[hex.length() / 2];
for (int i = 0 ; i < out.length ; i++) out[i] = (byte)((Character.digit(hex.charAt(i * 2),16) << 4)|Character.digit(hex.charAt(i * 2 + 1), 16));
return out;
}
}
@@ -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;
}
}
}
@@ -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();
}
}
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;
}
}
@@ -0,0 +1,32 @@
package de.caydenno1.xacrypto.misc;
import java.util.Arrays;
public class XACryptoException extends Exception {
private int id = (int) 0x00;
public XACryptoException(String res) {
super(res);
}
public XACryptoException(byte id){
super(String.format("0x%02X", id & 0xFF));
}
public XACryptoException(String res, byte id) {
super(res);
this.id = id & 0xFF;
}
public XACryptoException(String res, int iid) {
super(res);
this.id = iid;
}
public XACryptoException(String[] pnts, byte id){
super(String.join("|", pnts));
this.id = id & 0xFF;
}
public XACryptoException(String[] pnts, String other, byte id){
String[] data = Arrays.copyOf(pnts, pnts.length+1);
data[data.length - 1] = "REASON=".concat(other);
super(String.join("|", data));
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;
}
};
}
@@ -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,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;
}
}
@@ -0,0 +1,58 @@
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;
public class AriaECB implements ECB {
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,43 @@
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;
public class BlowfishECB implements ECBExceptionless {
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,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;
}
}
@@ -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;
}
}
@@ -0,0 +1,118 @@
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;
public class SM4ECB implements ECBExceptionless {
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,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;
}
}
@@ -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;
}
@@ -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;
}
@@ -0,0 +1,43 @@
package de.caydenno1.xacrypto.zekerrijndael;
import de.caydenno1.xacrypto.misc.XACryptoException;
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 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); }
}
}
@@ -0,0 +1,285 @@
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.*;
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;
}
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++) {
// 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 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,105 @@
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 = proc(new byte[16], aad);
Y = proc(Y, cip);
byte[] lenBlock = buildLenBlock(
aad.length * 8L,
cip.length * 8L
);
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){
int len = Math.min(16, in.length - off);
System.arraycopy(in, off, bloc, 0, len);
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) xor(Z,V);
boolean isLSB1 = (V[15] & 1) != 0;
RS(V);
if (isLSB1) 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[] 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);
}
return multi(blk, H);
}
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){
for (int i = 0 ; i < 16 ; i++) a[i] ^= b[i];
return a;
}
}
@@ -0,0 +1,3 @@
package de.caydenno1.xacrypto.zekerrijndael.GCM;
public record Result(byte[] cip, byte[] tag) {}
@@ -0,0 +1,90 @@
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.");
AES aes = new AES(key, getKeySize(key));
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 {
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 {
AES aes = new AES(key, getKeySize(key));
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 {
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,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));
}
}
@@ -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,11 @@
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.Serpent;
import java.lang.reflect.InvocationTargetException;
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.Global.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,263 @@
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);
for (int i = 1 ; i < round ; i++){
A(encRK[i], decRK[round - i]);
}
}
private void procRound(byte[] state, byte[][] rK){
for (int r = 0 ; r < round - 1 ; r++){
AriaXOR(state,rK[r]);
if (r % 2 == 0) {
SL1(state, state);
} else {
SL2(state, state);
}
A(state, state);
}
AriaXOR(state, rK[round-1]);
if((round-1) % 2 == 0) {
SL1(state, state);
} else {
SL2(state, state);
}
AriaXOR(state, 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) {
AriaXOR(i, ck, o);
SL1(o, o);
A(o, o);
}
//feistel even
private void FE(byte[] i, byte[] ck, byte[] o) {
AriaXOR(i, ck, o);
SL2(o, o);
A(o, 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]);
SROTR128(W[1], 19, encRK[0]);
AriaXOR(W[0], encRK[0], encRK[0]);
SROTR128(W[2], 19, encRK[1]);
AriaXOR(W[1], encRK[1], encRK[1]);
SROTR128(W[3], 19, encRK[2]);
AriaXOR(W[2], encRK[2], encRK[2]);
SROTR128(W[0], 19, encRK[3]);
AriaXOR(encRK[3], W[3], encRK[3]);
SROTR128(W[1], 31, encRK[4]);
AriaXOR(W[0], encRK[4], encRK[4]);
SROTR128(W[2], 31, encRK[5]);
AriaXOR(W[1], encRK[5], encRK[5]);
SROTR128(W[3], 31, encRK[6]);
AriaXOR(W[2], encRK[6], encRK[6]);
SROTR128(W[0], 31, encRK[7]);
AriaXOR(encRK[7], W[3], encRK[7]);
SROTR128(W[1], 128 - 61, encRK[8]);
AriaXOR(W[0], encRK[8], encRK[8]);
SROTR128(W[2], 128 - 61, encRK[9]);
AriaXOR(W[1], encRK[9], encRK[9]);
SROTR128(W[3], 128 - 61, encRK[10]);
AriaXOR(W[2], encRK[10], encRK[10]);
SROTR128(W[0], 128 - 61, encRK[11]);
AriaXOR(encRK[11], W[3], encRK[11]);
SROTR128(W[1], 128 - 31, encRK[12]);
AriaXOR(W[0], encRK[12], encRK[12]);
if (round >= 14) {
SROTR128(W[2], 128 - 31, encRK[13]);
AriaXOR(W[1], encRK[13], encRK[13]);
SROTR128(W[3], 128 - 31, encRK[14]);
AriaXOR(W[2], encRK[14], encRK[14]);
}
if (round == 16) {
SROTR128(W[0], 128 - 31, encRK[15]);
AriaXOR(encRK[15], W[3], encRK[15]);
SROTR128(W[1], 128 - 19, encRK[16]);
AriaXOR(W[0], encRK[16], 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) {
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);
}
}
@@ -0,0 +1,365 @@
package de.caydenno1.xacrypto.zekerrijndael.Global;
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);
}
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);
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) {
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];
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];
long2Bytes(d2, out, outOffset);
long2Bytes(d1, out, outOffset + 8);
return out;
}
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,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); }
}
@@ -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)); }
}
@@ -0,0 +1,141 @@
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;
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);
}
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] };
int index = (3 - i) % 8;
SBOXify(index, group, SERPENT_SBOX);
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,162 @@
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];
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[3], 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;
}
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++) {
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;
}
}