java.lang.Object
net.i2p.data.SimpleDataStructure
net.i2p.data.Hash
- All Implemented Interfaces:
DataStructure
A 32-byte SHA-256 hash, used throughout I2P as a destination, router, or tunnel identifier and as an integrity value for hashed data.
Creating a Hash:
create(byte[])and its siblings go through a staticSDSCacheand are the preferred way to obtain one. The cache is keyed on the first 4 bytes of the data and holds weak references, so entries disappear under memory pressure; its maximum size is scaled by the JVM's available memory. On a cache hit the byte array passed in is handed back toSimpleByteCachefor reuse and must not be touched afterwards.new Hash(byte[])bypasses the cache entirely. Use create() when the same hash may be built repeatedly.create(InputStream)reads exactly 32 bytes from the stream and wraps them; it does not hash the stream. To hash arbitrary data, useSimpleDataStructure.calculateHash()or a SHA256Generator.
Rendering:
toBase64()caches its result in a volatile field.toBase32()caches its result the same way.
Comparison:
hashCode()is the precomputed value of the first 4 bytes, held in a volatile field. It is not constant-time.- equals() is inherited from
SimpleDataStructureand isArrays.equals(byte[], byte[])- not constant-time, and not class-specific, so another 32-byte SimpleDataStructure such as aSessionKeyholding the same bytes compares equal to a Hash.
Thread safety:
- The data cannot be reassigned once set, so a Hash that is safely published (constructed and then handed to other threads) can be shared freely; the derived
_base64ed,_base32edand_cachedHashCodefields are volatile.SimpleDataStructure._dataitself is neither final nor volatile, so a Hash built by a constructor and published through an unsynchronized data structure may expose stale data. SimpleDataStructure.getData()hands out the backing array, so a caller that mutates it corrupts the cached hash code and the cached Base64 and Base32 strings, as well as any byte cache that shares the array.
Field Summary
Modifier and TypeFieldDescriptionprivate StringCache of the Base32 form.private StringCache of the Base64 form.Shared cache of parsed hashes.private intCache of the computed hash code.private static final intInitial cache capacity, scaled by available memory bySDSCache.static final HashPlaceholder all-zero hash, used as a stand-in when no real router hash is known.static final intLength of SHA-256 hash in bytes.Fields inherited from class SimpleDataStructure
_dataConstructor Summary
Method Summary
Modifier and TypeMethodDescriptionstatic voidDrop the shared cache of Hash instances, so cached instances become eligible for collection.static Hashcreate(byte[] data) Pull from cache or return newstatic Hashcreate(byte[] data, int off) Pull from cache or return new.static Hashcreate(InputStream in) Pull from cache or return new.inthashCode()A Hash is a hash, so just use the first 4 bytes for speed.intlength()Hash length in bytes.voidreadBytes(InputStream in) Reads the hash from an input stream.voidsetData(byte[] data) IllegalArgumentException if data is not 32 bytes (null is ok).toBase32()The .b32.i2p form of the hash.toBase64()Returns the hash as a Base64 string.Methods inherited from class SimpleDataStructure
calculateHash, equals, fromBase64, fromByteArray, getData, read, toByteArray, toString, writeBytesModifier and TypeMethodDescriptionSHA256 hash of the byte array, or null if data is null.booleanCompares the raw data only: two different SimpleDataStructure subclasses of the same length holding the same bytes are equal, e.g.voidfromBase64(String data) Data from the base64 string.voidfromByteArray(byte[] data) Does the same thing asSimpleDataStructure.setData(byte[])but null not allowed.byte[]getData()Data reference (not a copy).protected intread(InputStream in, byte[] target) Repeated reads until the buffer is full or IOException is thrown.byte[]Same thing as getData().toString()Returns a string representation of this data structure.voidwriteBytes(OutputStream out) Writes the data to the output stream.
Field Details
_base64ed
Cache of the Base64 form._base32ed
Cache of the Base32 form._cachedHashCode
private volatile int _cachedHashCodeCache of the computed hash code.HASH_LENGTH
FAKE_HASH
Placeholder all-zero hash, used as a stand-in when no real router hash is known.CACHE_SIZE
private static final int CACHE_SIZEInitial cache capacity, scaled by available memory bySDSCache.- See Also:
_cache
Constructor Details
Hash
public Hash()Create an empty hash (data is null).Hash
public Hash(byte[] data) IllegalArgumentException if data is not 32 bytes (null is ok).- Parameters:
data- the 32 bytes to copy into the hash, with null leaving the data unset- Throws:
IllegalArgumentException- if data is not 32 bytes (null is ok)
Method Details
create
Pull from cache or return newWARNING - If the SDS is found in the cache, the passed-in byte array will be returned to the SimpleByteCache for reuse. Do NOT save a reference to the passed-in data, or use or modify it, after this call.
Ignore this warning and you WILL corrupt the cache or other data structures.
- Parameters:
data- the 32 bytes to wrap- Returns:
- the cached or new hash
- Throws:
NullPointerException- if data is nullRuntimeException- if data is not the correct number of bytes (SDSCache wraps the constructor's IllegalArgumentException)
create
Pull from cache or return new.- Parameters:
data- the buffer holding the 32 bytes to wrapoff- the index within that buffer of the first of the 32 bytes- Returns:
- the cached or new hash
- Throws:
ArrayIndexOutOfBoundsException- if not enough bytes
create
Pull from cache or return new.- Parameters:
in- the stream read for exactly the 32 bytes of the hash- Returns:
- the cached or new hash
- Throws:
IOException- if the stream cannot be read or holds fewer than 32 bytes
length
public int length()Hash length in bytes.- Specified by:
lengthin classSimpleDataStructure- Returns:
- the legal length of the byte array
setData
public void setData(byte[] data) IllegalArgumentException if data is not 32 bytes (null is ok).- Overrides:
setDatain classSimpleDataStructure- Parameters:
data- of correct length, or null- Throws:
IllegalArgumentException- if data is not 32 bytes (null is ok)
readBytes
Reads the hash from an input stream.- Specified by:
readBytesin interfaceDataStructure- Overrides:
readBytesin classSimpleDataStructure- Parameters:
in- the stream to read- Throws:
DataFormatException- if the data is improperly formattedIOException- if there was a problem reading the stream
hashCode
public int hashCode()A Hash is a hash, so just use the first 4 bytes for speed. Precomputed at data-assignment time, so this does not read the data.- Overrides:
hashCodein classSimpleDataStructure- Returns:
- the hash code
toBase64
Returns the hash as a Base64 string. Cached after the first call.- Specified by:
toBase64in interfaceDataStructure- Overrides:
toBase64in classSimpleDataStructure- Returns:
- null on error
toBase32
The .b32.i2p form of the hash. Cached after the first call, liketoBase64(), and dropped by setData() and readBytes().- Returns:
- "{52 chars}.b32.i2p" or null if data not set.
clearCache
public static void clearCache()Drop the shared cache of Hash instances, so cached instances become eligible for collection. Hashes already handed to callers are unaffected, and the byte arrays the cached instances held are not returned to the byte cache.