hash StreamProcessor is now public
better docs on BinaryId some sugar
This commit is contained in:
parent
8eed7a3de7
commit
194fe22afa
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "net.sergeych"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@ -5,17 +5,60 @@ import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import net.sergeych.bintools.CRC
|
||||
import net.sergeych.bintools.CRC8
|
||||
import net.sergeych.crypto2.BinaryId.Companion.createFromBytes
|
||||
import net.sergeych.crypto2.BinaryId.Companion.createFromString
|
||||
import net.sergeych.crypto2.BinaryId.Companion.createFromUBytes
|
||||
import net.sergeych.crypto2.BinaryId.Companion.createRandom
|
||||
import net.sergeych.crypto2.BinaryId.IncomparableException
|
||||
import net.sergeych.crypto2.BinaryId.InvalidException
|
||||
import net.sergeych.mp_tools.decodeBase64Url
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Binary identifier with control code and magic number. To create instaance
|
||||
* use one of [createFromBytes], [createFromString], [createFromUBytes],
|
||||
* or [createRandom], also deserialize serialized one.
|
||||
*
|
||||
* Integrity is checked on instantiating automatically.
|
||||
*
|
||||
* It is comparable to other BinaryId as long as both have the same [magic]. Attempt to
|
||||
* compare these that differ throws [IncomparableException]
|
||||
*
|
||||
* ### Internal structure
|
||||
*
|
||||
* Say we have a `BinaryId` of size `N` bytes. The inner structure will be:
|
||||
*
|
||||
* | offset | meaning |
|
||||
* |-----------|---------|
|
||||
* | 0 ..< N-2 | id bytes |
|
||||
* | N-2 | magic, 0..255 |
|
||||
* | N-1 | CRC8, polynomial 0xA7, as in Bluetooth |
|
||||
*
|
||||
* @throws InvalidException if crc check failed
|
||||
*/
|
||||
@Serializable
|
||||
open class BinaryId protected constructor (
|
||||
/**
|
||||
* The packed binary id. Note that serialized version is one byte longer containing
|
||||
* the size prefix
|
||||
*/
|
||||
val id: UByteArray,
|
||||
) : Comparable<BinaryId> {
|
||||
|
||||
/**
|
||||
* Bad format (crc does not match)
|
||||
*/
|
||||
class InvalidException(text: String) : IllegalArgumentException(text)
|
||||
|
||||
/**
|
||||
* Attempt to compare binary ids with different magic. In this case only [equals]
|
||||
* works, but [compareTo] throws this exception.
|
||||
*/
|
||||
class IncomparableException(text: String) : IllegalArgumentException(text)
|
||||
|
||||
/**
|
||||
* magic number (as decoded), `0..255`
|
||||
*/
|
||||
@Transient
|
||||
val magic: Int = run {
|
||||
if (id.size < 4) throw InvalidException("BinaryId is too short")
|
||||
@ -30,7 +73,9 @@ open class BinaryId protected constructor (
|
||||
private val innerData: UByteArray by lazy { id.sliceArray( 1..< id.size-1 ) }
|
||||
|
||||
/**
|
||||
* The id body: all the bytes except check and magic. These could carry useful information.
|
||||
* The ID body: all the bytes except check and magic. ID bytes could carry useful information.
|
||||
*
|
||||
* - `id.size` is [body] size + 2 (see [BinaryId] inner structure)
|
||||
*/
|
||||
val body: UByteArray by lazy { id.sliceArray( 0 until id.size-2 ) }
|
||||
|
||||
@ -41,6 +86,11 @@ open class BinaryId protected constructor (
|
||||
VerifyingPublicKey(body)
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to recnstruct a [PublicKey] from [id] bytes. For such keys, [PublicKey.id] and [SecretKey.id]
|
||||
* are made from public key bytes so it could be restored from such an ID
|
||||
*
|
||||
*/
|
||||
val asPublicKey: PublicKey by lazy {
|
||||
if( magic != KeysmagicNumber.defaultAssymmetric.ordinal)
|
||||
throw InvalidException("It is not a veryfing key: magic=$magic, required ${KeysmagicNumber.defaultAssymmetric.ordinal}")
|
||||
@ -50,6 +100,11 @@ open class BinaryId protected constructor (
|
||||
|
||||
override fun toString(): String = id.encodeToBase64Url()
|
||||
|
||||
/**
|
||||
* Compare to another ID which __must have the same [magic]__ number; note that [equals]
|
||||
* works well despite magic inequity.
|
||||
* @throws IncomparableException if magic id do not match
|
||||
*/
|
||||
override fun compareTo(other: BinaryId): Int {
|
||||
if (other.magic != magic) throw IncomparableException("Mask mismatch (my=$magic their=${other.magic})")
|
||||
val id1 = other.id
|
||||
|
@ -70,7 +70,14 @@ class ByteChunk(val data: UByteArray): Comparable<ByteChunk> {
|
||||
*/
|
||||
operator fun plus(other: ByteChunk): ByteChunk = ByteChunk(data + other.data)
|
||||
|
||||
fun toByteArray(): ByteArray = data.asByteArray()
|
||||
fun toUByteArray(): UByteArray = data
|
||||
|
||||
companion object {
|
||||
fun fromHex(hex: String): ByteChunk = ByteChunk(hex.decodeHex().asUByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun ByteArray.asChunk() = ByteChunk(toUByteArray())
|
||||
fun UByteArray.asChunk(): ByteChunk = ByteChunk(this)
|
@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import org.kotlincrypto.hash.sha3.SHA3_256
|
||||
import org.kotlincrypto.hash.sha3.SHA3_384
|
||||
|
||||
private interface StreamProcessor {
|
||||
interface StreamProcessor {
|
||||
fun update(data: UByteArray)
|
||||
fun final(): UByteArray
|
||||
}
|
||||
@ -23,7 +23,7 @@ private interface StreamProcessor {
|
||||
@Suppress("unused")
|
||||
enum class Hash(
|
||||
private val direct: ((UByteArray) -> UByteArray)? = null,
|
||||
private val streamProcessor: () -> StreamProcessor,
|
||||
val streamProcessor: () -> StreamProcessor,
|
||||
) {
|
||||
|
||||
Blake2b(
|
||||
@ -111,7 +111,6 @@ enum class Hash(
|
||||
for (block in source) sp.update(block)
|
||||
return sp.final()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val defaultSuffix1 = "All lay loads on a willing horse".encodeToUByteArray()
|
||||
@ -122,6 +121,8 @@ private val defaultSuffix2 = "A stitch in time saves nine".encodeToUByteArray()
|
||||
*/
|
||||
fun blake2b(src: UByteArray): UByteArray = Hash.Blake2b.digest(src)
|
||||
|
||||
fun blake2b(src: ByteChunk): ByteChunk = blake2b(src.data).asChunk()
|
||||
|
||||
/**
|
||||
* Double linked Blake2b using the default or specified suffix. This should be more hard to
|
||||
* brute force.collision attack than just [blake2b]. Note that different suffixes provide different
|
||||
|
16
src/commonTest/kotlin/BinaryIdTest.kt
Normal file
16
src/commonTest/kotlin/BinaryIdTest.kt
Normal file
@ -0,0 +1,16 @@
|
||||
import net.sergeych.crypto2.BinaryId
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class BinaryIdTest {
|
||||
@Test
|
||||
fun testSizes() {
|
||||
val a = BinaryId.createRandom(5, 4)
|
||||
// println(a.id.toDump())
|
||||
// println(pack(a).toDump())
|
||||
assertEquals(2, a.body.size)
|
||||
assertEquals(5, a.magic)
|
||||
assertEquals(4, a.id.size)
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user