Skip to content

Hashing

Hashing computes a fixed-size fingerprint (called a digest) from arbitrary input data. The same input always produces the same digest, but the process is one-way – you cannot recover the original data from the hash. Use hashing for checksums, data integrity verification, and content addressing.

Assumed imports

import dev.whyoleg.cryptography.*
import dev.whyoleg.cryptography.algorithms.*

val provider = CryptographyProvider.Default

Basic Usage

Get the algorithm from your provider, obtain a Hasher, and call hash:

val hasher = provider.get(SHA256).hasher()

val digest = hasher.hash("Hello, World!".encodeToByteArray())

// Same input always produces the same digest
val digest2 = hasher.hash("Hello, World!".encodeToByteArray())
println(digest.contentEquals(digest2)) // true

The Hasher is reusable – each hash call is independent and does not accumulate state.

For larger data, the overload that accepts a RawSource from kotlinx-io could be used instead:

val source: RawSource = ... // file, network stream, etc.
val digest = hasher.hash(source)

Pass-Through

Use updatingSource or updatingSink to hash data as it flows through a kotlinx-io pipeline. This is useful when you need both the data and its hash – for example, saving a file to disk while computing a checksum:

val hashFunction = hasher.createHashFunction()

// Wrap a source -- data passes through AND is fed into the hash
val source: RawSource = ...
val hashingSource: RawSource = hashFunction.updatingSource(source)

// Read all data from hashingSource (it goes to both the consumer and the hash)
val data = hashingSource.readByteArray()

// After reading, the hash is ready
val digest = hashFunction.hashToByteArray()

HashFunction implements AutoCloseable and support reset for a reuse. After finalization, call close, or wrap it in a use block:

val digest = hasher.createHashFunction().use { hf ->
    // ... feed data to function
    hf.hashToByteArray()
}

For the most control, use update directly to feed data in arbitrary chunks:

val hashFunction = hasher.createHashFunction()

hashFunction.update("Hello, ".encodeToByteArray())
hashFunction.update("World!".encodeToByteArray())

val digest = hashFunction.hashToByteArray()

The result is identical to hashing the full concatenated input in a single hash call.

Supported Algorithms

Algorithm JDK WebCrypto Apple CryptoKit OpenSSL3
SHA224 ✅ ❌ ✅ ❌ ✅
SHA256 ✅ ✅ ✅ ✅ ✅
SHA384 ✅ ✅ ✅ ✅ ✅
SHA512 ✅ ✅ ✅ ✅ ✅
SHA3 ✅ ❌ ❌ ❌ ✅
SHA1 ☣ ✅ ✅ ✅ ✅ ✅
MD5 ☣ ✅ ❌ ✅ ✅ ✅
RIPEMD160 ⚠ ✅ ❌ ❌ ❌ ✅