utils.com.unbound.common.Converter 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;
import java.math.BigInteger;
import java.nio.BufferOverflowException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
public final class Converter
{
public interface IConvertable
{
void convert(Converter converter);
}
private static HashMap> codeTypes = new HashMap<>();
public static void registerCodeType(Class clazz, long codeType)
{
codeTypes.put(codeType, clazz);
}
private static IConvertable dynamicCreate(byte[] binary, int offset)
{
checkLength(binary.length >= offset + 8);
long codeType = getBE8(binary, offset);
Class clazz = codeTypes.get(codeType);
if (clazz==null) throw new IllegalArgumentException("Unknown IConvertable 0x" + HEX.toString(codeType));
IConvertable object = null;
try
{
object = clazz.newInstance();
}
catch (InstantiationException | IllegalAccessException e)
{
throw new IllegalArgumentException("IConvertable newInstance error for " + clazz.getName(), e);
}
return object;
}
public T convert(T value)
{
if (!write) value = (T) dynamicCreate(pointer, offset);
value.convert(this);
return value;
}
private boolean write;
private byte[] pointer;
private int offset;
private int length;
private Converter(boolean write, byte[] pointer)
{
this.write = write;
this.pointer = pointer;
offset = 0;
length = pointer == null ? 0 : pointer.length;
}
Converter(byte[] pointer) // read
{
this(false, pointer);
}
Converter()
{
this(true, null);
}
void setPointer(byte[] pointer)
{
offset = 0;
length = pointer.length;
this.pointer = pointer;
}
public boolean isWrite()
{
return write;
}
public static void checkLength(boolean ok)
{
if (!ok) throw new IllegalArgumentException("Convertor length error");
}
public byte[] getPointer()
{
return pointer;
}
public int getOffset()
{
return offset;
}
public int getLength()
{
return write ? offset : length;
}
public void checkAtLeast(int n)
{
if (write) return;
checkLength(length >= offset + n);
}
public void forward(int n)
{
checkAtLeast(n);
offset += n;
}
public boolean convert(boolean value)
{
return 0 != convert((byte) (value ? 1 : 0));
}
public byte convert(byte value)
{
forward(1);
if (write)
{
if (pointer != null) pointer[offset - 1] = value;
}
else value = pointer[offset - 1];
return value;
}
public short convert(short value)
{
forward(2);
if (write)
{
if (pointer != null) setBE2(pointer, offset - 2, value);
}
else value = getBE2(pointer, offset - 2);
return value;
}
public int convert(int value)
{
forward(4);
if (write)
{
if (pointer != null) setBE4(pointer, offset - 4, value);
}
else value = getBE4(pointer, offset - 4);
return value;
}
public long convert(long value)
{
forward(8);
if (write)
{
if (pointer != null) setBE8(pointer, offset - 8, value);
}
else value = getBE8(pointer, offset - 8);
return value;
}
public int beginStruct()
{
int begin = offset;
forward(2);
return begin;
}
public int beginStructVersion0()
{
return beginStructVersion(0);
}
public int beginStructVersion(int version)
{
int begin = offset;
forward(2);
convertVersion((byte)version);
return begin;
}
public void endStruct(int begin)
{
if (write)
{
if (pointer != null) setBE2(pointer, begin, (short) (offset - begin - 2));
}
else
{
int length = getBE2(pointer, begin);
offset = begin;
forward(length);
}
}
public byte convertVersion(byte version)
{
return convert(version);
}
public String convert(String value)
{
byte[] encoded = null;
short valueLength = 0;
if (write && value != null)
{
encoded = value.getBytes(StandardCharsets.UTF_8);
valueLength = (short) encoded.length;
}
valueLength = convert(valueLength);
forward(valueLength);
if (write)
{
if (pointer != null && encoded != null) System.arraycopy(encoded, 0, pointer, offset - valueLength, valueLength);
}
else value = new String(pointer, offset - valueLength, valueLength, StandardCharsets.UTF_8);
return value;
}
public int convertLen(int len)
{
short hi = 0;
short lo = 0;
if (write)
{
if (len < 0x8000)
{
lo = (short) len;
}
else
{
hi = (short) ((len >> 16) | 0x8000);
lo = (short) len;
convert(hi);
}
convert(lo);
}
else
{
hi = convert(hi);
if ((hi & 0x8000) != 0)
{
lo = convert(lo);
len = ((hi & 0x7fff) << 16) | (lo & 0xffff);
}
else len = hi;
}
return len;
}
public byte[] convert(byte[] value)
{
int valueLength = value != null ? value.length : 0;
valueLength = convertLen(valueLength);
forward(valueLength);
if (write)
{
if (pointer != null && value != null) System.arraycopy(value, 0, pointer, offset - valueLength, valueLength);
}
else value = Arrays.copyOfRange(pointer, offset - valueLength, offset);
return value;
}
public byte[] convertFixSize(byte[] value, int fixedSize)
{
if (write)
{
if (pointer != null)
{
if (value == null || value.length!=fixedSize) throw new IllegalArgumentException("Invalid byte array length");
System.arraycopy(value, 0, pointer, offset, fixedSize);
}
}
else value = Arrays.copyOfRange(pointer, offset, offset+fixedSize);
offset += fixedSize;
return value;
}
public BigInteger convert(BigInteger value)
{
if (write)
{
byte sign = (byte) value.signum();
convert(sign);
byte[] bytes = (sign >= 0 ? value : value.negate()).toByteArray();
convert(bytes);
}
else
{
byte sign = convert((byte) 0);
byte[] bytes = convert((byte[]) null);
value = new BigInteger(sign, bytes);
}
return value;
}
public BigInteger convertPosFixSize(BigInteger value, int fixedSize) // fixedSize in bytes
{
if (write)
{
if (pointer!=null) bigNumToBin(value, pointer, offset, fixedSize);
}
else
{
value = new BigInteger(1, Arrays.copyOfRange(pointer, offset, offset+fixedSize));
}
offset += fixedSize;
return value;
}
public static short getBE2(byte[] in, int offset)
{
return (short) ((((short) in[offset + 0]) << 8) | (in[offset + 1] & 0xff));
}
public static short getLE2(byte[] in, int offset)
{
return (short) ((((short) in[offset + 1]) << 8) | (in[offset + 0] & 0xff));
}
public static int getBE4(byte[] in, int offset)
{
return (((int) getBE2(in, offset + 0)) << 16) | (getBE2(in, offset + 2) & 0xffff);
}
public static int getLE4(byte[] in, int offset)
{
return (((int) getLE2(in, offset + 2)) << 16) | (getLE2(in, offset + 0) & 0xffff);
}
public static long getBE8(byte[] in, int offset)
{
return (((long) getBE4(in, offset + 0)) << 32) | (getBE4(in, offset + 4) & 0xffffffffl);
}
public static long getLE8(byte[] in, int offset)
{
return (((long) getLE4(in, offset + 4)) << 32) | (getLE4(in, offset + 0) & 0xffffffffl);
}
public static void setBE2(byte[] out, int offset, short v)
{
out[offset + 0] = (byte) (v >> 8);
out[offset + 1] = (byte) v;
}
public static void setLE2(byte[] out, int offset, short v)
{
out[offset + 1] = (byte) (v >> 8);
out[offset + 0] = (byte) v;
}
public static void setBE4(byte[] out, int offset, int v)
{
setBE2(out, offset + 0, (short) (v >> 16));
setBE2(out, offset + 2, (short) v);
}
public static void setLE4(byte[] out, int offset, int v)
{
setLE2(out, offset + 2, (short) (v >> 16));
setLE2(out, offset + 0, (short) v);
}
public static void setBE8(byte[] out, int offset, long v)
{
setBE4(out, offset + 0, (int) (v >> 32));
setBE4(out, offset + 4, (int) v);
}
public static void setLE8(byte[] out, int offset, long v)
{
setLE4(out, offset + 4, (int) (v >> 32));
setLE4(out, offset + 0, (int) v);
}
public static int bigNumSize(BigInteger in)
{
return (in.bitLength() + 7) / 8;
}
public static void bigNumToBin(BigInteger in, byte[] out, int offset, int length)
{
byte[] bin = in.toByteArray();
int binLength = bin.length;
int padding = (binLength > 0 && bin[0] == 0) ? 1 : 0;
binLength -= padding;
if (length < 0) length = binLength;
else
{
if (length < binLength) throw new BufferOverflowException();
}
int outPadding = length - binLength;
for (int i = 0; i < outPadding; i++) out[offset++] = 0;
System.arraycopy(bin, padding, out, offset, binLength);
}
public static byte[] bigNumToBin(BigInteger in, int length)
{
if (length < 0) length = bigNumSize(in);
byte[] out = new byte[length];
bigNumToBin(in, out, 0, length);
return out;
}
public static byte[] bigNumToBin(BigInteger in)
{
return bigNumToBin(in, -1);
}
public static BigInteger binToBigNum(byte[] in)
{
return binToBigNum(in, 0, in.length);
}
public static BigInteger binToBigNum(byte[] in, int offset, int length)
{
if (offset != 0 || length != in.length) in = Arrays.copyOfRange(in, offset, offset + length);
return new BigInteger(1, in);
}
public static byte[] concat(byte[] in1, byte[] in2)
{
if (in1==null || in1.length==0) return in2;
if (in2==null || in2.length==0) return in1;
byte[] out = new byte[in1.length + in2.length];
System.arraycopy(in1, 0, out, 0, in1.length);
System.arraycopy(in2, 0, out, in1.length, in2.length);
return out;
}
public static int convert(byte[] dst, Convertable src)
{
Converter converter = new Converter(true, dst);
src.convert(converter);
return converter.offset;
}
public static byte[] convert(Convertable src)
{
int size = convert(null, src);
byte[] dst = new byte[size];
convert(dst, src);
return dst;
}
public static T convert(Class clazz, byte[] src)
{
T dst = null;
try { dst = clazz.newInstance(); }
catch (InstantiationException | IllegalAccessException e) { throw new IllegalArgumentException(e); }
convert(dst, src);
return dst;
}
public static T convert(T dst, byte[] src)
{
Converter converter = new Converter(false, src);
dst.convert(converter);
return dst;
}
}