xof

Xof abstraction for Extendable-Output Functions

XOFs are very similar to Digest and Mac except that instead of calling digest() or doFinal(), which returns a fixed size ByteArray, their output size can be variable in length.

As such, KotlinCrypto takes the approach of making them distinctly different from those types, while implementing the same interfaces (Algorithm, Copyable, Resettable, Updatable).

Output for an Xof is done by reading, instead.

// Using SHAKE128 from KotlinCrypto/hash repo as an example
import org.kotlincrypto.hash.sha3.SHAKE128

fun main() {
val xof: Xof<SHAKE128> = SHAKE128.xOf()
val bytes = Random.Default.nextBytes(615)

// Xof implements interface Algorithm
println(xof.algorithm())
// SHAKE128

// Xof implements interface Updatable
xof.update(5.toByte())
xof.update(bytes)
xof.update(bytes, 10, 88)

// Xof implements interface Resettable
xof.reset()

xof.update(bytes)

// Xof implements interface Copyable
xof.copy()

val out1 = ByteArray(100)
val out2 = ByteArray(12345)

// Use produces a Reader which auto-closes when your action finishes.
// Reader is using a snapshot of the Xof state (thus the
// optional argument to resetXof with a default of true).
xof.use(resetXof = false) { read(out1, 0, out1.size); read(out2) }

val out3 = ByteArray(out1.size)
val out4 = ByteArray(out2.size)

// Can also create a Reader that won't auto-close
val reader = xof.reader(resetXof = false)
reader.read(out3)
reader.read(out4)
reader.close()

try {
// The Reader has been closed and will throw
// exception when trying to read from again.
reader.use { read(out4) }
} catch (e: IllegalStateException) {
e.printStackTrace()
}

// Contents are the same because Reader uses
// a snapshot of Xof, which was not updated
// between production of Readers.
assertContentEquals(out1 + out2, out3 + out4)

// Still able to update Xof, independent of the production
// and usage of Readers.
xof.update(10.toByte())
xof.use { read(out3); read(out4) }

try {
assertContentEquals(out1 + out2, out3 + out4)
throw IllegalStateException()
} catch (_: AssertionError) {
// pass
}
}
// Using CryptoRand from KotlinCrypto/random repo as an example
import org.kotlincrypto.random.CryptoRand
// Using KMAC128 from KotlinCrypto/MACs repo as an example
import org.kotlincrypto.macs.kmac.KMAC128

fun main() {
val key = CryptoRand.Default.nextBytes(ByteArray(100))
val kmacXof: Xof<KMAC128> = KMAC128.xOf(key)

// If Xof is for a Mac that implements ReKeyableXofAlgorithm,
// reinitialize the instance via the `Xof.Companion.reset`
// extension function for reuse.
val newKey = CryptoRand.Default.nextBytes(ByteArray(100))
kmacXof.reset(newKey = newKey)

// Or zero out key material before dereferencing
kmacXof.reset(newKey = ByteArray(1))
}

Packages

Link copied to clipboard
common