Moved util class to util package, added a couple of util tests, continued Argon implementation by completeing compression function
This commit is contained in:
parent
d22f5b73f7
commit
7e8e48aa1d
@ -21,6 +21,8 @@ import com.ionspin.kotlin.bignum.integer.toBigInteger
|
|||||||
import com.ionspin.kotlin.crypto.*
|
import com.ionspin.kotlin.crypto.*
|
||||||
import com.ionspin.kotlin.crypto.hash.StatelessHash
|
import com.ionspin.kotlin.crypto.hash.StatelessHash
|
||||||
import com.ionspin.kotlin.crypto.hash.UpdatableHash
|
import com.ionspin.kotlin.crypto.hash.UpdatableHash
|
||||||
|
import com.ionspin.kotlin.crypto.util.chunked
|
||||||
|
import com.ionspin.kotlin.crypto.util.rotateRight
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto.hash.sha
|
package com.ionspin.kotlin.crypto.hash.sha
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.chunked
|
import com.ionspin.kotlin.crypto.util.chunked
|
||||||
import com.ionspin.kotlin.crypto.hash.StatelessHash
|
import com.ionspin.kotlin.crypto.hash.StatelessHash
|
||||||
import com.ionspin.kotlin.crypto.hash.UpdatableHash
|
import com.ionspin.kotlin.crypto.hash.UpdatableHash
|
||||||
import com.ionspin.kotlin.crypto.rotateRight
|
import com.ionspin.kotlin.crypto.util.rotateRight
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto.hash.sha
|
package com.ionspin.kotlin.crypto.hash.sha
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.chunked
|
import com.ionspin.kotlin.crypto.util.chunked
|
||||||
import com.ionspin.kotlin.crypto.hash.StatelessHash
|
import com.ionspin.kotlin.crypto.hash.StatelessHash
|
||||||
import com.ionspin.kotlin.crypto.hash.UpdatableHash
|
import com.ionspin.kotlin.crypto.hash.UpdatableHash
|
||||||
import com.ionspin.kotlin.crypto.rotateRight
|
import com.ionspin.kotlin.crypto.util.rotateRight
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
|
@ -17,8 +17,7 @@
|
|||||||
package com.ionspin.kotlin.crypto.keyderivation
|
package com.ionspin.kotlin.crypto.keyderivation
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
|
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2b
|
||||||
import com.ionspin.kotlin.crypto.plus
|
import com.ionspin.kotlin.crypto.util.*
|
||||||
import com.ionspin.kotlin.crypto.toLittleEndianUByteArray
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03
|
* https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03
|
||||||
@ -42,13 +41,14 @@ class Argon2 internal constructor(
|
|||||||
val numberOfIterations: UInt,
|
val numberOfIterations: UInt,
|
||||||
val versionNumber: UInt,
|
val versionNumber: UInt,
|
||||||
val key: Array<UByte>,
|
val key: Array<UByte>,
|
||||||
associatedData: Array<UByte>
|
val associatedData: Array<UByte>,
|
||||||
val type: ArgonType
|
val type: ArgonType
|
||||||
) {
|
) {
|
||||||
enum class ArgonType {
|
enum class ArgonType {
|
||||||
Argon2i, Argon2d, Argon2id
|
Argon2i, Argon2d, Argon2id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalStdlibApi
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
|
||||||
@ -70,47 +70,88 @@ class Argon2 internal constructor(
|
|||||||
.plus(listOf(vLast))
|
.plus(listOf(vLast))
|
||||||
.foldRight(emptyArray<UByte>()) { arrayOfUBytes, acc -> arrayOfUBytes + acc }
|
.foldRight(emptyArray<UByte>()) { arrayOfUBytes, acc -> arrayOfUBytes + acc }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return concat
|
return concat
|
||||||
}
|
}
|
||||||
|
|
||||||
fun compressionFunctionG(x : Array<UByte>, y : Array<UByte>) : Array<Array<Array<UByte>>> {
|
fun compressionFunctionG(x: Array<UByte>, y: Array<UByte>): Array<UByte> {
|
||||||
val r = Array<UByte>(1024) { 0U }
|
val r = Array<UByte>(1024) { 0U } // view as 8x8 matrix of 16 byte registers
|
||||||
x.forEachIndexed { index, it -> r[index] = it xor y[index] }
|
x.forEachIndexed { index, it -> r[index] = it xor y[index] }
|
||||||
// mix rounds
|
val q = Array<UByte>(1024) { 0U }
|
||||||
return emptyArray() // TODO
|
val z = Array<UByte>(1024) { 0U }
|
||||||
|
// Do the argon/blake2b mixing on rows
|
||||||
|
for (i in 0..7) {
|
||||||
|
val startOfRow = (i * 8 * 16)
|
||||||
|
val endOfRow = startOfRow + (8 * 16)
|
||||||
|
mixRound(r.copyOfRange(startOfRow, endOfRow))
|
||||||
|
.map { it.toLittleEndianUByteArray() }
|
||||||
|
.flatMap { it.asIterable() }
|
||||||
|
.toTypedArray()
|
||||||
|
.copyInto(q, startOfRow, endOfRow)
|
||||||
|
}
|
||||||
|
// Do the argon/blake2b mixing on columns
|
||||||
|
for (i in 0..7) {
|
||||||
|
copyIntoGBlockColumn(
|
||||||
|
z,
|
||||||
|
i,
|
||||||
|
mixRound(extractColumnFromGBlock(q, i))
|
||||||
|
.map { it.toLittleEndianUByteArray() }
|
||||||
|
.flatMap { it.asIterable() }
|
||||||
|
.toTypedArray()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Z = Z xor R
|
||||||
|
r.forEachIndexed { index, it -> z[index] = it xor z[index] }
|
||||||
|
return z
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------- Unmodified blake2b mixing
|
private fun extractColumnFromGBlock(gBlock: Array<UByte>, columnPosition: Int): Array<UByte> {
|
||||||
/*
|
val result = Array<UByte>(128) { 0U }
|
||||||
internal fun mixRound(input: Array<ULong>, message: Array<ULong>, round: Int): Array<ULong> {
|
for (i in 0..7) {
|
||||||
var v = input
|
result[i] = gBlock[i * 8 + columnPosition]
|
||||||
val selectedSigma = sigma[round % 10]
|
}
|
||||||
v = mix(v, 0, 4, 8, 12, message[selectedSigma[0]], message[selectedSigma[1]])
|
return result
|
||||||
v = mix(v, 1, 5, 9, 13, message[selectedSigma[2]], message[selectedSigma[3]])
|
}
|
||||||
v = mix(v, 2, 6, 10, 14, message[selectedSigma[4]], message[selectedSigma[5]])
|
|
||||||
v = mix(v, 3, 7, 11, 15, message[selectedSigma[6]], message[selectedSigma[7]])
|
private fun copyIntoGBlockColumn(gBlock: Array<UByte>, columnPosition: Int, columnData: Array<UByte>) {
|
||||||
v = mix(v, 0, 5, 10, 15, message[selectedSigma[8]], message[selectedSigma[9]])
|
for (i in 0..7) {
|
||||||
v = mix(v, 1, 6, 11, 12, message[selectedSigma[10]], message[selectedSigma[11]])
|
gBlock[i * 8 + columnPosition] = columnData[i]
|
||||||
v = mix(v, 2, 7, 8, 13, message[selectedSigma[12]], message[selectedSigma[13]])
|
}
|
||||||
v = mix(v, 3, 4, 9, 14, message[selectedSigma[14]], message[selectedSigma[15]])
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//based on Blake2b mixRound
|
||||||
|
internal fun mixRound(input: Array<UByte>): Array<ULong> {
|
||||||
|
var v = input.chunked(4).map { it.fromLittleEndianArrayToULong() }.toTypedArray()
|
||||||
|
v = mix(v, 0, 4, 8, 12)
|
||||||
|
v = mix(v, 1, 5, 9, 13)
|
||||||
|
v = mix(v, 2, 6, 10, 14)
|
||||||
|
v = mix(v, 3, 7, 11, 15)
|
||||||
|
v = mix(v, 0, 5, 10, 15)
|
||||||
|
v = mix(v, 1, 6, 11, 12)
|
||||||
|
v = mix(v, 2, 7, 8, 13)
|
||||||
|
v = mix(v, 3, 4, 9, 14)
|
||||||
return v
|
return v
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mix(v: Array<ULong>, a: Int, b: Int, c: Int, d: Int, x: ULong, y: ULong): Array<ULong> {
|
const val R1 = 32
|
||||||
v[a] = (v[a] + v[b] + x)
|
const val R2 = 24
|
||||||
|
const val R3 = 16
|
||||||
|
const val R4 = 63
|
||||||
|
|
||||||
|
//Based on Blake2b mix
|
||||||
|
private fun mix(v: Array<ULong>, a: Int, b: Int, c: Int, d: Int): Array<ULong> {
|
||||||
|
v[a] = (v[a] + v[b] * 2U * a.toUInt() * b.toUInt())
|
||||||
v[d] = (v[d] xor v[a]) rotateRight R1
|
v[d] = (v[d] xor v[a]) rotateRight R1
|
||||||
v[c] = (v[c] + v[d])
|
v[c] = (v[c] + v[d] * 2U * c.toUInt() * d.toUInt())
|
||||||
v[b] = (v[b] xor v[c]) rotateRight R2
|
v[b] = (v[b] xor v[c]) rotateRight R2
|
||||||
v[a] = (v[a] + v[b] + y)
|
v[a] = (v[a] + v[b] * 2U * a.toUInt() * b.toUInt())
|
||||||
v[d] = (v[d] xor v[a]) rotateRight R3
|
v[d] = (v[d] xor v[a]) rotateRight R3
|
||||||
v[c] = (v[c] + v[d])
|
v[c] = (v[c] + v[d] * 2U * c.toUInt() * d.toUInt())
|
||||||
v[b] = (v[b] xor v[c]) rotateRight R4
|
v[b] = (v[b] xor v[c]) rotateRight R4
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
internal fun derive(
|
internal fun derive(
|
||||||
password: Array<UByte>,
|
password: Array<UByte>,
|
||||||
@ -155,9 +196,26 @@ class Argon2 internal constructor(
|
|||||||
argonHash(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray(), 64U)
|
argonHash(h0 + 1.toUInt().toLittleEndianUByteArray() + i.toUInt().toLittleEndianUByteArray(), 64U)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i in 0..parallelism.toInt()) {
|
||||||
|
for (j in 1..columnCount.toInt()) {
|
||||||
|
//TODO i,j choosing based on type
|
||||||
|
val iPrim = -1
|
||||||
|
val jPrim = -1
|
||||||
|
matrix[i][j] = compressionFunctionG(matrix[i][j - 1], matrix[iPrim][jPrim])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = matrix.foldIndexed(emptyArray<UByte>()) { index, acc, arrayOfArrays ->
|
||||||
|
return if (acc.size == 0) {
|
||||||
|
acc + arrayOfArrays[columnCount.toInt() - 1]
|
||||||
|
} else {
|
||||||
|
acc.mapIndexed { index, it -> it xor arrayOfArrays[columnCount.toInt() - 1][index] }.toTypedArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return emptyArray()
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
package com.ionspin.kotlin.crypto.symmetric
|
package com.ionspin.kotlin.crypto.symmetric
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.SRNG
|
import com.ionspin.kotlin.crypto.SRNG
|
||||||
import com.ionspin.kotlin.crypto.chunked
|
import com.ionspin.kotlin.crypto.util.chunked
|
||||||
import com.ionspin.kotlin.crypto.xor
|
import com.ionspin.kotlin.crypto.util.xor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advanced encryption standard with cipher block chaining and PKCS #5
|
* Advanced encryption standard with cipher block chaining and PKCS #5
|
||||||
|
@ -20,9 +20,9 @@ import com.ionspin.kotlin.bignum.Endianness
|
|||||||
import com.ionspin.kotlin.bignum.integer.BigInteger
|
import com.ionspin.kotlin.bignum.integer.BigInteger
|
||||||
import com.ionspin.kotlin.bignum.modular.ModularBigInteger
|
import com.ionspin.kotlin.bignum.modular.ModularBigInteger
|
||||||
import com.ionspin.kotlin.crypto.SRNG
|
import com.ionspin.kotlin.crypto.SRNG
|
||||||
import com.ionspin.kotlin.crypto.chunked
|
import com.ionspin.kotlin.crypto.util.chunked
|
||||||
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
|
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
|
||||||
import com.ionspin.kotlin.crypto.xor
|
import com.ionspin.kotlin.crypto.util.xor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
package com.ionspin.kotlin.crypto.util
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -103,6 +103,43 @@ fun UInt.toLittleEndianUByteArray() : Array<UByte> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UInt / Array utils
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun ULong.toBigEndianUByteArray() : Array<UByte> {
|
||||||
|
return Array<UByte> (8) {
|
||||||
|
((this shr (56 - (it * 8))) and 0xFFU).toUByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun ULong.toLittleEndianUByteArray() : Array<UByte> {
|
||||||
|
return Array<UByte> (8) {
|
||||||
|
((this shr (it * 8)) and 0xFFU).toUByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun Array<UByte>.fromLittleEndianArrayToULong() : ULong {
|
||||||
|
if (this.size > 8) {
|
||||||
|
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
||||||
|
}
|
||||||
|
var ulong = this.foldIndexed(0UL) { index, acc, uByte -> acc or (uByte.toULong() shl (index * 8))}
|
||||||
|
return ulong
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun Array<UByte>.fromBigEndianArrayToULong() : ULong {
|
||||||
|
if (this.size > 8) {
|
||||||
|
throw RuntimeException("ore than 8 bytes in input, potential overflow")
|
||||||
|
}
|
||||||
|
var ulong = this.foldIndexed(0UL) {
|
||||||
|
index, acc, uByte ->
|
||||||
|
val res = acc or (uByte.toULong() shl (56 - (index * 8)))
|
||||||
|
res
|
||||||
|
|
||||||
|
}
|
||||||
|
return ulong
|
||||||
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
operator fun UInt.plus(other : Array<UByte>) : Array<UByte> {
|
operator fun UInt.plus(other : Array<UByte>) : Array<UByte> {
|
||||||
return this.toLittleEndianUByteArray() + other
|
return this.toLittleEndianUByteArray() + other
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 Ugljesa Jovanovic
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.chunked
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Ugljesa Jovanovic
|
|
||||||
* ugljesa.jovanovic@ionspin.com
|
|
||||||
* on 17-Jul-2019
|
|
||||||
*/
|
|
||||||
class UtilTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSlicer() {
|
|
||||||
val array = arrayOf(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17)
|
|
||||||
val chunked = array.chunked(2)
|
|
||||||
assertTrue {
|
|
||||||
chunked.size == 9 && chunked[8][0] == 17
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto.symmetric
|
package com.ionspin.kotlin.crypto.symmetric
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.hexStringToUByteArray
|
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto.symmetric
|
package com.ionspin.kotlin.crypto.symmetric
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.hexStringToUByteArray
|
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 Ugljesa Jovanovic
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.ionspin.kotlin.crypto.util
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ugljesa Jovanovic
|
||||||
|
* ugljesa.jovanovic@ionspin.com
|
||||||
|
* on 17-Jul-2019
|
||||||
|
*/
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
class UtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSlicer() {
|
||||||
|
val array = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)
|
||||||
|
val chunked = array.chunked(2)
|
||||||
|
assertTrue {
|
||||||
|
chunked.size == 9 && chunked[8][0] == 17
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUIntToBigEndianArray() {
|
||||||
|
assertTrue {
|
||||||
|
val original = 1U
|
||||||
|
val converted = original.toBigEndianUByteArray()
|
||||||
|
converted[0] = 1U
|
||||||
|
true
|
||||||
|
}
|
||||||
|
assertTrue {
|
||||||
|
val original = 0xAABBCCDDU
|
||||||
|
val converted = original.toBigEndianUByteArray()
|
||||||
|
converted[0] == 0xAAU.toUByte() &&
|
||||||
|
converted[1] == 0xBBU.toUByte() &&
|
||||||
|
converted[2] == 0xCCU.toUByte() &&
|
||||||
|
converted[3] == 0xDDU.toUByte()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUIntToLittleEndianArray() {
|
||||||
|
assertTrue {
|
||||||
|
val original = 1U
|
||||||
|
val converted = original.toBigEndianUByteArray()
|
||||||
|
converted[4] = 1U
|
||||||
|
true
|
||||||
|
}
|
||||||
|
assertTrue {
|
||||||
|
val original = 0xAABBCCDDU
|
||||||
|
val converted = original.toBigEndianUByteArray()
|
||||||
|
converted[0] == 0xDDU.toUByte() &&
|
||||||
|
converted[1] == 0xCCU.toUByte() &&
|
||||||
|
converted[2] == 0xBBU.toUByte() &&
|
||||||
|
converted[3] == 0xAAU.toUByte()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFromBigEndianByteArrayToLong() {
|
||||||
|
|
||||||
|
assertTrue {
|
||||||
|
val ubyteArray = ubyteArrayOf(0xA1U, 0xA2U, 0xB1U, 0xB2U, 0xC1U, 0xC2U, 0xD1U, 0xD2U).toTypedArray()
|
||||||
|
val expected = 0xA1A2B1B2C1C2D1D2U
|
||||||
|
val reconstructed = ubyteArray.fromBigEndianArrayToULong();
|
||||||
|
reconstructed == expected
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFromLittleEndianByteArrayToLong() {
|
||||||
|
|
||||||
|
assertTrue {
|
||||||
|
val ubyteArray = ubyteArrayOf(0xA1U, 0xA2U, 0xB1U, 0xB2U, 0xC1U, 0xC2U, 0xD1U, 0xD2U).toTypedArray()
|
||||||
|
val expected = 0xD2D1C2C1B2B1A2A1UL
|
||||||
|
val reconstructed = ubyteArray.fromLittleEndianArrayToULong();
|
||||||
|
reconstructed == expected
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user