public abstract class SHAKEInputStream
extends java.io.InputStream
NIST (FIPS PUB 202) specifies the Secure Hash Algorithm-3 (SHA-3) family of message digest algorithms as supplement of the SHA-1 and SHA-2 message digest algorithm family. SHA-3 is based on the KECCAK message digest algorithm but is not fully identical to KECCAK because it adds a suffix to the message to ensure domain separation between the SHA-3 hash function and the newly specified SHA-3 Extendable-Output Function (XOF). The XOF allows the output to be extended to any desired length.
This class implements an InputStream for the SHAKE128 and SHAKE256 Extendable
Output Functions.
The suffix "128" or "256" does not indicate the (arbitrary) output
length of the XOF, it specifies its security strength.
SHAKE128 provides less than 128 bits of security if the output length d is
sufficiently small (see FIPS PUB 202). The collision resistance is min(d/2, 128),
the preimage resistance is >=min(d, 128), and the 2nd preimage resistance
is min(d,128). For example, if d = 224, then SHAKE128 provides min(224/2,128)=112
bits of collision resistance and min(224, 128) = 128 bits of preimage resistance (see FIPS PUB 202).
SHAKE256 provides less than 256 bits of security if the output length d is
sufficiently small (see FIPS PUB 202). The collision resistance is min(d/2, 256),
the preimage resistance is >=min(d, 256), and the 2nd preimage resistance
is min(d,256). For example, if d = 224, then SHAKE256 provides min(224/2,128)=112
bits of collision resistance and min(224, 256) = 224 bits of preimage resistance (see FIPS PUB 202).
Although it is possible to use an XOF as a hash function for a fixed output length,
XOFs have the potential for generating related outputs. When selecting two different
output length values for a common message, the two outputs of the XOF will be closely
related. The longer output will be an extension of the shorter output. For that reason
XOFs should be used with special care. See (the Security section of) NIST FIPS PUB 202
for more information! Please be aware that SHAKE128 is approved as XOF, but NOT as hash
function. Approved XOF use cases may be specified in further NIST Special Publications.
Currently the JCA API does not provide any engines for Extendable Output Functions.
Because of their relation to hash functions and the membership of SHAKE128 and SHAKE256 to the
SHA-3 family SHAKE may be used a MessageDigest
engine. A MessageDigest
engine, however, represents a hash function with a fixed-length digest output whereas
the output of an Extendable Output Function may have any length. In analogy to
a hash function the XOF first has to be updated with the input data. After the data
update has been completed output data of any length can be read from the XOF. This
reading functionality makes it possible to implement SHAKE as an input stream. However,
in difference to an ordinary input stream you first may have to update
the stream with the input data before subsequently reading
digest output from it, e.g:
// create the SHAKEInputStream SHAKE256InputStream shake256In = new SHAKE256InputStream(); ... // provide the input data by any required number of update calls: ... shake256In.update(m1); shake256In.update(m2); ... // after update has finished read output data of any desired length byte[] outBuf = ...; while (...) { shake256In.read(outBuf); } ... // close the stream shake256In.close();Note that the SHAKEInputStream by default will never produce an EOF since it is able to produce an arbitrary number of output bytes. Thus trying to read bytes until method
read
returns -1 may cause an infinite loop! For that reason you have take
care to actually get the requested amount of output data, e.g.:
SHAKE256InputStream shake256In = new SHAKE256InputStream(); ... // update with data ... int outputSize = ...; byte[] outputBuf = new byte[outputSize]; shake256In.read(outputBuf); shake256In.close();Alternatively you may let the SHAKEInputStream control the data reads by specifying the maximum output data size when creating the stream, e.g.:
int outputSize = ...; SHAKE256InputStream shake256In = new SHAKE256InputStream(outputSize); ... // update with data ... byte[] buf = new byte[2048]; int r = -1; while ((r = shake256In.read(buf)) != -1) { } shake256In.close();SHAKE is a based on a so-called sponge function. As you see from the examples above the usage of the SHAKEInputStream consists of two phases: during the update phase input data is absorbed by the XOF and during the read phase output data is squeezed from the XOF. As soon as you have started to read data from the stream you cannot provide update data anymore. However, SHAKEInputStream provides a
reset
functionality allowing to start a new data update phase without creating a new
stream:
... shake256In.reset(); ...
Modifier and Type | Method and Description |
---|---|
int |
available()
Returns the number of bytes available without blocking.
|
void |
close()
Closes this XOF stream.
|
int |
read()
Reads the next data byte from this XOF stream and returns it as an int
value between 0 and 255, or -1 if the end of the stream already has been
reached.
|
int |
read(byte[] b,
int off,
int len)
Reads up to
len bytes of output data from this XOF stream. |
void |
reset()
Resets this stream to be maybe updated with new data.
|
void |
setMaxReadSize(int maxReadSize)
Sets the maximum output (read) size of this XOF stream.
|
long |
skip(long n)
Skips up to a specified number of data bytes of this XOF stream and
returns the number of bytes skipped.
|
void |
update(byte input)
Updates the SHAKE engine with the given byte.
|
void |
update(byte[] input)
Updates the SHAKE engine with the given array.
|
void |
update(byte[] input,
int offset,
int len)
Updates the SHAKE engine with the given number of bytes, starting
at the given offset.
|
public void reset()
reset
in class java.io.InputStream
public void setMaxReadSize(int maxReadSize)
Since an Extendable Output Function may produce output of arbitrary size
trying to read output bytes from this stream until any of its read
methods returns -1 may cause an indefinite loop. For that reason the application
has to control outside the stream how many bytes shall be read. Alternatively
an application may use this method to specify the maximum possible output size
before starting to read from the stream. In this case the read
methods will return -1 if the specified output size has been reached or exceeded.
maxReadSize
- the maximum number of output bytes that can be read from this streamjava.lang.IllegalStateException
- if reading of data has been already startedjava.lang.IllegalArgumentException
- if maxReadSize is not positivepublic void update(byte input)
input
- the byte with which to update the SHAKE engine.java.lang.IllegalStateException
- if the stream is already in the read
phase or is already closedpublic void update(byte[] input, int offset, int len)
input
- the input byte arrayoffset
- the start position in the input arraylen
- the number of bytes, starting at offset
java.lang.IllegalStateException
- if the stream is already in the read
phase or is already closedpublic void update(byte[] input)
input
- the input byte array.java.lang.IllegalStateException
- if the stream is already in the read
phase or is already closedpublic int read(byte[] b, int off, int len) throws java.io.IOException
len
bytes of output data from this XOF stream.
Maximum len
bytes are read to the given byte array, beginning
at position off
.read
in class java.io.InputStream
b
- the byte array into which the data bytes are readoff
- the start offset in b
len
- the maximum number of bytes to be readjava.io.IOException
- if an I/O error occurspublic int read() throws java.io.IOException
read
in class java.io.InputStream
java.io.IOException
- if an I/O error occurspublic long skip(long n) throws java.io.IOException
Since the number of bytes actually skipped may not be equal (i.e. shorter) to the given number of bytes to skip, the number of bytes actually skipped are returned.
skip
in class java.io.InputStream
n
- the number of data bytes to skipjava.io.IOException
- if an I/O error occurspublic int available() throws java.io.IOException
available
in class java.io.InputStream
java.io.IOException
- if an I/O error occurspublic void close() throws java.io.IOException
close
in interface java.io.Closeable
close
in interface java.lang.AutoCloseable
close
in class java.io.InputStream
java.io.IOException
- if an IOException occurs during close