97 lines
3.5 KiB
Java
97 lines
3.5 KiB
Java
package io.github.lonamiwebs.overgram.utils;
|
|
|
|
import javax.crypto.BadPaddingException;
|
|
import javax.crypto.Cipher;
|
|
import javax.crypto.IllegalBlockSizeException;
|
|
import javax.crypto.NoSuchPaddingException;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
import java.security.InvalidKeyException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.util.Arrays;
|
|
|
|
public class AES {
|
|
public static byte[] decryptIge(final byte[] cipherText, final byte[] key, final byte[] iv) {
|
|
final Cipher cipher;
|
|
try {
|
|
cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException ignored) {
|
|
throw new SecurityException("AES/ECB/NoPadding is required but not available");
|
|
}
|
|
try {
|
|
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
|
|
} catch (InvalidKeyException ignored) {
|
|
throw new SecurityException("Invalid key");
|
|
}
|
|
|
|
final int blockSize = cipher.getBlockSize();
|
|
final byte[] plainText = new byte[cipherText.length];
|
|
|
|
byte[] x;
|
|
byte[] y;
|
|
byte[] xPrev = Arrays.copyOfRange(iv, 0, blockSize);
|
|
byte[] yPrev = Arrays.copyOfRange(iv, blockSize, iv.length);
|
|
try {
|
|
for (int i = 0; i < cipherText.length; ) {
|
|
x = Arrays.copyOfRange(cipherText, i, i + blockSize);
|
|
y = Utils.xor(cipher.doFinal(Utils.xor(x, yPrev)), xPrev);
|
|
xPrev = x;
|
|
yPrev = y;
|
|
|
|
for (int j = 0; j < blockSize; ++j) {
|
|
plainText[i] = y[j];
|
|
++i;
|
|
}
|
|
}
|
|
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
|
|
throw new SecurityException("Illegal block size or padding");
|
|
}
|
|
|
|
return plainText;
|
|
}
|
|
|
|
public static byte[] encryptIge(final byte[] plainText, final byte[] key, final byte[] iv) {
|
|
final Cipher cipher;
|
|
try {
|
|
cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException ignored) {
|
|
throw new SecurityException("AES/ECB/NoPadding is required but not available");
|
|
}
|
|
try {
|
|
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
|
|
} catch (InvalidKeyException ignored) {
|
|
throw new SecurityException("Invalid key");
|
|
}
|
|
|
|
final int blockSize = cipher.getBlockSize();
|
|
final byte[] paddedPlain;
|
|
if (plainText.length % 16 == 0) {
|
|
paddedPlain = plainText;
|
|
} else {
|
|
paddedPlain = Utils.concat(plainText, Utils.randomBytes(16 - plainText.length % 16));
|
|
}
|
|
|
|
final byte[] cipherText = new byte[paddedPlain.length];
|
|
byte[] x;
|
|
byte[] y;
|
|
byte[] xPrev = Arrays.copyOfRange(iv, 0, blockSize);
|
|
byte[] yPrev = Arrays.copyOfRange(iv, blockSize, iv.length);
|
|
try {
|
|
for (int i = 0; i < paddedPlain.length; ) {
|
|
y = Arrays.copyOfRange(paddedPlain, i, i + blockSize);
|
|
x = Utils.xor(cipher.doFinal(Utils.xor(y, xPrev)), yPrev);
|
|
yPrev = y;
|
|
xPrev = x;
|
|
|
|
for (int j = 0; j < blockSize; ++j) {
|
|
cipherText[i] = x[j];
|
|
++i;
|
|
}
|
|
}
|
|
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
|
|
throw new SecurityException("Illegal block size or padding");
|
|
}
|
|
|
|
return cipherText;
|
|
}
|
|
}
|