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

common.crypto.SHA3 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.crypto;

import java.util.Arrays;

public class SHA3
{
  public static final byte NIST_PADDING = 6;
  public static final byte KECCAK_PADDING = 1;

  private long[] state = new long[25];
  private byte[] buf = new byte[200];
  private int offset = 0;

  public void begin()
  {
    offset = 0;
    for (int i = 0; i < buf.length; i++) buf[i] = 0;
  }

  public void update(byte[] data)
  {
    update(data, 0, data.length);
  }

  public void update(byte[] data, int offset, int len)
  {
    for (int i = 0; i < len; i++) update(data[offset + i]);
  }

  public void update(byte b)
  {
    buf[offset++] ^= b;
    if (offset == 136) transform();
  }

  public byte[] end(byte padding)
  {
    buf[offset] ^= padding;
    buf[135] ^= 0x80;
    transform();
    return Arrays.copyOfRange(buf, 0, 32);
  }

  public static byte[] sha3_256(byte[] data, byte padding)
  {
    return SHA3.calculate(data, padding);
  }

  public static byte[] calculate(byte[] data, byte padding)
  {
    SHA3 context = new SHA3();
    context.begin();
    context.update(data);
    return context.end(padding);
  }

  private void transform()
  {
    for (int i = 0; i < 25; i++)
      state[i] =
              ((long) (buf[i * 8 + 0]) & 0xff) |
                      (((long) (buf[i * 8 + 1]) & 0xff) << 8) |
                      (((long) (buf[i * 8 + 2]) & 0xff) << 16) |
                      (((long) (buf[i * 8 + 3]) & 0xff) << 24) |
                      (((long) (buf[i * 8 + 4]) & 0xff) << 32) |
                      (((long) (buf[i * 8 + 5]) & 0xff) << 40) |
                      (((long) (buf[i * 8 + 6]) & 0xff) << 48) |
                      (((long) (buf[i * 8 + 7]) & 0xff) << 56);

    keccak(state);

    for (int i = 0; i < 25; i++)
    {
      buf[i * 8 + 0] = (byte) state[i];
      buf[i * 8 + 1] = (byte) (state[i] >> 8);
      buf[i * 8 + 2] = (byte) (state[i] >> 16);
      buf[i * 8 + 3] = (byte) (state[i] >> 24);
      buf[i * 8 + 4] = (byte) (state[i] >> 32);
      buf[i * 8 + 5] = (byte) (state[i] >> 40);
      buf[i * 8 + 6] = (byte) (state[i] >> 48);
      buf[i * 8 + 7] = (byte) (state[i] >> 56);
    }
    offset = 0;
  }


  private static void keccak(long[] a)
  {
    for (int i = 0; i < 24; i++)
    {
      //theta (precalculation part)
      long c0 = a[0] ^ a[5 + 0] ^ a[10 + 0] ^ a[15 + 0] ^ a[20 + 0];
      long c1 = a[1] ^ a[5 + 1] ^ a[10 + 1] ^ a[15 + 1] ^ a[20 + 1];
      long c2 = a[2] ^ a[5 + 2] ^ a[10 + 2] ^ a[15 + 2] ^ a[20 + 2];
      long c3 = a[3] ^ a[5 + 3] ^ a[10 + 3] ^ a[15 + 3] ^ a[20 + 3];
      long c4 = a[4] ^ a[5 + 4] ^ a[10 + 4] ^ a[15 + 4] ^ a[20 + 4];

      long t0 = (c0 << 1) ^ (c0 >>> (64 - 1)) ^ c3;
      long t1 = (c1 << 1) ^ (c1 >>> (64 - 1)) ^ c4;
      long t2 = (c2 << 1) ^ (c2 >>> (64 - 1)) ^ c0;
      long t3 = (c3 << 1) ^ (c3 >>> (64 - 1)) ^ c1;
      long t4 = (c4 << 1) ^ (c4 >>> (64 - 1)) ^ c2;

      //theta (xorring part) + rho + pi
      long x, a_10_;
      a[0] ^= t1;
      x = a[1] ^ t2;
      a_10_ = (x << 1) | (x >>> (64 - 1));
      x = a[6] ^ t2;
      a[1] = (x << 44) | (x >>> (64 - 44));
      x = a[9] ^ t0;
      a[6] = (x << 20) | (x >>> (64 - 20));
      x = a[22] ^ t3;
      a[9] = (x << 61) | (x >>> (64 - 61));

      x = a[14] ^ t0;
      a[22] = (x << 39) | (x >>> (64 - 39));
      x = a[20] ^ t1;
      a[14] = (x << 18) | (x >>> (64 - 18));
      x = a[2] ^ t3;
      a[20] = (x << 62) | (x >>> (64 - 62));
      x = a[12] ^ t3;
      a[2] = (x << 43) | (x >>> (64 - 43));
      x = a[13] ^ t4;
      a[12] = (x << 25) | (x >>> (64 - 25));

      x = a[19] ^ t0;
      a[13] = (x << 8) | (x >>> (64 - 8));
      x = a[23] ^ t4;
      a[19] = (x << 56) | (x >>> (64 - 56));
      x = a[15] ^ t1;
      a[23] = (x << 41) | (x >>> (64 - 41));
      x = a[4] ^ t0;
      a[15] = (x << 27) | (x >>> (64 - 27));
      x = a[24] ^ t0;
      a[4] = (x << 14) | (x >>> (64 - 14));

      x = a[21] ^ t2;
      a[24] = (x << 2) | (x >>> (64 - 2));
      x = a[8] ^ t4;
      a[21] = (x << 55) | (x >>> (64 - 55));
      x = a[16] ^ t2;
      a[8] = (x << 45) | (x >>> (64 - 45));
      x = a[5] ^ t1;
      a[16] = (x << 36) | (x >>> (64 - 36));
      x = a[3] ^ t4;
      a[5] = (x << 28) | (x >>> (64 - 28));

      x = a[18] ^ t4;
      a[3] = (x << 21) | (x >>> (64 - 21));
      x = a[17] ^ t3;
      a[18] = (x << 15) | (x >>> (64 - 15));
      x = a[11] ^ t2;
      a[17] = (x << 10) | (x >>> (64 - 10));
      x = a[7] ^ t3;
      a[11] = (x << 6) | (x >>> (64 - 6));
      x = a[10] ^ t1;
      a[7] = (x << 3) | (x >>> (64 - 3));
      a[10] = a_10_;

      //chi
      for (int c = 0; c < 25; c += 5)
      {
        long x0 = a[c + 0];
        long x1 = a[c + 1];
        long x2 = a[c + 2];
        long x3 = a[c + 3];
        long x4 = a[c + 4];
        a[c + 0] = x0 ^ ((~x1) & x2);
        a[c + 1] = x1 ^ ((~x2) & x3);
        a[c + 2] = x2 ^ ((~x3) & x4);
        a[c + 3] = x3 ^ ((~x4) & x0);
        a[c + 4] = x4 ^ ((~x0) & x1);
      }

      //iota
      a[0] ^= rc[i];
    }
  }

  private static final long[] rc =
  {
    0x0000000000000001L, 0x0000000000008082L, 0x800000000000808AL, 0x8000000080008000L, 0x000000000000808BL,
    0x0000000080000001L, 0x8000000080008081L, 0x8000000000008009L, 0x000000000000008AL, 0x0000000000000088L,
    0x0000000080008009L, 0x000000008000000AL, 0x000000008000808BL, 0x800000000000008BL, 0x8000000000008089L,
    0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, 0x000000000000800AL, 0x800000008000000AL,
    0x8000000080008081L, 0x8000000000008080L, 0x0000000080000001L, 0x8000000080008008L
  };
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy