From f2c23cb3a37916bd5ae54c6d298e00cf1d38c8db Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Sat, 11 Jan 2025 06:26:26 -0500 Subject: [PATCH 1/4] Update Xof benchmarks --- .../org/kotlincrypto/core/benchmarks/XofOps.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt index 2d538d1..9f676eb 100644 --- a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt +++ b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt @@ -28,18 +28,18 @@ import kotlin.random.Random @OptIn(InternalKotlinCryptoApi::class) open class XofUtilsBenchmark { - private val longs: LongArray = LongArray(10) { Random.Default.nextLong() } - private val loHi = Array(longs.size) { longs[it].let { l -> l.toInt() to l.rotateLeft(32).toInt() } } + @Benchmark + fun leftEncodeLong() { + Xof.Utils.leftEncode(-99993873488683833L) + } @Benchmark - fun leftEncodeLongs() { - val longs = longs - longs.forEach { long -> Xof.Utils.leftEncode(long) } + fun leftEncodeInt() { + Xof.Utils.leftEncode( 11978435) } @Benchmark fun leftEncodeLoHi() { - val loHi = loHi - loHi.forEach { Xof.Utils.leftEncode(it.first, it.second) } + Xof.Utils.leftEncode(184581845, 11978435) } } From b55994448e4a6cb7ac4f24e2adf7caf01f70929d Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Sat, 11 Jan 2025 06:36:29 -0500 Subject: [PATCH 2/4] Inline secondary digest function body --- .../core/digest/internal/-Buffer.kt | 65 ++++++++++--------- .../org/kotlincrypto/core/digest/Digest.kt | 22 +++++-- .../org/kotlincrypto/core/digest/Digest.kt | 22 +++++-- 3 files changed, 65 insertions(+), 44 deletions(-) diff --git a/library/digest/src/commonMain/kotlin/org/kotlincrypto/core/digest/internal/-Buffer.kt b/library/digest/src/commonMain/kotlin/org/kotlincrypto/core/digest/internal/-Buffer.kt index da11e58..7537155 100644 --- a/library/digest/src/commonMain/kotlin/org/kotlincrypto/core/digest/internal/-Buffer.kt +++ b/library/digest/src/commonMain/kotlin/org/kotlincrypto/core/digest/internal/-Buffer.kt @@ -13,37 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -@file:Suppress("KotlinRedundantDiagnosticSuppress") +@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE") package org.kotlincrypto.core.digest.internal +import org.kotlincrypto.core.digest.Digest import kotlin.jvm.JvmInline -import kotlin.jvm.JvmSynthetic @JvmInline -internal value class Buffer private constructor(internal val value: ByteArray) { - - internal fun copy(): Buffer = Buffer(value.copyOf()) - - internal companion object { - - @JvmSynthetic - @Throws(IllegalArgumentException::class) - internal fun initialize( - algorithm: String, - blockSize: Int, - digestLength: Int, - ): Buffer { - require(algorithm.isNotBlank()) { "algorithm cannot be blank" } - require(blockSize > 0) { "blockSize must be greater than 0" } - require(blockSize % 8 == 0) { "blockSize must be a factor of 8" } - require(digestLength >= 0) { "digestLength cannot be negative" } - return Buffer(ByteArray(blockSize)) - } - } +internal value class Buffer internal constructor(internal val value: ByteArray) + +@Throws(IllegalArgumentException::class) +@Suppress("UnusedReceiverParameter") +internal inline fun Digest.initializeBuffer( + algorithm: String, + blockSize: Int, + digestLength: Int, +): Buffer { + require(algorithm.isNotBlank()) { "algorithm cannot be blank" } + require(blockSize > 0) { "blockSize must be greater than 0" } + require(blockSize % 8 == 0) { "blockSize must be a factor of 8" } + require(digestLength >= 0) { "digestLength cannot be negative" } + return Buffer(ByteArray(blockSize)) } -@Suppress("NOTHING_TO_INLINE") +internal inline fun Buffer.copy(): Buffer = Buffer(value.copyOf()) + internal inline fun Buffer.commonUpdate( input: Byte, bufPosPlusPlus: Int, @@ -59,7 +54,6 @@ internal inline fun Buffer.commonUpdate( bufPosSet(0) } -@Suppress("NOTHING_TO_INLINE") internal inline fun Buffer.commonUpdate( input: ByteArray, offset: Int, @@ -111,20 +105,31 @@ internal inline fun Buffer.commonUpdate( bufPosSet(posBuf) } -@Suppress("NOTHING_TO_INLINE") +internal inline fun Buffer.commonDigest( + input: ByteArray, + updateProtected: (ByteArray, Int, Int) -> Unit, + bufPosGet: () -> Int, + digestProtected: (buf: ByteArray, bufPos: Int) -> ByteArray, + resetProtected: () -> Unit, + bufPosSet: (zero: Int) -> Unit, +): ByteArray { + updateProtected(input, 0, input.size) + return commonDigest(bufPosGet(), digestProtected, resetProtected, bufPosSet) +} + internal inline fun Buffer.commonDigest( bufPos: Int, digestProtected: (buf: ByteArray, bufPos: Int) -> ByteArray, - reset: () -> Unit, + resetProtected: () -> Unit, + bufPosSet: (zero: Int) -> Unit, ): ByteArray { // Zeroize any stale input that may be left in the buffer value.fill(0, bufPos) - val final = digestProtected(value, bufPos) - reset() - return final + val digest = digestProtected(value, bufPos) + commonReset(resetProtected, bufPosSet) + return digest } -@Suppress("NOTHING_TO_INLINE") internal inline fun Buffer.commonReset( resetProtected: () -> Unit, bufPosSet: (zero: Int) -> Unit, diff --git a/library/digest/src/jvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt b/library/digest/src/jvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt index b3b95cd..4171c62 100644 --- a/library/digest/src/jvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt +++ b/library/digest/src/jvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt @@ -57,7 +57,7 @@ public actual abstract class Digest: MessageDigest, Algorithm, Cloneable, Copyab * */ @Throws(IllegalArgumentException::class) protected actual constructor(algorithm: String, blockSize: Int, digestLength: Int): super(algorithm) { - this.buf = Buffer.initialize(algorithm, blockSize, digestLength) + this.buf = initializeBuffer(algorithm, blockSize, digestLength) this.digestLength = digestLength this.bufPos = 0 } @@ -127,7 +127,8 @@ public actual abstract class Digest: MessageDigest, Algorithm, Cloneable, Copyab public actual final override fun digest(): ByteArray = buf.commonDigest( bufPos = bufPos, digestProtected = ::digestProtected, - reset = ::reset + resetProtected = ::resetProtected, + bufPosSet = { bufPos = it }, ) /** @@ -135,14 +136,21 @@ public actual abstract class Digest: MessageDigest, Algorithm, Cloneable, Copyab * performing final operations and returning the resultant array of bytes. The * [Digest] is [reset] afterward. * */ - public actual final override fun digest(input: ByteArray): ByteArray { - updateProtected(input, 0, input.size) - return digest() - } + public actual final override fun digest(input: ByteArray): ByteArray = buf.commonDigest( + input = input, + updateProtected = ::updateProtected, + bufPosGet = ::bufPos, + digestProtected = ::digestProtected, + resetProtected = ::resetProtected, + bufPosSet = { bufPos = it }, + ) // See Resettable interface documentation public actual final override fun reset() { - buf.commonReset(::resetProtected) { bufPos = it } + buf.commonReset( + resetProtected = ::resetProtected, + bufPosSet = { bufPos = it }, + ) } /** diff --git a/library/digest/src/nonJvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt b/library/digest/src/nonJvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt index 9fd87f2..3633aae 100644 --- a/library/digest/src/nonJvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt +++ b/library/digest/src/nonJvmMain/kotlin/org/kotlincrypto/core/digest/Digest.kt @@ -52,7 +52,7 @@ public actual abstract class Digest: Algorithm, Copyable, Resettable, Up * */ @Throws(IllegalArgumentException::class) protected actual constructor(algorithm: String, blockSize: Int, digestLength: Int) { - this.buf = Buffer.initialize(algorithm, blockSize, digestLength) + this.buf = initializeBuffer(algorithm, blockSize, digestLength) this.algorithm = algorithm this.digestLength = digestLength this.bufPos = 0 @@ -124,7 +124,8 @@ public actual abstract class Digest: Algorithm, Copyable, Resettable, Up public actual fun digest(): ByteArray = buf.commonDigest( bufPos = bufPos, digestProtected = ::digestProtected, - reset = ::reset, + resetProtected = ::resetProtected, + bufPosSet = { bufPos = it }, ) /** @@ -132,14 +133,21 @@ public actual abstract class Digest: Algorithm, Copyable, Resettable, Up * performing final operations and returning the resultant array of bytes. The * [Digest] is [reset] afterward. * */ - public actual fun digest(input: ByteArray): ByteArray { - updateProtected(input, 0, input.size) - return digest() - } + public actual fun digest(input: ByteArray): ByteArray = buf.commonDigest( + input = input, + updateProtected = ::updateProtected, + bufPosGet = ::bufPos, + digestProtected = ::digestProtected, + resetProtected = ::resetProtected, + bufPosSet = { bufPos = it }, + ) // See Resettable interface documentation public actual final override fun reset() { - buf.commonReset(::resetProtected) { bufPos = it } + buf.commonReset( + resetProtected = ::resetProtected, + bufPosSet = { bufPos = it }, + ) } /** From 71ce8624025c225294f23b6b7a29057f28a52c7b Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Sat, 11 Jan 2025 06:37:06 -0500 Subject: [PATCH 3/4] Inline private Xof.Utils.encode function to callsites --- .../kotlincrypto/core/benchmarks/DigestOps.kt | 2 ++ .../org/kotlincrypto/core/benchmarks/XofOps.kt | 3 ++- .../kotlin/org/kotlincrypto/core/xof/Xof.kt | 18 +++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/DigestOps.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/DigestOps.kt index e004033..7ae5340 100644 --- a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/DigestOps.kt +++ b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/DigestOps.kt @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +@file:Suppress("unused") + package org.kotlincrypto.core.benchmarks import kotlinx.benchmark.* diff --git a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt index 9f676eb..88f1757 100644 --- a/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt +++ b/benchmarks/src/commonMain/kotlin/org/kotlincrypto/core/benchmarks/XofOps.kt @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +@file:Suppress("unused") + package org.kotlincrypto.core.benchmarks import kotlinx.benchmark.* import org.kotlincrypto.core.InternalKotlinCryptoApi import org.kotlincrypto.core.xof.Xof -import kotlin.random.Random @State(Scope.Benchmark) @BenchmarkMode(Mode.AverageTime) diff --git a/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt b/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt index a552425..0c47215 100644 --- a/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt +++ b/library/xof/src/commonMain/kotlin/org/kotlincrypto/core/xof/Xof.kt @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +@file:Suppress("KotlinRedundantDiagnosticSuppress", "NOTHING_TO_INLINE") + package org.kotlincrypto.core.xof import org.kotlincrypto.core.* @@ -209,9 +211,7 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl @JvmStatic public fun leftEncode(value: Long): ByteArray { - val lo = value.toInt() - val hi = value.rotateLeft(32).toInt() - return encode(lo = lo, hi = hi, left = true) + return encode(lo = value.lo(), hi = value.hi(), left = true) } @JvmStatic @@ -226,9 +226,7 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl @JvmStatic public fun rightEncode(value: Long): ByteArray { - val lo = value.toInt() - val hi = value.rotateLeft(32).toInt() - return encode(lo = lo, hi = hi, left = false) + return encode(lo = value.lo(), hi = value.hi(), left = false) } @JvmStatic @@ -237,7 +235,13 @@ public sealed class Xof: Algorithm, Copyable>, Resettabl } @JvmStatic - private fun encode(lo: Int, hi: Int, left: Boolean): ByteArray { + private inline fun Long.lo(): Int = toInt() + + @JvmStatic + private inline fun Long.hi(): Int = rotateLeft(32).toInt() + + @JvmStatic + private inline fun encode(lo: Int, hi: Int, left: Boolean): ByteArray { val a = if (hi == 0) { if (lo == 0) { // If it's zero, return early From d9e872b25fc599349b2f4d1f9e79176777fadb01 Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Sat, 11 Jan 2025 06:37:27 -0500 Subject: [PATCH 4/4] Decrement next version release to 0.6.0 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index b611902..4c6a9ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,10 +30,10 @@ POM_DEVELOPER_ID=KotlinCrypto POM_DEVELOPER_NAME=Kotlin Crypto POM_DEVELOPER_URL=https://github.com/KotlinCrypto/ -VERSION_NAME=1.0.0-alpha01-SNAPSHOT +VERSION_NAME=0.6.0-SNAPSHOT # 0.1.0-alpha01 = 00 01 00 11 # 0.1.0-beta01 = 00 01 00 21 # 0.1.0-rc01 = 00 01 00 31 # 0.1.0 = 00 01 00 99 # 1.1.0 = 01 01 00 99 -VERSION_CODE=01000011 +VERSION_CODE=00060011