forked from sergeych/crypto2
		
	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