/*
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.provider;

import static sun.security.provider.ByteArrayAccess.*;
import java.nio.*;
import java.util.*;
import java.security.*;

This class implements the Secure Hash Algorithm SHA-3 developed by the National Institute of Standards and Technology along with the National Security Agency as defined in FIPS PUB 202.

It implements java.security.MessageDigestSpi, and can be used through Java Cryptography Architecture (JCA), as a pluggable MessageDigest implementation.

Author: Valerie Peng
Since: 9
/** * This class implements the Secure Hash Algorithm SHA-3 developed by * the National Institute of Standards and Technology along with the * National Security Agency as defined in FIPS PUB 202. * * <p>It implements java.security.MessageDigestSpi, and can be used * through Java Cryptography Architecture (JCA), as a pluggable * MessageDigest implementation. * * @since 9 * @author Valerie Peng */
abstract class SHA3 extends DigestBase { private static final int WIDTH = 200; // in bytes, e.g. 1600 bits private static final int DM = 5; // dimension of lanes private static final int NR = 24; // number of rounds // precomputed round constants needed by the step mapping Iota private static final long[] RC_CONSTANTS = { 0x01L, 0x8082L, 0x800000000000808aL, 0x8000000080008000L, 0x808bL, 0x80000001L, 0x8000000080008081L, 0x8000000000008009L, 0x8aL, 0x88L, 0x80008009L, 0x8000000aL, 0x8000808bL, 0x800000000000008bL, 0x8000000000008089L, 0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, 0x800aL, 0x800000008000000aL, 0x8000000080008081L, 0x8000000000008080L, 0x80000001L, 0x8000000080008008L, }; private byte[] state = new byte[WIDTH]; private final long[] lanes = new long[DM*DM];
Creates a new SHA-3 object.
/** * Creates a new SHA-3 object. */
SHA3(String name, int digestLength) { super(name, digestLength, (WIDTH - (2 * digestLength))); }
Core compression function. Processes blockSize bytes at a time and updates the state of this object.
/** * Core compression function. Processes blockSize bytes at a time * and updates the state of this object. */
void implCompress(byte[] b, int ofs) { for (int i = 0; i < buffer.length; i++) { state[i] ^= b[ofs++]; } keccak(); }
Return the digest. Subclasses do not need to reset() themselves, DigestBase calls implReset() when necessary.
/** * Return the digest. Subclasses do not need to reset() themselves, * DigestBase calls implReset() when necessary. */
void implDigest(byte[] out, int ofs) { int numOfPadding = setPaddingBytes(buffer, (int)(bytesProcessed % buffer.length)); if (numOfPadding < 1) { throw new ProviderException("Incorrect pad size: " + numOfPadding); } for (int i = 0; i < buffer.length; i++) { state[i] ^= buffer[i]; } keccak(); System.arraycopy(state, 0, out, ofs, engineGetDigestLength()); }
Resets the internal state to start a new hash.
/** * Resets the internal state to start a new hash. */
void implReset() { Arrays.fill(state, (byte)0); Arrays.fill(lanes, 0L); }
Utility function for padding the specified data based on the pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required for SHA-3 hash (section 6.1).
/** * Utility function for padding the specified data based on the * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required * for SHA-3 hash (section 6.1). */
private static int setPaddingBytes(byte[] in, int len) { if (len != in.length) { // erase leftover values Arrays.fill(in, len, in.length, (byte)0); // directly store the padding bytes into the input // as the specified buffer is allocated w/ size = rateR in[len] |= (byte) 0x06; in[in.length - 1] |= (byte) 0x80; } return (in.length - len); }
Utility function for transforming the specified byte array 's' into array of lanes 'm' as defined in section 3.1.2.
/** * Utility function for transforming the specified byte array 's' * into array of lanes 'm' as defined in section 3.1.2. */
private static void bytes2Lanes(byte[] s, long[] m) { int sOfs = 0; // Conversion traverses along x-axis before y-axis for (int y = 0; y < DM; y++, sOfs += 40) { b2lLittle(s, sOfs, m, DM*y, 40); } }
Utility function for transforming the specified array of lanes 'm' into a byte array 's' as defined in section 3.1.3.
/** * Utility function for transforming the specified array of * lanes 'm' into a byte array 's' as defined in section 3.1.3. */
private static void lanes2Bytes(long[] m, byte[] s) { int sOfs = 0; // Conversion traverses along x-axis before y-axis for (int y = 0; y < DM; y++, sOfs += 40) { l2bLittle(m, DM*y, s, sOfs, 40); } }
Step mapping Theta as defined in section 3.2.1 .
/** * Step mapping Theta as defined in section 3.2.1 . */
private static long[] smTheta(long[] a) { long c0 = a[0]^a[5]^a[10]^a[15]^a[20]; long c1 = a[1]^a[6]^a[11]^a[16]^a[21]; long c2 = a[2]^a[7]^a[12]^a[17]^a[22]; long c3 = a[3]^a[8]^a[13]^a[18]^a[23]; long c4 = a[4]^a[9]^a[14]^a[19]^a[24]; long d0 = c4 ^ Long.rotateLeft(c1, 1); long d1 = c0 ^ Long.rotateLeft(c2, 1); long d2 = c1 ^ Long.rotateLeft(c3, 1); long d3 = c2 ^ Long.rotateLeft(c4, 1); long d4 = c3 ^ Long.rotateLeft(c0, 1); for (int y = 0; y < a.length; y += DM) { a[y] ^= d0; a[y+1] ^= d1; a[y+2] ^= d2; a[y+3] ^= d3; a[y+4] ^= d4; } return a; }
Merged Step mapping Rho (section 3.2.2) and Pi (section 3.2.3). for performance. Optimization is achieved by precalculating shift constants for the following loop int xNext, yNext; for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) { int numberOfShift = ((t + 1)*(t + 2)/2) % 64; a[y][x] = Long.rotateLeft(a[y][x], numberOfShift); xNext = y; yNext = (2 * x + 3 * y) % DM; } and with inplace permutation.
/** * Merged Step mapping Rho (section 3.2.2) and Pi (section 3.2.3). * for performance. Optimization is achieved by precalculating * shift constants for the following loop * int xNext, yNext; * for (int t = 0, x = 1, y = 0; t <= 23; t++, x = xNext, y = yNext) { * int numberOfShift = ((t + 1)*(t + 2)/2) % 64; * a[y][x] = Long.rotateLeft(a[y][x], numberOfShift); * xNext = y; * yNext = (2 * x + 3 * y) % DM; * } * and with inplace permutation. */
private static long[] smPiRho(long[] a) { long tmp = Long.rotateLeft(a[10], 3); a[10] = Long.rotateLeft(a[1], 1); a[1] = Long.rotateLeft(a[6], 44); a[6] = Long.rotateLeft(a[9], 20); a[9] = Long.rotateLeft(a[22], 61); a[22] = Long.rotateLeft(a[14], 39); a[14] = Long.rotateLeft(a[20], 18); a[20] = Long.rotateLeft(a[2], 62); a[2] = Long.rotateLeft(a[12], 43); a[12] = Long.rotateLeft(a[13], 25); a[13] = Long.rotateLeft(a[19], 8); a[19] = Long.rotateLeft(a[23], 56); a[23] = Long.rotateLeft(a[15], 41); a[15] = Long.rotateLeft(a[4], 27); a[4] = Long.rotateLeft(a[24], 14); a[24] = Long.rotateLeft(a[21], 2); a[21] = Long.rotateLeft(a[8], 55); a[8] = Long.rotateLeft(a[16], 45); a[16] = Long.rotateLeft(a[5], 36); a[5] = Long.rotateLeft(a[3], 28); a[3] = Long.rotateLeft(a[18], 21); a[18] = Long.rotateLeft(a[17], 15); a[17] = Long.rotateLeft(a[11], 10); a[11] = Long.rotateLeft(a[7], 6); a[7] = tmp; return a; }
Step mapping Chi as defined in section 3.2.4.
/** * Step mapping Chi as defined in section 3.2.4. */
private static long[] smChi(long[] a) { for (int y = 0; y < a.length; y+=DM) { long ay0 = a[y]; long ay1 = a[y+1]; long ay2 = a[y+2]; long ay3 = a[y+3]; long ay4 = a[y+4]; a[y] = ay0 ^ ((~ay1) & ay2); a[y+1] = ay1 ^ ((~ay2) & ay3); a[y+2] = ay2 ^ ((~ay3) & ay4); a[y+3] = ay3 ^ ((~ay4) & ay0); a[y+4] = ay4 ^ ((~ay0) & ay1); } return a; }
Step mapping Iota as defined in section 3.2.5.
/** * Step mapping Iota as defined in section 3.2.5. */
private static long[] smIota(long[] a, int rndIndex) { a[0] ^= RC_CONSTANTS[rndIndex]; return a; }
The function Keccak as defined in section 5.2 with rate r = 1600 and capacity c = (digest length x 2).
/** * The function Keccak as defined in section 5.2 with * rate r = 1600 and capacity c = (digest length x 2). */
private void keccak() { // convert the 200-byte state into 25 lanes bytes2Lanes(state, lanes); // process the lanes through step mappings for (int ir = 0; ir < NR; ir++) { smIota(smChi(smPiRho(smTheta(lanes))), ir); } // convert the resulting 25 lanes back into 200-byte state lanes2Bytes(lanes, state); } public Object clone() throws CloneNotSupportedException { SHA3 copy = (SHA3) super.clone(); copy.state = copy.state.clone(); return copy; }
SHA3-224 implementation class.
/** * SHA3-224 implementation class. */
public static final class SHA224 extends SHA3 { public SHA224() { super("SHA3-224", 28); } }
SHA3-256 implementation class.
/** * SHA3-256 implementation class. */
public static final class SHA256 extends SHA3 { public SHA256() { super("SHA3-256", 32); } }
SHAs-384 implementation class.
/** * SHAs-384 implementation class. */
public static final class SHA384 extends SHA3 { public SHA384() { super("SHA3-384", 48); } }
SHA3-512 implementation class.
/** * SHA3-512 implementation class. */
public static final class SHA512 extends SHA3 { public SHA512() { super("SHA3-512", 64); } } }