All Downloads are FREE. Search and download functionalities are using the official Maven repository.

common.Converter Maven / Gradle / Ivy

Go to download

This is a collection of JAVA libraries that implement Unbound cryptographic classes for JAVA provider, PKCS11 wrapper, cryptoki, and advapi

There is a newer version: 42761
Show newest version
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 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 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 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) & 0xffffffff);
  }

  public static long getLE8(byte[] in, int offset)
  {
    return (((long) getLE4(in, offset + 4)) << 16) | (getLE4(in, offset + 0) & 0xffffffff);
  }

  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() / 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 = binLength - length;
    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);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy