Extracted interfaces for hashes

This commit is contained in:
Ugljesa Jovanovic 2019-07-21 12:26:41 +02:00
parent 995cb23176
commit 6d8024cf7f
No known key found for this signature in database
GPG Key ID: 46D004C9820EBB98
12 changed files with 162 additions and 112 deletions

View File

@ -14,14 +14,37 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto package com.ionspin.kotlin.crypto.hash
/** /**
* Created by Ugljesa Jovanovic * Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com * ugljesa.jovanovic@ionspin.com
* on 20-Jul-2019 * on 20-Jul-2019
*/ */
interface Hash interface Hash {
val MAX_HASH_BYTES : Int
}
interface UpdateableHash : Hash @ExperimentalUnsignedTypes
interface UpdateableHash : Hash {
fun update(data : Array<UByte>)
fun update(data : String)
fun digest() : Array<UByte>
fun digestString() : String
}
@ExperimentalUnsignedTypes
interface StatelessHash : Hash {
fun digest(inputString: String, key: String? = null, hashLength: Int = MAX_HASH_BYTES): Array<UByte>
fun digest(
inputMessage: Array<UByte> = emptyArray(),
key: Array<UByte> = emptyArray(),
hashLength: Int = MAX_HASH_BYTES
): Array<UByte>
}

View File

@ -14,14 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.blake2b package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.bignum.integer.BigInteger import com.ionspin.kotlin.bignum.integer.BigInteger
import com.ionspin.kotlin.bignum.integer.toBigInteger import com.ionspin.kotlin.bignum.integer.toBigInteger
import com.ionspin.kotlin.crypto.* import com.ionspin.kotlin.crypto.*
import kotlinx.coroutines.CoroutineScope import com.ionspin.kotlin.crypto.hash.StatelessHash
import kotlinx.coroutines.Dispatchers import com.ionspin.kotlin.crypto.hash.UpdateableHash
import kotlinx.coroutines.Job
/** /**
* Created by Ugljesa Jovanovic * Created by Ugljesa Jovanovic
@ -31,12 +30,13 @@ import kotlinx.coroutines.Job
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : UpdateableHash { class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : UpdateableHash {
companion object : Hash {
companion object : StatelessHash {
const val BITS_IN_WORD = 64 const val BITS_IN_WORD = 64
const val ROUNDS_IN_COMPRESS = 12 const val ROUNDS_IN_COMPRESS = 12
const val BLOCK_BYTES = 128 const val BLOCK_BYTES = 128
const val MAX_HASH_BYTES = 64 override val MAX_HASH_BYTES = 64
const val MIN_HASH_BYTES = 1 const val MIN_HASH_BYTES = 1
const val MAX_KEY_BYTES = 64 const val MAX_KEY_BYTES = 64
const val MIN_KEY_BYTES = 0 const val MIN_KEY_BYTES = 0
@ -143,38 +143,39 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatea
} }
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun digest(inputString: String, key: String? = null): Array<UByte> { override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
val chunked = inputString.encodeToByteArray().map { it.toUByte() }.toList().chunked(BLOCK_BYTES) val array = inputString.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray()
.map { it.toTypedArray() }.toTypedArray()
val keyBytes = key?.run { val keyBytes = key?.run {
encodeToByteArray().map { it.toUByte() }.toTypedArray() encodeToByteArray().map { it.toUByte() }.toTypedArray()
} ?: emptyArray() } ?: emptyArray()
return digest(inputMessage = chunked, secretKey = keyBytes) return digest(inputMessage = array, key = keyBytes)
} }
fun digest( override fun digest(
inputMessage: Array<Array<UByte>> = emptyArray(), inputMessage: Array<UByte>,
secretKey: Array<UByte> = emptyArray(), key: Array<UByte>,
hashLength: Int = MAX_HASH_BYTES hashLength: Int
): Array<UByte> { ): Array<UByte> {
val chunkedMessage = inputMessage.chunked(BLOCK_BYTES)
val h = iv.copyOf() val h = iv.copyOf()
h[0] = h[0] xor 0x01010000UL xor (secretKey.size.toULong() shl 8) xor hashLength.toULong() h[0] = h[0] xor 0x01010000UL xor (key.size.toULong() shl 8) xor hashLength.toULong()
val message = if (secretKey.isEmpty()) { val message = if (key.isEmpty()) {
if (inputMessage.isEmpty()) { if (chunkedMessage.isEmpty()) {
Array(1) { Array(1) {
Array<UByte>(128) { Array<UByte>(128) {
0U 0U
} }
} }
} else { } else {
inputMessage chunkedMessage
} }
} else { } else {
arrayOf(padToBlock(secretKey), *inputMessage) arrayOf(padToBlock(key), *chunkedMessage)
} }
if (message.size > 1) { if (message.size > 1) {
@ -246,6 +247,8 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatea
requestedHashLenght requestedHashLenght
) )
override val MAX_HASH_BYTES: Int = Blake2b.MAX_HASH_BYTES
var h = iv.copyOf() var h = iv.copyOf()
var counter = BigInteger.ZERO var counter = BigInteger.ZERO
var bufferCounter = 0 var bufferCounter = 0
@ -260,15 +263,15 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatea
} }
} }
fun update(array: Array<UByte>) { override fun update(data: Array<UByte>) {
if (array.isEmpty()) { if (data.isEmpty()) {
throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating") throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
} }
when { when {
bufferCounter + array.size < BLOCK_BYTES -> appendToBuffer(array, bufferCounter) bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
bufferCounter + array.size >= BLOCK_BYTES -> { bufferCounter + data.size >= BLOCK_BYTES -> {
val chunked = array.chunked(BLOCK_BYTES) val chunked = data.chunked(BLOCK_BYTES)
chunked.forEach { chunk -> chunked.forEach { chunk ->
if (bufferCounter + chunk.size < BLOCK_BYTES) { if (bufferCounter + chunk.size < BLOCK_BYTES) {
appendToBuffer(chunk, bufferCounter) appendToBuffer(chunk, bufferCounter)
@ -301,8 +304,8 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatea
} }
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun update(input: String) { override fun update(data: String) {
update(input.encodeToByteArray().map { it.toUByte() }.toTypedArray()) update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
} }
private fun appendToBuffer(array: Array<UByte>, start: Int) { private fun appendToBuffer(array: Array<UByte>, start: Int) {
@ -314,7 +317,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatea
h = compress(h, block, counter, false) h = compress(h, block, counter, false)
} }
fun digest(): Array<UByte> { override fun digest(): Array<UByte> {
val lastBlockPadded = padToBlock(buffer) val lastBlockPadded = padToBlock(buffer)
counter += bufferCounter counter += bufferCounter
compress(h, lastBlockPadded, counter, true) compress(h, lastBlockPadded, counter, true)
@ -325,7 +328,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatea
} }
fun digestString(): String { override fun digestString(): String {
return digest().map { it.toString(16) }.joinToString(separator = "") return digest().map { it.toString(16) }.joinToString(separator = "")
} }

View File

@ -14,10 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.sha package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.Hash
import com.ionspin.kotlin.crypto.chunked import com.ionspin.kotlin.crypto.chunked
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdateableHash
import com.ionspin.kotlin.crypto.rotateRight import com.ionspin.kotlin.crypto.rotateRight
@ -29,15 +30,20 @@ import com.ionspin.kotlin.crypto.rotateRight
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class Sha256 : Hash { class Sha256 : UpdateableHash {
companion object { override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash {
const val BLOCK_SIZE = 512 const val BLOCK_SIZE = 512
const val BLOCK_SIZE_IN_BYTES = 64 const val BLOCK_SIZE_IN_BYTES = 64
const val UINT_MASK = 0xFFFFFFFFU const val UINT_MASK = 0xFFFFFFFFU
const val BYTE_MASK_FROM_ULONG = 0xFFUL const val BYTE_MASK_FROM_ULONG = 0xFFUL
const val BYTE_MASK_FROM_UINT = 0xFFU const val BYTE_MASK_FROM_UINT = 0xFFU
override val MAX_HASH_BYTES: Int = 32
val iv = arrayOf( val iv = arrayOf(
0x6a09e667U, 0x6a09e667U,
0xbb67ae85U, 0xbb67ae85U,
@ -61,20 +67,23 @@ class Sha256 : Hash {
) )
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun digest(message: String): Array<UByte> { override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
return digest(message.encodeToByteArray().map { it.toUByte() }.toTypedArray()) return digest(
inputString.encodeToByteArray().map { it.toUByte() }.toTypedArray(),
key?.run { encodeToByteArray().map { it.toUByte() }.toTypedArray() } ?: emptyArray<UByte>(),
hashLength)
} }
fun digest(message: Array<UByte>): Array<UByte> { override fun digest(inputMessage: Array<UByte>, key: Array<UByte>, hashLength: Int): Array<UByte> {
var h = iv.copyOf() var h = iv.copyOf()
val expansionArray = createExpansionArray(message.size) val expansionArray = createExpansionArray(inputMessage.size)
val chunks = ( val chunks = (
message + inputMessage +
expansionArray + expansionArray +
(message.size * 8).toULong().toPaddedByteArray() (inputMessage.size * 8).toULong().toPaddedByteArray()
) )
.chunked(BLOCK_SIZE_IN_BYTES) .chunked(BLOCK_SIZE_IN_BYTES)
@ -236,19 +245,19 @@ class Sha256 : Hash {
var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U } var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun update(message: String) { override fun update(data: String) {
return update(message.encodeToByteArray().map { it.toUByte() }.toTypedArray()) return update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
} }
fun update(array: Array<UByte>) { override fun update(data: Array<UByte>) {
if (array.isEmpty()) { if (data.isEmpty()) {
throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating") throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
} }
when { when {
bufferCounter + array.size < BLOCK_SIZE_IN_BYTES -> appendToBuffer(array, bufferCounter) bufferCounter + data.size < BLOCK_SIZE_IN_BYTES -> appendToBuffer(data, bufferCounter)
bufferCounter + array.size >= BLOCK_SIZE_IN_BYTES -> { bufferCounter + data.size >= BLOCK_SIZE_IN_BYTES -> {
val chunked = array.chunked(BLOCK_SIZE_IN_BYTES) val chunked = data.chunked(BLOCK_SIZE_IN_BYTES)
chunked.forEach { chunk -> chunked.forEach { chunk ->
if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) { if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
appendToBuffer(chunk, bufferCounter) appendToBuffer(chunk, bufferCounter)
@ -285,10 +294,11 @@ class Sha256 : Hash {
mix(h, w).copyInto(h) mix(h, w).copyInto(h)
} }
fun digest() : Array<UByte> { override fun digest(): Array<UByte> {
val length = counter + bufferCounter val length = counter + bufferCounter
val expansionArray = createExpansionArray(length) val expansionArray = createExpansionArray(length)
val finalBlock = buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPaddedByteArray() val finalBlock =
buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPaddedByteArray()
finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach { finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
consumeBlock(it) consumeBlock(it)
} }
@ -305,11 +315,14 @@ class Sha256 : Hash {
return digest return digest
} }
override fun digestString(): String {
return digest().map { it.toString(16) }.joinToString(separator = "")
}
private fun appendToBuffer(array: Array<UByte>, start: Int) { private fun appendToBuffer(array: Array<UByte>, start: Int) {
array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size) array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
bufferCounter += array.size bufferCounter += array.size
} }
} }

View File

@ -14,10 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.sha package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.Hash
import com.ionspin.kotlin.crypto.chunked import com.ionspin.kotlin.crypto.chunked
import com.ionspin.kotlin.crypto.hash.StatelessHash
import com.ionspin.kotlin.crypto.hash.UpdateableHash
import com.ionspin.kotlin.crypto.rotateRight import com.ionspin.kotlin.crypto.rotateRight
/** /**
@ -27,13 +28,18 @@ import com.ionspin.kotlin.crypto.rotateRight
*/ */
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
class Sha512 : Hash { class Sha512 : UpdateableHash {
companion object {
override val MAX_HASH_BYTES: Int = 32
companion object : StatelessHash {
const val BLOCK_SIZE = 1024 const val BLOCK_SIZE = 1024
const val BLOCK_SIZE_IN_BYTES = 128 const val BLOCK_SIZE_IN_BYTES = 128
const val CHUNK_SIZE = 80 const val CHUNK_SIZE = 80
const val ULONG_MASK = 0xFFFFFFFFFFFFFFFFUL const val ULONG_MASK = 0xFFFFFFFFFFFFFFFFUL
override val MAX_HASH_BYTES: Int = 32
val k = arrayOf( val k = arrayOf(
0x428a2f98d728ae22UL, 0x428a2f98d728ae22UL,
0x7137449123ef65cdUL, 0x7137449123ef65cdUL,
@ -129,19 +135,24 @@ class Sha512 : Hash {
) )
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun digest(message: String): Array<UByte> { override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
return digest(message.encodeToByteArray().map { it.toUByte() }.toTypedArray()) return digest(
inputString.encodeToByteArray().map { it.toUByte() }.toTypedArray(),
key?.run { encodeToByteArray().map { it.toUByte() }.toTypedArray() } ?: emptyArray<UByte>(),
hashLength = hashLength
)
} }
fun digest(message: Array<UByte>): Array<UByte> { override fun digest(inputMessage: Array<UByte>, key: Array<UByte>, hashLength: Int): Array<UByte> {
var h = iv.copyOf() var h = iv.copyOf()
val expansionArray = createExpansionArray(message.size) val expansionArray = createExpansionArray(inputMessage.size)
val chunks = val chunks =
(message + expansionArray + (message.size * 8).toULong().toPadded128BitByteArray()).chunked( (inputMessage + expansionArray + (inputMessage.size * 8).toULong().toPadded128BitByteArray()).chunked(
BLOCK_SIZE_IN_BYTES) BLOCK_SIZE_IN_BYTES
)
chunks.forEach { chunk -> chunks.forEach { chunk ->
val w = expandChunk(chunk) val w = expandChunk(chunk)
@ -309,19 +320,19 @@ class Sha512 : Hash {
var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U } var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun update(message: String) { override fun update(data: String) {
return update(message.encodeToByteArray().map { it.toUByte() }.toTypedArray()) return update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
} }
fun update(array: Array<UByte>) { override fun update(data: Array<UByte>) {
if (array.isEmpty()) { if (data.isEmpty()) {
throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating") throw RuntimeException("Updating with empty array is not allowed. If you need empty hash, just call digest without updating")
} }
when { when {
bufferCounter + array.size < BLOCK_SIZE_IN_BYTES -> appendToBuffer(array, bufferCounter) bufferCounter + data.size < BLOCK_SIZE_IN_BYTES -> appendToBuffer(data, bufferCounter)
bufferCounter + array.size >= BLOCK_SIZE_IN_BYTES -> { bufferCounter + data.size >= BLOCK_SIZE_IN_BYTES -> {
val chunked = array.chunked(BLOCK_SIZE_IN_BYTES) val chunked = data.chunked(BLOCK_SIZE_IN_BYTES)
chunked.forEach { chunk -> chunked.forEach { chunk ->
if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) { if (bufferCounter + chunk.size < BLOCK_SIZE_IN_BYTES) {
appendToBuffer(chunk, bufferCounter) appendToBuffer(chunk, bufferCounter)
@ -358,10 +369,11 @@ class Sha512 : Hash {
mix(h, w).copyInto(h) mix(h, w).copyInto(h)
} }
fun digest() : Array<UByte> { override fun digest(): Array<UByte> {
val length = counter + bufferCounter val length = counter + bufferCounter
val expansionArray = createExpansionArray(length) val expansionArray = createExpansionArray(length)
val finalBlock = buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPadded128BitByteArray() val finalBlock =
buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPadded128BitByteArray()
finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach { finalBlock.chunked(BLOCK_SIZE_IN_BYTES).forEach {
consumeBlock(it) consumeBlock(it)
} }
@ -378,6 +390,10 @@ class Sha512 : Hash {
return digest return digest
} }
override fun digestString(): String {
return digest().map { it.toString(16) }.joinToString(separator = "")
}
private fun appendToBuffer(array: Array<UByte>, start: Int) { private fun appendToBuffer(array: Array<UByte>, start: Int) {
array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size) array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size)
bufferCounter += array.size bufferCounter += array.size

View File

@ -16,9 +16,9 @@
package com.ionspin.kotlin.crypto package com.ionspin.kotlin.crypto
import com.ionspin.kotlin.crypto.blake2b.Blake2b import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
import com.ionspin.kotlin.crypto.sha.Sha256 import com.ionspin.kotlin.crypto.hash.sha.Sha256
import com.ionspin.kotlin.crypto.sha.Sha512 import com.ionspin.kotlin.crypto.hash.sha.Sha512
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -74,7 +74,7 @@ class ReadmeTest {
@Test @Test
fun sha256Example() { fun sha256Example() {
val input ="abc" val input ="abc"
val result = Sha256.digest(message = input) val result = Sha256.digest(inputString = input)
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue { assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray()) result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
@ -87,7 +87,7 @@ class ReadmeTest {
@Test @Test
fun sha512Example() { fun sha512Example() {
val input ="abc" val input ="abc"
val result = Sha512.digest(message = input.encodeToByteArray().map { it.toUByte() }.toTypedArray()) val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toTypedArray())
println(result.map {it.toString(16)}) println(result.map {it.toString(16)})
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.blake2b package com.ionspin.kotlin.crypto.hash.blake2b
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue

View File

@ -14,11 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.blake2b package com.ionspin.kotlin.crypto.hash.blake2b
import com.ionspin.kotlin.crypto.util.testBlocking
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.blake2b package com.ionspin.kotlin.crypto.hash.blake2b
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -37,10 +37,9 @@ class Blake2bKnowAnswerTests {
fun knownAnswerTest() { fun knownAnswerTest() {
kat.forEach { kat.forEach {
val parsedInput = it.input.chunked(2).map { it.toUByte(16) }.toTypedArray() val parsedInput = it.input.chunked(2).map { it.toUByte(16) }.toTypedArray()
val chunkedInput = parsedInput.toList().chunked(128).map { it.toTypedArray() }.toTypedArray()
val result = Blake2b.digest( val result = Blake2b.digest(
inputMessage = chunkedInput, inputMessage = parsedInput,
secretKey = it.key.chunked(2).map { it.toUByte(16) }.toTypedArray() key = it.key.chunked(2).map { it.toUByte(16) }.toTypedArray()
) )
assertTrue { assertTrue {
result.contentEquals(it.hash.chunked(2).map { it.toUByte(16) }.toTypedArray()) result.contentEquals(it.hash.chunked(2).map { it.toUByte(16) }.toTypedArray())

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.sha package com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -31,7 +31,7 @@ class Sha256Test {
@Test @Test
fun testWellKnownValue() { fun testWellKnownValue() {
val result = Sha256.digest(message = "abc") val result = Sha256.digest(inputString = "abc")
val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" val expectedResult = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
assertTrue { assertTrue {
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray()) result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
@ -44,7 +44,7 @@ class Sha256Test {
@Test @Test
fun testWellKnownDoubleBlock() { fun testWellKnownDoubleBlock() {
val resultDoubleBlock = Sha256.digest(message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") val resultDoubleBlock = Sha256.digest(inputString = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
assertTrue { assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray()) resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
@ -56,7 +56,7 @@ class Sha256Test {
fun testWellKnown3() { //It's good that I'm consistent with names. fun testWellKnown3() { //It's good that I'm consistent with names.
val resultDoubleBlock = Sha256.digest(message = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") val resultDoubleBlock = Sha256.digest(inputString = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1" val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
assertTrue { assertTrue {
@ -71,7 +71,7 @@ class Sha256Test {
for (i in 0 until 1000000) { for (i in 0 until 1000000) {
inputBuilder.append("a") inputBuilder.append("a")
} }
val resultDoubleBlock = Sha256.digest(message = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toTypedArray()) val resultDoubleBlock = Sha256.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toTypedArray())
val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0" val expectedResultForDoubleBlock = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
assertTrue { assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray()) resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())

View File

@ -14,9 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.sha package com.ionspin.kotlin.crypto.hash.sha
import com.ionspin.kotlin.crypto.chunked
import kotlin.test.Ignore import kotlin.test.Ignore
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -47,7 +46,7 @@ class Sha256UpdateableTest {
@Test @Test
fun testWellKnownDoubleBlock() { fun testWellKnownDoubleBlock() {
val sha256 = Sha256() val sha256 = Sha256()
sha256.update(message = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") sha256.update(data = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
val resultDoubleBlock = sha256.digest() val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" val expectedResultForDoubleBlock = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
@ -60,7 +59,7 @@ class Sha256UpdateableTest {
@Test @Test
fun testWellKnown3() { //It's good that I'm consistent with names. fun testWellKnown3() { //It's good that I'm consistent with names.
val sha256 = Sha256() val sha256 = Sha256()
sha256.update(message = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") sha256.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha256.digest() val resultDoubleBlock = sha256.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1" val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.sha package com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -30,7 +30,7 @@ class Sha512Test {
@Test @Test
fun testWellKnownValue() { fun testWellKnownValue() {
val result = Sha512.digest(message = "abc".encodeToByteArray().map { it.toUByte() }.toTypedArray()) val result = Sha512.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toTypedArray())
println(result.map {it.toString(16)}) println(result.map {it.toString(16)})
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
@ -46,7 +46,7 @@ class Sha512Test {
@Test @Test
fun testWellKnown3() { fun testWellKnown3() {
val sha512 = Sha512() val sha512 = Sha512()
sha512.update(message = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest() val resultDoubleBlock = sha512.digest()
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909" "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
@ -62,7 +62,7 @@ class Sha512Test {
for (i in 0 until 1000000) { for (i in 0 until 1000000) {
inputBuilder.append("a") inputBuilder.append("a")
} }
val resultDoubleBlock = Sha512.digest(message = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toTypedArray()) val resultDoubleBlock = Sha512.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toTypedArray())
val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b" val expectedResultForDoubleBlock = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
assertTrue { assertTrue {
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray()) resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.ionspin.kotlin.crypto.sha package com.ionspin.kotlin.crypto.hash.sha
import kotlin.test.Ignore import kotlin.test.Ignore
import kotlin.test.Test import kotlin.test.Test
@ -45,7 +45,7 @@ class Sha512UpdateableTest {
@Test @Test
fun testWellKnownDoubleBlock() { fun testWellKnownDoubleBlock() {
val sha512 = Sha512() val sha512 = Sha512()
sha512.update(message = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") sha512.update(data = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
val resultDoubleBlock = sha512.digest() val resultDoubleBlock = sha512.digest()
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = "")) println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" + val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +