common.crypto.AES Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of unbound-java-provider Show documentation
Show all versions of unbound-java-provider Show documentation
This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi
package com.unbound.common.crypto;
import com.unbound.common.Converter;
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;
public final class AES
{
private Cipher cipher;
byte[] key;
public AES(byte[] key)
{
this.key = key;
cipher = SystemProvider.Cipher.getInstance("AES/ECB/NoPadding");
}
private void checkInit(int mode)
{
try
{
if (key!=null)
{
cipher.init(mode, new SecretKeySpec(key, "AES"));
key = null;
}
}
catch (Exception e) { throw new IllegalArgumentException(e); }
}
public byte[] encrypt(byte[] in)
{
checkInit(Cipher.ENCRYPT_MODE);
return cipher.update(in);
}
public AES encrypt(byte[] in, int inOffset, int inLength, byte[] out, int outOffset)
{
try
{
checkInit(Cipher.ENCRYPT_MODE);
cipher.update(in, inOffset, inLength, out, outOffset);
return this;
}
catch (Exception e) { throw new IllegalArgumentException(e); }
}
public byte[] decrypt(byte[] in)
{
checkInit(Cipher.DECRYPT_MODE);
return cipher.update(in);
}
public AES decrypt(byte[] in, int inOffset, int inLength, byte[] out, int outOffset)
{
try
{
checkInit(Cipher.DECRYPT_MODE);
cipher.update(in, inOffset, inLength, out, outOffset);
return this;
}
catch (Exception e) { throw new IllegalArgumentException(e); }
}
static byte[] encrypt(byte[] key, byte[] in)
{
return new AES(key).encrypt(in);
}
static byte[] decrypt(byte[] key, byte[] in)
{
return new AES(key).decrypt(in);
}
public static final class GCM
{
public static byte[] encrypt(byte[] key, byte[] iv, int tagLen, byte[] in)
{
return encrypt(key, iv, null, tagLen, in);
}
public static byte[] encrypt(byte[] key, byte[] iv, byte[] aad, int tagLen, byte[] in)
{
try
{
byte[] out = new byte[in.length + tagLen];
GCMParameterSpec params = new GCMParameterSpec(tagLen * 8, iv);
Cipher cipher = SystemProvider.Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), params);
if (aad!=null && aad.length>0) cipher.updateAAD(aad);
int tempSize = cipher.update(in, 0, in.length, out, 0);
cipher.doFinal(out, tempSize);
return out;
}
catch (Exception e) { throw new IllegalArgumentException(e); }
}
public static byte[] decrypt(byte[] key, byte[] iv, int tagLen, byte[] in) throws AEADBadTagException
{
return decrypt(key, iv, null, tagLen, in);
}
public static byte[] decrypt(byte[] key, byte[] iv, byte[] aad, int tagLen, byte[] in) throws AEADBadTagException
{
try
{
byte[] out = new byte[in.length - tagLen];
GCMParameterSpec params = new GCMParameterSpec(tagLen * 8, iv);
Cipher cipher = SystemProvider.Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), params);
if (aad!=null && aad.length>0) cipher.updateAAD(aad);
int tempSize = cipher.update(in, 0, in.length, out, 0);
cipher.doFinal(out, tempSize);
return out;
}
catch (AEADBadTagException e) { throw e; }
catch (Exception e) { throw new IllegalArgumentException(e); }
}
}
public static final class XTS
{
private static void gfMulX128LE(byte[] ps)
{
long whiteningLo = Converter.getLE8(ps, 0);
long whiteningHi = Converter.getLE8(ps, 8);
int finalCarry = (0 == (whiteningHi & 0x8000000000000000L)) ? 0 : 135;
whiteningHi <<= 1;
whiteningHi |= whiteningLo >>> 63;
whiteningLo <<= 1;
whiteningLo ^= finalCarry;
Converter.setLE8(ps, 0, whiteningLo);
Converter.setLE8(ps, 8, whiteningHi);
}
private static void xor(byte[] dst, int dstOffset, byte[] src1, int srcOffset1, byte[] src2, int srcOffset2)
{
for (int i=0; i<16; i++) dst[dstOffset+i] = (byte)(src1[srcOffset1+i] ^ src2[srcOffset2+i]);
}
static byte[] encrypt(byte[] key, byte[] plain)
{
byte[] encrypted = new byte[plain.length];
try
{
byte[] k1 = Arrays.copyOfRange(key, 0, 16);
byte[] k2 = Arrays.copyOfRange(key, 16, 32);
byte[] iv = new byte[16]; // zeroes
byte[] ps = new AES(k2).encrypt(iv);
Cipher cipher = SystemProvider.Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(k1, "AES"));
byte[] temp = new byte[16];
int n = plain.length/16;
int offset = 0;
for (int i = 0; i0 && i==n-1)
{
System.arraycopy(ps, 0, psSave, 0, 16);
gfMulX128LE(ps);
}
xor(temp, 0, ps, 0, encrypted, offset);
cipher.update(temp, 0, 16, temp);
xor(plain, offset, temp, 0, ps, 0);
gfMulX128LE(ps);
}
if (tail>0)
{
for (int i=0; i