Overgram/lib/src/main/java/io/github/lonamiwebs/overgram/utils/AES.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;
}
}