Migrate everything to UByteArray
This commit is contained in:
parent
4ea04eb90d
commit
34a86cd9c7
@ -28,23 +28,23 @@ interface Hash {
|
|||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
interface UpdatableHash : Hash {
|
interface UpdatableHash : Hash {
|
||||||
fun update(data : Array<UByte>)
|
fun update(data : UByteArray)
|
||||||
|
|
||||||
fun update(data : String)
|
fun update(data : String)
|
||||||
|
|
||||||
fun digest() : Array<UByte>
|
fun digest() : UByteArray
|
||||||
|
|
||||||
fun digestString() : String
|
fun digestString() : String
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
interface StatelessHash : Hash {
|
interface StatelessHash : Hash {
|
||||||
fun digest(inputString: String, key: String? = null, hashLength: Int = MAX_HASH_BYTES): Array<UByte>
|
fun digest(inputString: String, key: String? = null, hashLength: Int = MAX_HASH_BYTES): UByteArray
|
||||||
|
|
||||||
fun digest(
|
fun digest(
|
||||||
inputMessage: Array<UByte> = emptyArray(),
|
inputMessage: UByteArray = ubyteArrayOf(),
|
||||||
key: Array<UByte> = emptyArray(),
|
key: UByteArray = ubyteArrayOf(),
|
||||||
hashLength: Int = MAX_HASH_BYTES
|
hashLength: Int = MAX_HASH_BYTES
|
||||||
): Array<UByte>
|
): UByteArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,10 +31,14 @@ import com.ionspin.kotlin.crypto.util.rotateRight
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : UpdatableHash {
|
class Blake2b(val key: UByteArray? = null, val hashLength: Int = 64) : UpdatableHash {
|
||||||
|
|
||||||
companion object : StatelessHash {
|
companion object : StatelessHash {
|
||||||
|
//Hack start
|
||||||
|
//If this line is not included konanc 1.4-M1 fails to link because it cant find ByteArray which is
|
||||||
|
//a backing class for UByteArray
|
||||||
|
val byteArray: ByteArray = byteArrayOf(0, 1)
|
||||||
|
//Hack end
|
||||||
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
|
||||||
@ -103,7 +107,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
|
|
||||||
fun compress(
|
fun compress(
|
||||||
h: Array<ULong>,
|
h: Array<ULong>,
|
||||||
input: Array<UByte>,
|
input: UByteArray,
|
||||||
offsetCounter: BigInteger,
|
offsetCounter: BigInteger,
|
||||||
finalBlock: Boolean
|
finalBlock: Boolean
|
||||||
): Array<ULong> {
|
): Array<ULong> {
|
||||||
@ -145,24 +149,24 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
|
override fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
|
||||||
val array = inputString.encodeToByteArray().map { it.toUByte() }.toList().toTypedArray()
|
val array = inputString.encodeToByteArray().toUByteArray()
|
||||||
val keyBytes = key?.run {
|
val keyBytes = key?.run {
|
||||||
encodeToByteArray().map { it.toUByte() }.toTypedArray()
|
encodeToByteArray().toUByteArray()
|
||||||
} ?: emptyArray()
|
} ?: ubyteArrayOf()
|
||||||
return digest(inputMessage = array, key = keyBytes, hashLength = hashLength)
|
return digest(inputMessage = array, key = keyBytes, hashLength = hashLength)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(
|
override fun digest(
|
||||||
inputMessage: Array<UByte>,
|
inputMessage: UByteArray,
|
||||||
key: Array<UByte>,
|
key: UByteArray,
|
||||||
hashLength: Int
|
hashLength: Int
|
||||||
): Array<UByte> {
|
): UByteArray {
|
||||||
if (hashLength > MAX_HASH_BYTES) {
|
if (hashLength > MAX_HASH_BYTES) {
|
||||||
throw RuntimeException("Invalid hash length. Requested length more than maximum length. Requested length $hashLength")
|
throw RuntimeException("Invalid hash length. Requested length more than maximum length. Requested length $hashLength")
|
||||||
}
|
}
|
||||||
val chunkedMessage = inputMessage.chunked(BLOCK_BYTES)
|
val chunkedMessage = inputMessage.chunked(BLOCK_BYTES).map { it.toUByteArray() }.toTypedArray()
|
||||||
|
|
||||||
val h = iv.copyOf()
|
val h = iv.copyOf()
|
||||||
|
|
||||||
@ -172,7 +176,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
val message = if (key.isEmpty()) {
|
val message = if (key.isEmpty()) {
|
||||||
if (chunkedMessage.isEmpty()) {
|
if (chunkedMessage.isEmpty()) {
|
||||||
Array(1) {
|
Array(1) {
|
||||||
Array<UByte>(128) {
|
UByteArray(128) {
|
||||||
0U
|
0U
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +203,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
val lastBlockPadded = if (message.isNotEmpty()) {
|
val lastBlockPadded = if (message.isNotEmpty()) {
|
||||||
padToBlock(message[message.size - 1])
|
padToBlock(message[message.size - 1])
|
||||||
} else {
|
} else {
|
||||||
Array<UByte>(16) { 0U }
|
UByteArray(16) { 0U }
|
||||||
}
|
}
|
||||||
|
|
||||||
compress(h, lastBlockPadded, lastSize.toBigInteger(), true).copyInto(h)
|
compress(h, lastBlockPadded, lastSize.toBigInteger(), true).copyInto(h)
|
||||||
@ -208,7 +212,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
return formatResult(h).copyOfRange(0, hashLength)
|
return formatResult(h).copyOfRange(0, hashLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatResult(h: Array<ULong>): Array<UByte> {
|
private fun formatResult(h: Array<ULong>): UByteArray {
|
||||||
return h.map {
|
return h.map {
|
||||||
arrayOf(
|
arrayOf(
|
||||||
(it and 0xFFUL).toUByte(),
|
(it and 0xFFUL).toUByte(),
|
||||||
@ -222,10 +226,10 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
)
|
)
|
||||||
}.flatMap {
|
}.flatMap {
|
||||||
it.toList()
|
it.toList()
|
||||||
}.toTypedArray()
|
}.toUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun padToBlock(unpadded: Array<UByte>): Array<UByte> {
|
private fun padToBlock(unpadded: UByteArray): UByteArray {
|
||||||
if (unpadded.size == BLOCK_BYTES) {
|
if (unpadded.size == BLOCK_BYTES) {
|
||||||
return unpadded
|
return unpadded
|
||||||
}
|
}
|
||||||
@ -234,7 +238,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
throw IllegalStateException("Block larger than 128 bytes")
|
throw IllegalStateException("Block larger than 128 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array(BLOCK_BYTES) {
|
return UByteArray(BLOCK_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in 0 until unpadded.size -> unpadded[it]
|
in 0 until unpadded.size -> unpadded[it]
|
||||||
else -> 0U
|
else -> 0U
|
||||||
@ -248,7 +252,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
key: String?,
|
key: String?,
|
||||||
requestedHashLenght: Int = 64
|
requestedHashLenght: Int = 64
|
||||||
) : this(
|
) : this(
|
||||||
(key?.encodeToByteArray()?.map { it.toUByte() }?.toTypedArray() ?: emptyArray<UByte>()),
|
(key?.encodeToByteArray()?.toUByteArray() ?: ubyteArrayOf()),
|
||||||
requestedHashLenght
|
requestedHashLenght
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -257,7 +261,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
var h = iv.copyOf()
|
var h = iv.copyOf()
|
||||||
var counter = BigInteger.ZERO
|
var counter = BigInteger.ZERO
|
||||||
var bufferCounter = 0
|
var bufferCounter = 0
|
||||||
var buffer = Array<UByte>(BLOCK_BYTES) { 0U }
|
var buffer = UByteArray(BLOCK_BYTES) { 0U }
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -268,7 +272,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(data: Array<UByte>) {
|
override fun update(data: UByteArray) {
|
||||||
if (data.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")
|
||||||
}
|
}
|
||||||
@ -276,7 +280,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
when {
|
when {
|
||||||
bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
|
bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
|
||||||
bufferCounter + data.size >= BLOCK_BYTES -> {
|
bufferCounter + data.size >= BLOCK_BYTES -> {
|
||||||
val chunked = data.chunked(BLOCK_BYTES)
|
val chunked = data.chunked(BLOCK_BYTES).map { it.toUByteArray() }
|
||||||
chunked.forEach { chunk ->
|
chunked.forEach { chunk ->
|
||||||
if (bufferCounter + chunk.size < BLOCK_BYTES) {
|
if (bufferCounter + chunk.size < BLOCK_BYTES) {
|
||||||
appendToBuffer(chunk, bufferCounter)
|
appendToBuffer(chunk, bufferCounter)
|
||||||
@ -289,7 +293,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
)
|
)
|
||||||
counter += BLOCK_BYTES
|
counter += BLOCK_BYTES
|
||||||
consumeBlock(buffer)
|
consumeBlock(buffer)
|
||||||
buffer = Array<UByte>(BLOCK_BYTES) {
|
buffer = UByteArray(BLOCK_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
|
in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
|
||||||
chunk[it + (BLOCK_BYTES - bufferCounter)]
|
chunk[it + (BLOCK_BYTES - bufferCounter)]
|
||||||
@ -310,19 +314,19 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
}
|
}
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
override fun update(data: String) {
|
override fun update(data: String) {
|
||||||
update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
update(data.encodeToByteArray().toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appendToBuffer(array: Array<UByte>, start: Int) {
|
private fun appendToBuffer(array: UByteArray, 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
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeBlock(block: Array<UByte>) {
|
private fun consumeBlock(block: UByteArray) {
|
||||||
h = compress(h, block, counter, false)
|
h = compress(h, block, counter, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(): Array<UByte> {
|
override fun digest(): UByteArray {
|
||||||
val lastBlockPadded = padToBlock(buffer)
|
val lastBlockPadded = padToBlock(buffer)
|
||||||
counter += bufferCounter
|
counter += bufferCounter
|
||||||
compress(h, lastBlockPadded, counter, true)
|
compress(h, lastBlockPadded, counter, true)
|
||||||
@ -341,7 +345,7 @@ class Blake2b(val key: Array<UByte>? = null, val hashLength: Int = 64) : Updatab
|
|||||||
h = iv.copyOf()
|
h = iv.copyOf()
|
||||||
counter = BigInteger.ZERO
|
counter = BigInteger.ZERO
|
||||||
bufferCounter = 0
|
bufferCounter = 0
|
||||||
buffer = Array<UByte>(BLOCK_BYTES) { 0U }
|
buffer = UByteArray(BLOCK_BYTES) { 0U }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,14 +67,14 @@ class Sha256 : UpdatableHash {
|
|||||||
)
|
)
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
|
override fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
|
||||||
return digest(
|
return digest(
|
||||||
inputString.encodeToByteArray().map { it.toUByte() }.toTypedArray(),
|
inputString.encodeToByteArray().toUByteArray(),
|
||||||
key?.run { encodeToByteArray().map { it.toUByte() }.toTypedArray() } ?: emptyArray<UByte>(),
|
key?.run { encodeToByteArray().toUByteArray()} ?: ubyteArrayOf(),
|
||||||
hashLength)
|
hashLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(inputMessage: Array<UByte>, key: Array<UByte>, hashLength: Int): Array<UByte> {
|
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
||||||
|
|
||||||
var h = iv.copyOf()
|
var h = iv.copyOf()
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ class Sha256 : UpdatableHash {
|
|||||||
.chunked(BLOCK_SIZE_IN_BYTES)
|
.chunked(BLOCK_SIZE_IN_BYTES)
|
||||||
|
|
||||||
chunks.forEach { chunk ->
|
chunks.forEach { chunk ->
|
||||||
val w = expandChunk(chunk)
|
val w = expandChunk(chunk.toUByteArray())
|
||||||
mix(h, w).copyInto(h)
|
mix(h, w).copyInto(h)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ class Sha256 : UpdatableHash {
|
|||||||
return (((x and y) xor (x and z) xor (y and z)))
|
return (((x and y) xor (x and z) xor (y and z)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun expandChunk(chunk: Array<UByte>): Array<UInt> {
|
private fun expandChunk(chunk: UByteArray): Array<UInt> {
|
||||||
val w = Array<UInt>(BLOCK_SIZE_IN_BYTES) {
|
val w = Array<UInt>(BLOCK_SIZE_IN_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in 0 until 16 -> {
|
in 0 until 16 -> {
|
||||||
@ -188,7 +188,7 @@ class Sha256 : UpdatableHash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun createExpansionArray(originalSizeInBytes: Int): Array<UByte> {
|
fun createExpansionArray(originalSizeInBytes: Int): UByteArray {
|
||||||
val originalMessageSizeInBits = originalSizeInBytes * 8
|
val originalMessageSizeInBits = originalSizeInBytes * 8
|
||||||
|
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ class Sha256 : UpdatableHash {
|
|||||||
0 -> 0
|
0 -> 0
|
||||||
else -> (BLOCK_SIZE - expandedRemainderOf512) / 8
|
else -> (BLOCK_SIZE - expandedRemainderOf512) / 8
|
||||||
}
|
}
|
||||||
val expansionArray = Array<UByte>(zeroAddAmount + 1) {
|
val expansionArray = UByteArray(zeroAddAmount + 1) {
|
||||||
when (it) {
|
when (it) {
|
||||||
0 -> 0b10000000U
|
0 -> 0b10000000U
|
||||||
else -> 0U
|
else -> 0U
|
||||||
@ -207,9 +207,9 @@ class Sha256 : UpdatableHash {
|
|||||||
return expansionArray
|
return expansionArray
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ULong.toPaddedByteArray(): Array<UByte> {
|
private fun ULong.toPaddedByteArray(): UByteArray {
|
||||||
val byteMask = BYTE_MASK_FROM_ULONG
|
val byteMask = BYTE_MASK_FROM_ULONG
|
||||||
return Array(8) {
|
return UByteArray(8) {
|
||||||
when (it) {
|
when (it) {
|
||||||
7 -> (this and byteMask).toUByte()
|
7 -> (this and byteMask).toUByte()
|
||||||
6 -> ((this shr 8) and byteMask).toUByte()
|
6 -> ((this shr 8) and byteMask).toUByte()
|
||||||
@ -224,9 +224,9 @@ class Sha256 : UpdatableHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun UInt.toPaddedByteArray(): Array<UByte> {
|
private fun UInt.toPaddedByteArray(): UByteArray {
|
||||||
val byteMask = BYTE_MASK_FROM_UINT
|
val byteMask = BYTE_MASK_FROM_UINT
|
||||||
return Array(4) {
|
return UByteArray(4) {
|
||||||
when (it) {
|
when (it) {
|
||||||
3 -> (this and byteMask).toUByte()
|
3 -> (this and byteMask).toUByte()
|
||||||
2 -> ((this shr 8) and byteMask).toUByte()
|
2 -> ((this shr 8) and byteMask).toUByte()
|
||||||
@ -242,14 +242,14 @@ class Sha256 : UpdatableHash {
|
|||||||
var h = iv.copyOf()
|
var h = iv.copyOf()
|
||||||
var counter = 0
|
var counter = 0
|
||||||
var bufferCounter = 0
|
var bufferCounter = 0
|
||||||
var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
|
var buffer = UByteArray(BLOCK_SIZE_IN_BYTES) { 0U }
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
override fun update(data: String) {
|
override fun update(data: String) {
|
||||||
return update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
return update(data.encodeToByteArray().toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(data: Array<UByte>) {
|
override fun update(data: UByteArray) {
|
||||||
if (data.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")
|
||||||
}
|
}
|
||||||
@ -260,9 +260,9 @@ class Sha256 : UpdatableHash {
|
|||||||
val chunked = data.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.toUByteArray(), bufferCounter)
|
||||||
} else {
|
} else {
|
||||||
chunk.copyInto(
|
chunk.toUByteArray().copyInto(
|
||||||
destination = buffer,
|
destination = buffer,
|
||||||
destinationOffset = bufferCounter,
|
destinationOffset = bufferCounter,
|
||||||
startIndex = 0,
|
startIndex = 0,
|
||||||
@ -270,7 +270,7 @@ class Sha256 : UpdatableHash {
|
|||||||
)
|
)
|
||||||
counter += BLOCK_SIZE_IN_BYTES
|
counter += BLOCK_SIZE_IN_BYTES
|
||||||
consumeBlock(buffer)
|
consumeBlock(buffer)
|
||||||
buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) {
|
buffer = UByteArray(BLOCK_SIZE_IN_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
|
in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
|
||||||
chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
|
chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
|
||||||
@ -289,18 +289,18 @@ class Sha256 : UpdatableHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeBlock(block: Array<UByte>) {
|
private fun consumeBlock(block: UByteArray) {
|
||||||
val w = expandChunk(block)
|
val w = expandChunk(block)
|
||||||
mix(h, w).copyInto(h)
|
mix(h, w).copyInto(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(): Array<UByte> {
|
override fun digest(): UByteArray {
|
||||||
val length = counter + bufferCounter
|
val length = counter + bufferCounter
|
||||||
val expansionArray = createExpansionArray(length)
|
val expansionArray = createExpansionArray(length)
|
||||||
val finalBlock =
|
val finalBlock =
|
||||||
buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPaddedByteArray()
|
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.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -319,7 +319,7 @@ class Sha256 : UpdatableHash {
|
|||||||
return digest().map { it.toString(16) }.joinToString(separator = "")
|
return digest().map { it.toString(16) }.joinToString(separator = "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appendToBuffer(array: Array<UByte>, start: Int) {
|
private fun appendToBuffer(array: UByteArray, 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
|
||||||
}
|
}
|
||||||
|
@ -135,15 +135,15 @@ class Sha512 : UpdatableHash {
|
|||||||
)
|
)
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
override fun digest(inputString: String, key: String?, hashLength: Int): Array<UByte> {
|
override fun digest(inputString: String, key: String?, hashLength: Int): UByteArray {
|
||||||
return digest(
|
return digest(
|
||||||
inputString.encodeToByteArray().map { it.toUByte() }.toTypedArray(),
|
inputString.encodeToByteArray().toUByteArray(),
|
||||||
key?.run { encodeToByteArray().map { it.toUByte() }.toTypedArray() } ?: emptyArray<UByte>(),
|
key?.run { encodeToByteArray().toUByteArray() } ?: ubyteArrayOf(),
|
||||||
hashLength = hashLength
|
hashLength = hashLength
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(inputMessage: Array<UByte>, key: Array<UByte>, hashLength: Int): Array<UByte> {
|
override fun digest(inputMessage: UByteArray, key: UByteArray, hashLength: Int): UByteArray {
|
||||||
|
|
||||||
var h = iv.copyOf()
|
var h = iv.copyOf()
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ class Sha512 : UpdatableHash {
|
|||||||
)
|
)
|
||||||
|
|
||||||
chunks.forEach { chunk ->
|
chunks.forEach { chunk ->
|
||||||
val w = expandChunk(chunk)
|
val w = expandChunk(chunk.toUByteArray())
|
||||||
mix(h, w)
|
mix(h, w)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ class Sha512 : UpdatableHash {
|
|||||||
return ((x and y) xor (x and z) xor (y and z))
|
return ((x and y) xor (x and z) xor (y and z))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun expandChunk(chunk: Array<UByte>): Array<ULong> {
|
private fun expandChunk(chunk: UByteArray): Array<ULong> {
|
||||||
val w = Array<ULong>(CHUNK_SIZE) {
|
val w = Array<ULong>(CHUNK_SIZE) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in 0 until 16 -> {
|
in 0 until 16 -> {
|
||||||
@ -259,7 +259,7 @@ class Sha512 : UpdatableHash {
|
|||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createExpansionArray(originalSizeInBytes: Int): Array<UByte> {
|
fun createExpansionArray(originalSizeInBytes: Int): UByteArray {
|
||||||
val originalMessageSizeInBits = originalSizeInBytes * 8
|
val originalMessageSizeInBits = originalSizeInBytes * 8
|
||||||
|
|
||||||
val expandedRemainderOf1024 = (originalMessageSizeInBits + 129) % BLOCK_SIZE
|
val expandedRemainderOf1024 = (originalMessageSizeInBits + 129) % BLOCK_SIZE
|
||||||
@ -267,7 +267,7 @@ class Sha512 : UpdatableHash {
|
|||||||
0 -> 0
|
0 -> 0
|
||||||
else -> (BLOCK_SIZE - expandedRemainderOf1024) / 8
|
else -> (BLOCK_SIZE - expandedRemainderOf1024) / 8
|
||||||
}
|
}
|
||||||
val expansionArray = Array<UByte>(zeroAddAmount + 1) {
|
val expansionArray = UByteArray(zeroAddAmount + 1) {
|
||||||
when (it) {
|
when (it) {
|
||||||
0 -> 0b10000000U
|
0 -> 0b10000000U
|
||||||
else -> 0U
|
else -> 0U
|
||||||
@ -277,10 +277,10 @@ class Sha512 : UpdatableHash {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun ULong.toPaddedByteArray(): Array<UByte> {
|
private fun ULong.toPaddedByteArray(): UByteArray {
|
||||||
val byteMask = 0xFFUL
|
val byteMask = 0xFFUL
|
||||||
//Ignore messages longer than 64 bits for now
|
//Ignore messages longer than 64 bits for now
|
||||||
return Array(8) {
|
return UByteArray(8) {
|
||||||
when (it) {
|
when (it) {
|
||||||
7 -> (this and byteMask).toUByte()
|
7 -> (this and byteMask).toUByte()
|
||||||
6 -> ((this shr 8) and byteMask).toUByte()
|
6 -> ((this shr 8) and byteMask).toUByte()
|
||||||
@ -295,10 +295,10 @@ class Sha512 : UpdatableHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ULong.toPadded128BitByteArray(): Array<UByte> {
|
private fun ULong.toPadded128BitByteArray(): UByteArray {
|
||||||
val byteMask = 0xFFUL
|
val byteMask = 0xFFUL
|
||||||
//Ignore messages longer than 64 bits for now
|
//Ignore messages longer than 64 bits for now
|
||||||
return Array(16) {
|
return UByteArray(16) {
|
||||||
when (it) {
|
when (it) {
|
||||||
15 -> (this and byteMask).toUByte()
|
15 -> (this and byteMask).toUByte()
|
||||||
14 -> ((this shr 8) and byteMask).toUByte()
|
14 -> ((this shr 8) and byteMask).toUByte()
|
||||||
@ -317,14 +317,14 @@ class Sha512 : UpdatableHash {
|
|||||||
var h = iv.copyOf()
|
var h = iv.copyOf()
|
||||||
var counter = 0
|
var counter = 0
|
||||||
var bufferCounter = 0
|
var bufferCounter = 0
|
||||||
var buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) { 0U }
|
var buffer = UByteArray(BLOCK_SIZE_IN_BYTES) { 0U }
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
override fun update(data: String) {
|
override fun update(data: String) {
|
||||||
return update(data.encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
return update(data.encodeToByteArray().toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(data: Array<UByte>) {
|
override fun update(data: UByteArray) {
|
||||||
if (data.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")
|
||||||
}
|
}
|
||||||
@ -335,9 +335,9 @@ class Sha512 : UpdatableHash {
|
|||||||
val chunked = data.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.toUByteArray(), bufferCounter)
|
||||||
} else {
|
} else {
|
||||||
chunk.copyInto(
|
chunk.toUByteArray().copyInto(
|
||||||
destination = buffer,
|
destination = buffer,
|
||||||
destinationOffset = bufferCounter,
|
destinationOffset = bufferCounter,
|
||||||
startIndex = 0,
|
startIndex = 0,
|
||||||
@ -345,7 +345,7 @@ class Sha512 : UpdatableHash {
|
|||||||
)
|
)
|
||||||
counter += BLOCK_SIZE_IN_BYTES
|
counter += BLOCK_SIZE_IN_BYTES
|
||||||
consumeBlock(buffer)
|
consumeBlock(buffer)
|
||||||
buffer = Array<UByte>(BLOCK_SIZE_IN_BYTES) {
|
buffer = UByteArray(BLOCK_SIZE_IN_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
|
in (0 until (chunk.size - (BLOCK_SIZE_IN_BYTES - bufferCounter))) -> {
|
||||||
chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
|
chunk[it + (BLOCK_SIZE_IN_BYTES - bufferCounter)]
|
||||||
@ -364,18 +364,18 @@ class Sha512 : UpdatableHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeBlock(block: Array<UByte>) {
|
private fun consumeBlock(block: UByteArray) {
|
||||||
val w = expandChunk(block)
|
val w = expandChunk(block)
|
||||||
mix(h, w).copyInto(h)
|
mix(h, w).copyInto(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun digest(): Array<UByte> {
|
override fun digest(): UByteArray {
|
||||||
val length = counter + bufferCounter
|
val length = counter + bufferCounter
|
||||||
val expansionArray = createExpansionArray(length)
|
val expansionArray = createExpansionArray(length)
|
||||||
val finalBlock =
|
val finalBlock =
|
||||||
buffer.copyOfRange(0, bufferCounter) + expansionArray + (length * 8).toULong().toPadded128BitByteArray()
|
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.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -394,7 +394,7 @@ class Sha512 : UpdatableHash {
|
|||||||
return digest().map { it.toString(16) }.joinToString(separator = "")
|
return digest().map { it.toString(16) }.joinToString(separator = "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appendToBuffer(array: Array<UByte>, start: Int) {
|
private fun appendToBuffer(array: UByteArray, 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
|
||||||
}
|
}
|
||||||
|
@ -310,8 +310,8 @@ class Argon2(
|
|||||||
key.size.toUInt().toLittleEndianUByteArray() + key +
|
key.size.toUInt().toLittleEndianUByteArray() + key +
|
||||||
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
|
associatedData.size.toUInt().toLittleEndianUByteArray() + associatedData
|
||||||
val h0 = Blake2b.digest(
|
val h0 = Blake2b.digest(
|
||||||
blakeInput.toTypedArray()
|
blakeInput
|
||||||
).toUByteArray()
|
)
|
||||||
|
|
||||||
//Compute B[i][0]
|
//Compute B[i][0]
|
||||||
for (i in 0 until parallelism) {
|
for (i in 0 until parallelism) {
|
||||||
|
@ -127,17 +127,17 @@ object Argon2Utils {
|
|||||||
|
|
||||||
internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray {
|
internal fun argonBlake2bArbitraryLenghtHash(input: UByteArray, length: UInt): UByteArray {
|
||||||
if (length <= 64U) {
|
if (length <= 64U) {
|
||||||
return Blake2b.digest(inputMessage = length + input.toTypedArray(), hashLength = length.toInt()).toUByteArray()
|
return Blake2b.digest(inputMessage = length + input, hashLength = length.toInt())
|
||||||
}
|
}
|
||||||
//We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
|
//We can cast to int because UInt even if MAX_VALUE divided by 32 is guaranteed not to overflow
|
||||||
val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2
|
val numberOf64ByteBlocks = (1U + ((length - 1U) / 32U) - 2U).toInt() // equivalent to ceil(length/32) - 2
|
||||||
val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() }
|
val v = Array<UByteArray>(numberOf64ByteBlocks) { ubyteArrayOf() }
|
||||||
v[0] = Blake2b.digest(length + input.toTypedArray()).toUByteArray()
|
v[0] = Blake2b.digest(length + input)
|
||||||
for (i in 1 until numberOf64ByteBlocks) {
|
for (i in 1 until numberOf64ByteBlocks) {
|
||||||
v[i] = Blake2b.digest(v[i - 1].toTypedArray()).toUByteArray()
|
v[i] = Blake2b.digest(v[i - 1])
|
||||||
}
|
}
|
||||||
val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32
|
val remainingPartOfInput = length.toInt() - numberOf64ByteBlocks * 32
|
||||||
val vLast = Blake2b.digest(v[numberOf64ByteBlocks - 1].toTypedArray(), hashLength = remainingPartOfInput).toUByteArray()
|
val vLast = Blake2b.digest(v[numberOf64ByteBlocks - 1], hashLength = remainingPartOfInput)
|
||||||
val concat =
|
val concat =
|
||||||
(v.map { it.copyOfRange(0, 32) })
|
(v.map { it.copyOfRange(0, 32) })
|
||||||
.plus(listOf(vLast))
|
.plus(listOf(vLast))
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.ionspin.kotlin.crypto.symmetric
|
package com.ionspin.kotlin.crypto.symmetric
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.util.flattenToUByteArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019
|
* Created by Ugljesa Jovanovic (jovanovic.ugljesa@gmail.com) on 07/Sep/2019
|
||||||
*/
|
*/
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UByte>) {
|
internal class Aes internal constructor(val aesKey: AesKey, val input: UByteArray) {
|
||||||
companion object {
|
companion object {
|
||||||
private val debug = false
|
private val debug = false
|
||||||
|
|
||||||
@ -54,18 +56,18 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
|
|
||||||
val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U)
|
val rcon: UByteArray = ubyteArrayOf(0x8DU, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, 0x1BU, 0x36U)
|
||||||
|
|
||||||
fun encrypt(aesKey: AesKey, input: Array<UByte>): Array<UByte> {
|
fun encrypt(aesKey: AesKey, input: UByteArray): UByteArray {
|
||||||
return Aes(aesKey, input).encrypt()
|
return Aes(aesKey, input).encrypt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decrypt(aesKey: AesKey, input: Array<UByte>): Array<UByte> {
|
fun decrypt(aesKey: AesKey, input: UByteArray): UByteArray {
|
||||||
return Aes(aesKey, input).decrypt()
|
return Aes(aesKey, input).decrypt()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val state: Array<Array<UByte>> = (0 until 4).map { outerCounter ->
|
val state: Array<UByteArray> = (0 until 4).map { outerCounter ->
|
||||||
Array<UByte>(4) { innerCounter -> input[innerCounter * 4 + outerCounter] }
|
UByteArray(4) { innerCounter -> input[innerCounter * 4 + outerCounter] }
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
|
||||||
val numberOfRounds = when (aesKey) {
|
val numberOfRounds = when (aesKey) {
|
||||||
@ -74,7 +76,7 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
is AesKey.Aes256Key -> 14
|
is AesKey.Aes256Key -> 14
|
||||||
}
|
}
|
||||||
|
|
||||||
val expandedKey: Array<Array<UByte>> = expandKey()
|
val expandedKey: Array<UByteArray> = expandKey()
|
||||||
|
|
||||||
|
|
||||||
var round = 0
|
var round = 0
|
||||||
@ -110,22 +112,22 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun shiftRows() {
|
fun shiftRows() {
|
||||||
state[0] = arrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
|
state[0] = ubyteArrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
|
||||||
state[1] = arrayOf(state[1][1], state[1][2], state[1][3], state[1][0])
|
state[1] = ubyteArrayOf(state[1][1], state[1][2], state[1][3], state[1][0])
|
||||||
state[2] = arrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
|
state[2] = ubyteArrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
|
||||||
state[3] = arrayOf(state[3][3], state[3][0], state[3][1], state[3][2])
|
state[3] = ubyteArrayOf(state[3][3], state[3][0], state[3][1], state[3][2])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun inversShiftRows() {
|
fun inversShiftRows() {
|
||||||
state[0] = arrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
|
state[0] = ubyteArrayOf(state[0][0], state[0][1], state[0][2], state[0][3])
|
||||||
state[1] = arrayOf(state[1][3], state[1][0], state[1][1], state[1][2])
|
state[1] = ubyteArrayOf(state[1][3], state[1][0], state[1][1], state[1][2])
|
||||||
state[2] = arrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
|
state[2] = ubyteArrayOf(state[2][2], state[2][3], state[2][0], state[2][1])
|
||||||
state[3] = arrayOf(state[3][1], state[3][2], state[3][3], state[3][0])
|
state[3] = ubyteArrayOf(state[3][1], state[3][2], state[3][3], state[3][0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mixColumns() {
|
fun mixColumns() {
|
||||||
val stateMixed: Array<Array<UByte>> = (0 until 4).map {
|
val stateMixed: Array<UByteArray> = (0 until 4).map {
|
||||||
Array<UByte>(4) { 0U }
|
UByteArray(4) { 0U }
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
for (c in 0..3) {
|
for (c in 0..3) {
|
||||||
|
|
||||||
@ -138,8 +140,8 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun inverseMixColumns() {
|
fun inverseMixColumns() {
|
||||||
val stateMixed: Array<Array<UByte>> = (0 until 4).map {
|
val stateMixed: Array<UByteArray> = (0 until 4).map {
|
||||||
Array<UByte>(4) { 0U }
|
UByteArray(4) { 0U }
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
for (c in 0..3) {
|
for (c in 0..3) {
|
||||||
stateMixed[0][c] =
|
stateMixed[0][c] =
|
||||||
@ -203,9 +205,9 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
return galoisFieldMultiply(this.toUByte(), second)
|
return galoisFieldMultiply(this.toUByte(), second)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun expandKey(): Array<Array<UByte>> {
|
fun expandKey(): Array<UByteArray> {
|
||||||
val expandedKey = (0 until 4 * (numberOfRounds + 1)).map {
|
val expandedKey = (0 until 4 * (numberOfRounds + 1)).map {
|
||||||
Array<UByte>(4) { 0U }
|
UByteArray(4) { 0U }
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
// First round
|
// First round
|
||||||
for (i in 0 until aesKey.numberOf32BitWords) {
|
for (i in 0 until aesKey.numberOf32BitWords) {
|
||||||
@ -241,13 +243,13 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
}
|
}
|
||||||
expandedKey[i] = expandedKey[i - aesKey.numberOf32BitWords].mapIndexed { index, it ->
|
expandedKey[i] = expandedKey[i - aesKey.numberOf32BitWords].mapIndexed { index, it ->
|
||||||
it xor temp[index]
|
it xor temp[index]
|
||||||
}.toTypedArray()
|
}.toUByteArray()
|
||||||
clearArray(temp)
|
clearArray(temp)
|
||||||
}
|
}
|
||||||
return expandedKey
|
return expandedKey
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encrypt(): Array<UByte> {
|
fun encrypt(): UByteArray {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
throw RuntimeException("Encrypt can only be called once per Aes instance, since the state is cleared at the " +
|
throw RuntimeException("Encrypt can only be called once per Aes instance, since the state is cleared at the " +
|
||||||
"end of the operation")
|
"end of the operation")
|
||||||
@ -273,8 +275,8 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
addRoundKey()
|
addRoundKey()
|
||||||
printState()
|
printState()
|
||||||
val transposedMatrix = (0 until 4).map { outerCounter ->
|
val transposedMatrix = (0 until 4).map { outerCounter ->
|
||||||
Array<UByte>(4) { 0U }
|
UByteArray(4) { 0U }
|
||||||
}.toTypedArray()
|
}
|
||||||
for (i in 0 until 4) {
|
for (i in 0 until 4) {
|
||||||
for (j in 0 until 4) {
|
for (j in 0 until 4) {
|
||||||
transposedMatrix[i][j] = state[j][i]
|
transposedMatrix[i][j] = state[j][i]
|
||||||
@ -282,10 +284,10 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
}
|
}
|
||||||
state.forEach { clearArray(it) }
|
state.forEach { clearArray(it) }
|
||||||
completed = true
|
completed = true
|
||||||
return transposedMatrix.flatten().toTypedArray()
|
return transposedMatrix.flattenToUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decrypt(): Array<UByte> {
|
fun decrypt(): UByteArray {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
throw RuntimeException("Decrypt can only be called once per Aes instance, since the state is cleared at the " +
|
throw RuntimeException("Decrypt can only be called once per Aes instance, since the state is cleared at the " +
|
||||||
"end of the operation")
|
"end of the operation")
|
||||||
@ -313,20 +315,19 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
printState()
|
printState()
|
||||||
|
|
||||||
val transposedMatrix = (0 until 4).map { outerCounter ->
|
val transposedMatrix = (0 until 4).map { outerCounter ->
|
||||||
Array<UByte>(4) { 0U }
|
UByteArray(4) { 0U }
|
||||||
}.toTypedArray()
|
}
|
||||||
for (i in 0 until 4) {
|
for (i in 0 until 4) {
|
||||||
for (j in 0 until 4) {
|
for (j in 0 until 4) {
|
||||||
transposedMatrix[i][j] = state[j][i]
|
transposedMatrix[i][j] = state[j][i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printState(transposedMatrix)
|
|
||||||
state.forEach { clearArray(it) }
|
state.forEach { clearArray(it) }
|
||||||
completed = true
|
completed = true
|
||||||
return transposedMatrix.flatten().toTypedArray()
|
return transposedMatrix.flattenToUByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clearArray(array : Array<UByte>) {
|
private fun clearArray(array : UByteArray) {
|
||||||
array.indices.forEach { array[it] = 0U }
|
array.indices.forEach { array[it] = 0U }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +343,7 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun printState(specific : Array<Array<UByte>>) {
|
private fun printState(specific : List<UByteArray>) {
|
||||||
if (!debug) {
|
if (!debug) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -356,7 +357,7 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
|
|||||||
}
|
}
|
||||||
|
|
||||||
sealed class AesKey(val key: String, val keyLength: Int) {
|
sealed class AesKey(val key: String, val keyLength: Int) {
|
||||||
val keyArray: Array<UByte> = key.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
val keyArray: UByteArray = key.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
val numberOf32BitWords = keyLength / 32
|
val numberOf32BitWords = keyLength / 32
|
||||||
|
|
||||||
class Aes128Key(key: String) : AesKey(key, 128)
|
class Aes128Key(key: String) : AesKey(key, 128)
|
||||||
|
@ -32,7 +32,7 @@ import com.ionspin.kotlin.crypto.util.xor
|
|||||||
* on 21-Sep-2019
|
* on 21-Sep-2019
|
||||||
*/
|
*/
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: Array<UByte>? = null) {
|
class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializationVector: UByteArray? = null) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val BLOCK_BYTES = 16
|
const val BLOCK_BYTES = 16
|
||||||
@ -54,7 +54,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
/**
|
/**
|
||||||
* Bulk encryption, returns encrypted data and a random initialization vector
|
* Bulk encryption, returns encrypted data and a random initialization vector
|
||||||
*/
|
*/
|
||||||
fun encrypt(aesKey: AesKey, data: Array<UByte>): EncryptedDataAndInitializationVector {
|
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitializationVector {
|
||||||
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
|
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
|
||||||
aesCbc.addData(data)
|
aesCbc.addData(data)
|
||||||
return aesCbc.encrypt()
|
return aesCbc.encrypt()
|
||||||
@ -63,20 +63,20 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
/**
|
/**
|
||||||
* Bulk decryption, returns decrypted data
|
* Bulk decryption, returns decrypted data
|
||||||
*/
|
*/
|
||||||
fun decrypt(aesKey: AesKey, data: Array<UByte>, initialCounter: Array<UByte>? = null): Array<UByte> {
|
fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
|
||||||
val aesCbc = AesCbc(aesKey, Mode.DECRYPT, initialCounter)
|
val aesCbc = AesCbc(aesKey, Mode.DECRYPT, initialCounter)
|
||||||
aesCbc.addData(data)
|
aesCbc.addData(data)
|
||||||
return aesCbc.decrypt()
|
return aesCbc.decrypt()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun padToBlock(unpadded: Array<UByte>): Array<UByte> {
|
private fun padToBlock(unpadded: UByteArray): UByteArray {
|
||||||
val paddingSize = 16 - unpadded.size
|
val paddingSize = 16 - unpadded.size
|
||||||
if (unpadded.size == BLOCK_BYTES) {
|
if (unpadded.size == BLOCK_BYTES) {
|
||||||
return unpadded
|
return unpadded
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unpadded.size == BLOCK_BYTES) {
|
if (unpadded.size == BLOCK_BYTES) {
|
||||||
return Array(BLOCK_BYTES) {
|
return UByteArray(BLOCK_BYTES) {
|
||||||
BLOCK_BYTES.toUByte()
|
BLOCK_BYTES.toUByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
throw IllegalStateException("Block larger than 128 bytes")
|
throw IllegalStateException("Block larger than 128 bytes")
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array(BLOCK_BYTES) {
|
return UByteArray(BLOCK_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in unpadded.indices -> unpadded[it]
|
in unpadded.indices -> unpadded[it]
|
||||||
else -> paddingSize.toUByte()
|
else -> paddingSize.toUByte()
|
||||||
@ -95,20 +95,20 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentOutput: Array<UByte> = arrayOf()
|
var currentOutput: UByteArray = ubyteArrayOf()
|
||||||
var previousEncrypted: Array<UByte> = arrayOf()
|
var previousEncrypted: UByteArray = ubyteArrayOf()
|
||||||
val initVector = if (initializationVector.isNullOrEmpty()) {
|
val initVector = if (initializationVector.isNullOrEmpty()) {
|
||||||
SRNG.getRandomBytes(16).toTypedArray()
|
SRNG.getRandomBytes(16)
|
||||||
} else {
|
} else {
|
||||||
initializationVector
|
initializationVector
|
||||||
}
|
}
|
||||||
|
|
||||||
val output = MutableList<Array<UByte>>(0) { arrayOf() }
|
val output = MutableList<UByteArray>(0) { ubyteArrayOf() }
|
||||||
|
|
||||||
var buffer: Array<UByte> = UByteArray(16) { 0U }.toTypedArray()
|
var buffer: UByteArray = UByteArray(16) { 0U }
|
||||||
var bufferCounter = 0
|
var bufferCounter = 0
|
||||||
|
|
||||||
fun addData(data: Array<UByte>) {
|
fun addData(data: UByteArray) {
|
||||||
//Padding
|
//Padding
|
||||||
when {
|
when {
|
||||||
bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
|
bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
|
||||||
@ -116,16 +116,16 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
val chunked = data.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.toUByteArray(), bufferCounter)
|
||||||
} else {
|
} else {
|
||||||
chunk.copyInto(
|
chunk.toUByteArray().copyInto(
|
||||||
destination = buffer,
|
destination = buffer,
|
||||||
destinationOffset = bufferCounter,
|
destinationOffset = bufferCounter,
|
||||||
startIndex = 0,
|
startIndex = 0,
|
||||||
endIndex = BLOCK_BYTES - bufferCounter
|
endIndex = BLOCK_BYTES - bufferCounter
|
||||||
)
|
)
|
||||||
output += consumeBlock(buffer)
|
output += consumeBlock(buffer)
|
||||||
buffer = Array<UByte>(BLOCK_BYTES) {
|
buffer = UByteArray(BLOCK_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
|
in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
|
||||||
chunk[it + (BLOCK_BYTES - bufferCounter)]
|
chunk[it + (BLOCK_BYTES - bufferCounter)]
|
||||||
@ -153,7 +153,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
if (bufferCounter > 0) {
|
if (bufferCounter > 0) {
|
||||||
val lastBlockPadded = padToBlock(buffer)
|
val lastBlockPadded = padToBlock(buffer)
|
||||||
if (lastBlockPadded.size > BLOCK_BYTES) {
|
if (lastBlockPadded.size > BLOCK_BYTES) {
|
||||||
val chunks = lastBlockPadded.chunked(BLOCK_BYTES)
|
val chunks = lastBlockPadded.chunked(BLOCK_BYTES).map { it.toUByteArray() }
|
||||||
output += consumeBlock(chunks[0])
|
output += consumeBlock(chunks[0])
|
||||||
output += consumeBlock(chunks[1])
|
output += consumeBlock(chunks[1])
|
||||||
} else {
|
} else {
|
||||||
@ -161,7 +161,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return EncryptedDataAndInitializationVector(
|
return EncryptedDataAndInitializationVector(
|
||||||
output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
|
output.reversed().foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
|
||||||
initVector
|
initVector
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
* Decrypt data
|
* Decrypt data
|
||||||
* @return Decrypted data
|
* @return Decrypted data
|
||||||
*/
|
*/
|
||||||
fun decrypt(): Array<UByte> {
|
fun decrypt(): UByteArray {
|
||||||
val removePaddingCount = output.last().last()
|
val removePaddingCount = output.last().last()
|
||||||
|
|
||||||
|
|
||||||
@ -178,22 +178,23 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
output.last().dropLast(removePaddingCount.toInt() and 0x7F)
|
output.last().dropLast(removePaddingCount.toInt() and 0x7F)
|
||||||
} else {
|
} else {
|
||||||
output.last().toList()
|
output.last().toList()
|
||||||
}
|
}.toUByteArray()
|
||||||
val preparedOutput = output.dropLast(1).toTypedArray() + removedPadding.toTypedArray()
|
val preparedOutput = (output.dropLast(1) + listOf(removedPadding))
|
||||||
//JS compiler freaks out here if we don't supply exact type
|
//JS compiler freaks out here if we don't supply exact type
|
||||||
val reversed : List<Array<UByte>> = preparedOutput.reversed() as List<Array<UByte>>
|
val reversed : List<UByteArray> = preparedOutput.reversed() as List<UByteArray>
|
||||||
val folded : Array<UByte> = reversed.foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc ->
|
val folded : UByteArray = reversed.foldRight(UByteArray(0) { 0U }) { uByteArray, acc ->
|
||||||
acc + arrayOfUBytes }
|
acc + uByteArray
|
||||||
|
}
|
||||||
return folded
|
return folded
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appendToBuffer(array: Array<UByte>, start: Int) {
|
private fun appendToBuffer(array: UByteArray, 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
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeBlock(data: Array<UByte>): Array<UByte> {
|
private fun consumeBlock(data: UByteArray): UByteArray {
|
||||||
return when (mode) {
|
return when (mode) {
|
||||||
Mode.ENCRYPT -> {
|
Mode.ENCRYPT -> {
|
||||||
currentOutput = if (currentOutput.isEmpty()) {
|
currentOutput = if (currentOutput.isEmpty()) {
|
||||||
@ -220,7 +221,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
data class EncryptedDataAndInitializationVector(val encryptedData : Array<UByte>, val initilizationVector : Array<UByte>) {
|
data class EncryptedDataAndInitializationVector(val encryptedData : UByteArray, val initilizationVector : UByteArray) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other == null || this::class != other::class) return false
|
if (other == null || this::class != other::class) return false
|
||||||
|
@ -37,7 +37,7 @@ import com.ionspin.kotlin.crypto.util.xor
|
|||||||
* on 22-Sep-2019
|
* on 22-Sep-2019
|
||||||
*/
|
*/
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: Array<UByte>? = null) {
|
class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCounter: UByteArray? = null) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val BLOCK_BYTES = 16
|
const val BLOCK_BYTES = 16
|
||||||
@ -60,7 +60,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
/**
|
/**
|
||||||
* Bulk encryption, returns encrypted data and a random initial counter
|
* Bulk encryption, returns encrypted data and a random initial counter
|
||||||
*/
|
*/
|
||||||
fun encrypt(aesKey: AesKey, data: Array<UByte>): EncryptedDataAndInitialCounter {
|
fun encrypt(aesKey: AesKey, data: UByteArray): EncryptedDataAndInitialCounter {
|
||||||
val aesCtr = AesCtr(aesKey, Mode.ENCRYPT)
|
val aesCtr = AesCtr(aesKey, Mode.ENCRYPT)
|
||||||
aesCtr.addData(data)
|
aesCtr.addData(data)
|
||||||
return aesCtr.encrypt()
|
return aesCtr.encrypt()
|
||||||
@ -68,7 +68,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
/**
|
/**
|
||||||
* Bulk decryption, returns decrypted data
|
* Bulk decryption, returns decrypted data
|
||||||
*/
|
*/
|
||||||
fun decrypt(aesKey: AesKey, data: Array<UByte>, initialCounter: Array<UByte>? = null): Array<UByte> {
|
fun decrypt(aesKey: AesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray {
|
||||||
val aesCtr = AesCtr(aesKey, Mode.DECRYPT, initialCounter)
|
val aesCtr = AesCtr(aesKey, Mode.DECRYPT, initialCounter)
|
||||||
aesCtr.addData(data)
|
aesCtr.addData(data)
|
||||||
return aesCtr.decrypt()
|
return aesCtr.decrypt()
|
||||||
@ -76,21 +76,21 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentOutput: Array<UByte> = arrayOf()
|
var currentOutput: UByteArray = ubyteArrayOf()
|
||||||
var previousEncrypted: Array<UByte> = arrayOf()
|
var previousEncrypted: UByteArray = ubyteArrayOf()
|
||||||
val counterStart = if (initialCounter.isNullOrEmpty()) {
|
val counterStart = if (initialCounter.isNullOrEmpty()) {
|
||||||
SRNG.getRandomBytes(16).toTypedArray()
|
SRNG.getRandomBytes(16)
|
||||||
} else {
|
} else {
|
||||||
initialCounter
|
initialCounter
|
||||||
}
|
}
|
||||||
var blockCounter = modularCreator.fromBigInteger(BigInteger.fromUByteArray(counterStart, Endianness.BIG))
|
var blockCounter = modularCreator.fromBigInteger(BigInteger.fromUByteArray(counterStart.toTypedArray(), Endianness.BIG))
|
||||||
|
|
||||||
val output = MutableList<Array<UByte>>(0) { arrayOf() }
|
val output = MutableList<UByteArray>(0) { ubyteArrayOf() }
|
||||||
|
|
||||||
var buffer: Array<UByte> = UByteArray(16) { 0U }.toTypedArray()
|
var buffer: UByteArray = UByteArray(16) { 0U }
|
||||||
var bufferCounter = 0
|
var bufferCounter = 0
|
||||||
|
|
||||||
fun addData(data: Array<UByte>) {
|
fun addData(data: UByteArray) {
|
||||||
//Padding
|
//Padding
|
||||||
when {
|
when {
|
||||||
bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
|
bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter)
|
||||||
@ -98,9 +98,9 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
val chunked = data.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.toUByteArray(), bufferCounter)
|
||||||
} else {
|
} else {
|
||||||
chunk.copyInto(
|
chunk.toUByteArray().copyInto(
|
||||||
destination = buffer,
|
destination = buffer,
|
||||||
destinationOffset = bufferCounter,
|
destinationOffset = bufferCounter,
|
||||||
startIndex = 0,
|
startIndex = 0,
|
||||||
@ -108,7 +108,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
)
|
)
|
||||||
output += consumeBlock(buffer, blockCounter)
|
output += consumeBlock(buffer, blockCounter)
|
||||||
blockCounter += 1
|
blockCounter += 1
|
||||||
buffer = Array<UByte>(BLOCK_BYTES) {
|
buffer = UByteArray(BLOCK_BYTES) {
|
||||||
when (it) {
|
when (it) {
|
||||||
in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
|
in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> {
|
||||||
chunk[it + (BLOCK_BYTES - bufferCounter)]
|
chunk[it + (BLOCK_BYTES - bufferCounter)]
|
||||||
@ -136,7 +136,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
output += consumeBlock(buffer, blockCounter)
|
output += consumeBlock(buffer, blockCounter)
|
||||||
}
|
}
|
||||||
return EncryptedDataAndInitialCounter(
|
return EncryptedDataAndInitialCounter(
|
||||||
output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
|
output.reversed().foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
|
||||||
counterStart
|
counterStart
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -144,25 +144,25 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
* Decrypt data
|
* Decrypt data
|
||||||
* @return Decrypted data
|
* @return Decrypted data
|
||||||
*/
|
*/
|
||||||
fun decrypt(): Array<UByte> {
|
fun decrypt(): UByteArray {
|
||||||
if (bufferCounter > 0) {
|
if (bufferCounter > 0) {
|
||||||
output += consumeBlock(buffer, blockCounter)
|
output += consumeBlock(buffer, blockCounter)
|
||||||
}
|
}
|
||||||
//JS compiler freaks out here if we don't supply exact type
|
//JS compiler freaks out here if we don't supply exact type
|
||||||
val reversed: List<Array<UByte>> = output.reversed() as List<Array<UByte>>
|
val reversed: List<UByteArray> = output.reversed() as List<UByteArray>
|
||||||
val folded: Array<UByte> = reversed.foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc ->
|
val folded: UByteArray = reversed.foldRight(UByteArray(0) { 0U }) { arrayOfUBytes, acc ->
|
||||||
acc + arrayOfUBytes
|
acc + arrayOfUBytes
|
||||||
}
|
}
|
||||||
return folded
|
return folded
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun appendToBuffer(array: Array<UByte>, start: Int) {
|
private fun appendToBuffer(array: UByteArray, 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
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun consumeBlock(data: Array<UByte>, blockCount: ModularBigInteger): Array<UByte> {
|
private fun consumeBlock(data: UByteArray, blockCount: ModularBigInteger): UByteArray {
|
||||||
val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).expandCounterTo16Bytes()
|
val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).toUByteArray().expandCounterTo16Bytes()
|
||||||
return when (mode) {
|
return when (mode) {
|
||||||
Mode.ENCRYPT -> {
|
Mode.ENCRYPT -> {
|
||||||
Aes.encrypt(aesKey, blockCountAsByteArray) xor data
|
Aes.encrypt(aesKey, blockCountAsByteArray) xor data
|
||||||
@ -174,11 +174,11 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Array<UByte>.expandCounterTo16Bytes() : Array<UByte> {
|
private fun UByteArray.expandCounterTo16Bytes() : UByteArray {
|
||||||
return if (this.size < 16) {
|
return if (this.size < 16) {
|
||||||
println("Expanding")
|
println("Expanding")
|
||||||
val diff = 16 - this.size
|
val diff = 16 - this.size
|
||||||
val pad = Array<UByte>(diff) { 0U }
|
val pad = UByteArray(diff) { 0U }
|
||||||
pad + this
|
pad + this
|
||||||
} else {
|
} else {
|
||||||
this
|
this
|
||||||
@ -188,7 +188,7 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
data class EncryptedDataAndInitialCounter(val encryptedData : Array<UByte>, val initialCounter : Array<UByte>) {
|
data class EncryptedDataAndInitialCounter(val encryptedData : UByteArray, val initialCounter : UByteArray) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other == null || this::class != other::class) return false
|
if (other == null || this::class != other::class) return false
|
||||||
|
@ -89,10 +89,15 @@ infix fun UByteArray.xor(other : UByteArray) : UByteArray {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
fun String.hexStringToUByteArray() : Array<UByte> {
|
fun String.hexStringToTypedUByteArray() : Array<UByte> {
|
||||||
return this.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
return this.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun String.hexStringToUByteArray() : UByteArray {
|
||||||
|
return this.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
fun Array<UByte>.toHexString() : String {
|
fun Array<UByte>.toHexString() : String {
|
||||||
return this.joinToString(separator = "") {
|
return this.joinToString(separator = "") {
|
||||||
@ -104,6 +109,17 @@ fun Array<UByte>.toHexString() : String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
fun UByteArray.toHexString() : String {
|
||||||
|
return this.joinToString(separator = "") {
|
||||||
|
if (it <= 0x0FU) {
|
||||||
|
"0${it.toString(16)}"
|
||||||
|
} else {
|
||||||
|
it.toString(16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// UInt / Array utils
|
// UInt / Array utils
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
fun UInt.toBigEndianUByteArray() : Array<UByte> {
|
fun UInt.toBigEndianUByteArray() : Array<UByte> {
|
||||||
@ -228,6 +244,19 @@ fun Array<UByte>.fromBigEndianArrayToUInt() : UInt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
@ExperimentalUnsignedTypes
|
||||||
operator fun UInt.plus(other : Array<UByte>) : Array<UByte> {
|
operator fun UInt.plus(other : UByteArray) : UByteArray {
|
||||||
return this.toLittleEndianTypedUByteArray() + other
|
return this.toLittleEndianUByteArray() + other
|
||||||
|
}
|
||||||
|
|
||||||
|
//AES Flatten
|
||||||
|
fun Collection<UByteArray>.flattenToUByteArray(): UByteArray {
|
||||||
|
val result = UByteArray(sumBy { it.size })
|
||||||
|
var position = 0
|
||||||
|
for (element in this) {
|
||||||
|
element.forEach { uByte ->
|
||||||
|
result[position] = uByte
|
||||||
|
position++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
@ -39,7 +39,7 @@ class ReadmeTest {
|
|||||||
val input = "abc"
|
val input = "abc"
|
||||||
val result = Blake2b.digest(input)
|
val result = Blake2b.digest(input)
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
val expectedResult = arrayOf<UByte>(
|
val expectedResult = ubyteArrayOf(
|
||||||
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
|
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
|
||||||
0x4CU,0x21U,0x2FU,0x14U,0x68U,0x5AU,0xC4U,0xB7U,0x4BU,0x12U,0xBBU,0x6FU,0xDBU,0xFFU,0xA2U,0xD1U,
|
0x4CU,0x21U,0x2FU,0x14U,0x68U,0x5AU,0xC4U,0xB7U,0x4BU,0x12U,0xBBU,0x6FU,0xDBU,0xFFU,0xA2U,0xD1U,
|
||||||
0x7DU,0x87U,0xC5U,0x39U,0x2AU,0xABU,0x79U,0x2DU,0xC2U,0x52U,0xD5U,0xDEU,0x45U,0x33U,0xCCU,0x95U,
|
0x7DU,0x87U,0xC5U,0x39U,0x2AU,0xABU,0x79U,0x2DU,0xC2U,0x52U,0xD5U,0xDEU,0x45U,0x33U,0xCCU,0x95U,
|
||||||
@ -65,7 +65,7 @@ class ReadmeTest {
|
|||||||
}
|
}
|
||||||
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
|
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
|
||||||
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
|
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
|
||||||
.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult)
|
result.contentEquals(expectedResult)
|
||||||
@ -79,7 +79,7 @@ class ReadmeTest {
|
|||||||
val result = Sha256.digest(inputString = 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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,12 +89,12 @@ class ReadmeTest {
|
|||||||
@Test
|
@Test
|
||||||
fun sha512Example() {
|
fun sha512Example() {
|
||||||
val input = "abc"
|
val input = "abc"
|
||||||
val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
val result = Sha512.digest(inputMessage = input.encodeToByteArray().map { it.toUByte() }.toUByteArray())
|
||||||
println(result.map { it.toString(16) })
|
println(result.map { it.toString(16) })
|
||||||
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
||||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class ReadmeTest {
|
|||||||
val result = sha256.digest()
|
val result = sha256.digest()
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ class ReadmeTest {
|
|||||||
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
||||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class Blake2BTest {
|
|||||||
|
|
||||||
val result = Blake2b.digest(test)
|
val result = Blake2b.digest(test)
|
||||||
//Generated with b2sum 8.31
|
//Generated with b2sum 8.31
|
||||||
val expectedResult = arrayOf<UByte>(
|
val expectedResult = ubyteArrayOf(
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
0x2fU, 0x49U, 0xaeU, 0xb6U, 0x13U, 0xe3U, 0x4eU, 0x92U, 0x4eU, 0x17U, 0x5aU, 0x6aU, 0xf2U, 0xfaU, 0xadU,
|
0x2fU, 0x49U, 0xaeU, 0xb6U, 0x13U, 0xe3U, 0x4eU, 0x92U, 0x4eU, 0x17U, 0x5aU, 0x6aU, 0xf2U, 0xfaU, 0xadU,
|
||||||
0x7bU, 0xc7U, 0x82U, 0x35U, 0xf9U, 0xc5U, 0xe4U, 0x61U, 0xc6U, 0x8fU, 0xd5U, 0xb4U, 0x07U, 0xeeU, 0x8eU,
|
0x7bU, 0xc7U, 0x82U, 0x35U, 0xf9U, 0xc5U, 0xe4U, 0x61U, 0xc6U, 0x8fU, 0xd5U, 0xb4U, 0x07U, 0xeeU, 0x8eU,
|
||||||
@ -81,7 +81,7 @@ class Blake2BTest {
|
|||||||
val expectedResultString = "800bb78cd4da18995c8074713bb674" +
|
val expectedResultString = "800bb78cd4da18995c8074713bb674" +
|
||||||
"3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" +
|
"3cd94b2b6490a693fe4000ed00833b88b7b474d94af9cfed246b1b" +
|
||||||
"4ce1935a76154d7ea7c410493557741d18ec3a08da75"
|
"4ce1935a76154d7ea7c410493557741d18ec3a08da75"
|
||||||
val expectedResult = expectedResultString.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
val expectedResult = expectedResultString.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult)
|
result.contentEquals(expectedResult)
|
||||||
@ -95,7 +95,7 @@ class Blake2BTest {
|
|||||||
|
|
||||||
val result = Blake2b.digest(test)
|
val result = Blake2b.digest(test)
|
||||||
//Generated with b2sum 8.31
|
//Generated with b2sum 8.31
|
||||||
val expectedResult = arrayOf<UByte>(
|
val expectedResult = ubyteArrayOf(
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
0xe0U, 0xabU, 0xb7U, 0x5dU, 0xb2U, 0xc8U, 0xe1U, 0x3cU, 0x5fU, 0x1dU, 0x9fU, 0x55U, 0xc8U, 0x4eU, 0xacU, 0xd7U,
|
0xe0U, 0xabU, 0xb7U, 0x5dU, 0xb2U, 0xc8U, 0xe1U, 0x3cU, 0x5fU, 0x1dU, 0x9fU, 0x55U, 0xc8U, 0x4eU, 0xacU, 0xd7U,
|
||||||
0xa8U, 0x44U, 0x57U, 0x9bU, 0xc6U, 0x9cU, 0x47U, 0x26U, 0xebU, 0xeaU, 0x2bU, 0xafU, 0x9eU, 0x44U, 0x16U, 0xebU,
|
0xa8U, 0x44U, 0x57U, 0x9bU, 0xc6U, 0x9cU, 0x47U, 0x26U, 0xebU, 0xeaU, 0x2bU, 0xafU, 0x9eU, 0x44U, 0x16U, 0xebU,
|
||||||
@ -122,7 +122,7 @@ class Blake2BTest {
|
|||||||
}
|
}
|
||||||
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
|
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
|
||||||
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
|
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
|
||||||
.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult)
|
result.contentEquals(expectedResult)
|
||||||
@ -136,7 +136,7 @@ class Blake2BTest {
|
|||||||
|
|
||||||
val result = Blake2b.digest(test)
|
val result = Blake2b.digest(test)
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
val expectedResult = arrayOf<UByte>(
|
val expectedResult = ubyteArrayOf(
|
||||||
|
|
||||||
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
|
0xBAU,0x80U,0xA5U,0x3FU,0x98U,0x1CU,0x4DU,0x0DU,0x6AU,0x27U,0x97U,0xB6U,0x9FU,0x12U,0xF6U,0xE9U,
|
||||||
0x4CU,0x21U,0x2FU,0x14U,0x68U,0x5AU,0xC4U,0xB7U,0x4BU,0x12U,0xBBU,0x6FU,0xDBU,0xFFU,0xA2U,0xD1U,
|
0x4CU,0x21U,0x2FU,0x14U,0x68U,0x5AU,0xC4U,0xB7U,0x4BU,0x12U,0xBBU,0x6FU,0xDBU,0xFFU,0xA2U,0xD1U,
|
||||||
|
@ -32,7 +32,7 @@ class Blake2bInstanceTest {
|
|||||||
fun testUpdatableBlake2b() {
|
fun testUpdatableBlake2b() {
|
||||||
val updates = 14
|
val updates = 14
|
||||||
val input = "1234567890"
|
val input = "1234567890"
|
||||||
val expectedResult = arrayOf<UByte>(
|
val expectedResult = ubyteArrayOf(
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
0x2fU, 0x49U, 0xaeU, 0xb6U, 0x13U, 0xe3U, 0x4eU, 0x92U, 0x4eU, 0x17U, 0x5aU, 0x6aU, 0xf2U, 0xfaU, 0xadU,
|
0x2fU, 0x49U, 0xaeU, 0xb6U, 0x13U, 0xe3U, 0x4eU, 0x92U, 0x4eU, 0x17U, 0x5aU, 0x6aU, 0xf2U, 0xfaU, 0xadU,
|
||||||
0x7bU, 0xc7U, 0x82U, 0x35U, 0xf9U, 0xc5U, 0xe4U, 0x61U, 0xc6U, 0x8fU, 0xd5U, 0xb4U, 0x07U, 0xeeU, 0x8eU,
|
0x7bU, 0xc7U, 0x82U, 0x35U, 0xf9U, 0xc5U, 0xe4U, 0x61U, 0xc6U, 0x8fU, 0xd5U, 0xb4U, 0x07U, 0xeeU, 0x8eU,
|
||||||
@ -83,7 +83,7 @@ class Blake2bInstanceTest {
|
|||||||
}
|
}
|
||||||
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
|
val expectedResult = ("5c6a9a4ae911c02fb7e71a991eb9aea371ae993d4842d206e" +
|
||||||
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
|
"6020d46f5e41358c6d5c277c110ef86c959ed63e6ecaaaceaaff38019a43264ae06acf73b9550b1")
|
||||||
.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult)
|
result.contentEquals(expectedResult)
|
||||||
|
@ -36,13 +36,13 @@ class Blake2bKnowAnswerTests {
|
|||||||
@Test
|
@Test
|
||||||
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) }.toUByteArray()
|
||||||
val result = Blake2b.digest(
|
val result = Blake2b.digest(
|
||||||
inputMessage = parsedInput,
|
inputMessage = parsedInput,
|
||||||
key = it.key.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
key = it.key.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
)
|
)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(it.hash.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
result.contentEquals(it.hash.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,13 +51,13 @@ class Blake2bKnowAnswerTests {
|
|||||||
fun knownAnswerTestInstance() {
|
fun knownAnswerTestInstance() {
|
||||||
|
|
||||||
kat.forEach { kat ->
|
kat.forEach { kat ->
|
||||||
val parsedInput = kat.input.chunked(2).map { it.toUByte(16) }.toTypedArray()
|
val parsedInput = kat.input.chunked(2).map { it.toUByte(16) }.toUByteArray()
|
||||||
val chunkedInput = parsedInput.toList().chunked(128).map { it.toTypedArray() }.toTypedArray()
|
val chunkedInput = parsedInput.toList().chunked(128).map { it.toUByteArray() }
|
||||||
val blake2b = Blake2b(key = kat.key.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
val blake2b = Blake2b(key = kat.key.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
chunkedInput.forEach { blake2b.update(it) }
|
chunkedInput.forEach { blake2b.update(it) }
|
||||||
val result = blake2b.digest()
|
val result = blake2b.digest()
|
||||||
assertTrue("KAT ${kat.input} \nkey: ${kat.key} \nexpected: {${kat.hash}") {
|
assertTrue("KAT ${kat.input} \nkey: ${kat.key} \nexpected: {${kat.hash}") {
|
||||||
result.contentEquals(kat.hash.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
result.contentEquals(kat.hash.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ class Sha256Test {
|
|||||||
val result = Sha256.digest(inputString = "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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class Sha256Test {
|
|||||||
val resultDoubleBlock = Sha256.digest(inputString = "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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class Sha256Test {
|
|||||||
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
|
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
|
||||||
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
|
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,10 +71,10 @@ class Sha256Test {
|
|||||||
for (i in 0 until 1000000) {
|
for (i in 0 until 1000000) {
|
||||||
inputBuilder.append("a")
|
inputBuilder.append("a")
|
||||||
}
|
}
|
||||||
val resultDoubleBlock = Sha256.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
val resultDoubleBlock = Sha256.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,7 +36,7 @@ class Sha256UpdatableTest {
|
|||||||
val result = sha256.digest()
|
val result = sha256.digest()
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ class Sha256UpdatableTest {
|
|||||||
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
|
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ class Sha256UpdatableTest {
|
|||||||
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
|
println(resultDoubleBlock.map{ it.toString(16)}.joinToString(separator = ""))
|
||||||
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
|
val expectedResultForDoubleBlock = "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class Sha256UpdatableTest {
|
|||||||
val resultDoubleBlock = sha256.digest()
|
val resultDoubleBlock = sha256.digest()
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class Sha256UpdatableTest {
|
|||||||
val resultDoubleBlock = sha256.digest()
|
val resultDoubleBlock = sha256.digest()
|
||||||
val expectedResultForDoubleBlock = "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e"
|
val expectedResultForDoubleBlock = "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,12 +30,12 @@ class Sha512Test {
|
|||||||
@Test
|
@Test
|
||||||
fun testWellKnownValue() {
|
fun testWellKnownValue() {
|
||||||
|
|
||||||
val result = Sha512.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
val result = Sha512.digest(inputMessage = "abc".encodeToByteArray().map { it.toUByte() }.toUByteArray())
|
||||||
println(result.map {it.toString(16)})
|
println(result.map {it.toString(16)})
|
||||||
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
||||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class Sha512Test {
|
|||||||
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
|
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
|
||||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
|
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +62,10 @@ class Sha512Test {
|
|||||||
for (i in 0 until 1000000) {
|
for (i in 0 until 1000000) {
|
||||||
inputBuilder.append("a")
|
inputBuilder.append("a")
|
||||||
}
|
}
|
||||||
val resultDoubleBlock = Sha512.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toTypedArray())
|
val resultDoubleBlock = Sha512.digest(inputMessage = (inputBuilder.toString()).encodeToByteArray().map { it.toUByte() }.toUByteArray())
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ class Sha512UpdatableTest {
|
|||||||
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
val expectedResult = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
||||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
result.contentEquals(expectedResult.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class Sha512UpdatableTest {
|
|||||||
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
|
val expectedResultForDoubleBlock = "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
|
||||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
|
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ class Sha512UpdatableTest {
|
|||||||
val resultDoubleBlock = sha512.digest()
|
val resultDoubleBlock = sha512.digest()
|
||||||
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) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ class Sha512UpdatableTest {
|
|||||||
val resultDoubleBlock = sha512.digest()
|
val resultDoubleBlock = sha512.digest()
|
||||||
val expectedResultForDoubleBlock = "b47c933421ea2db149ad6e10fce6c7f93d0752380180ffd7f4629a712134831d77be6091b819ed352c2967a2e2d4fa5050723c9630691f1a05a7281dbe6c1086"
|
val expectedResultForDoubleBlock = "b47c933421ea2db149ad6e10fce6c7f93d0752380180ffd7f4629a712134831d77be6091b819ed352c2967a2e2d4fa5050723c9630691f1a05a7281dbe6c1086"
|
||||||
assertTrue {
|
assertTrue {
|
||||||
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toTypedArray())
|
resultDoubleBlock.contentEquals(expectedResultForDoubleBlock.chunked(2).map { it.toUByte(16) }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.ionspin.kotlin.crypto.symmetric
|
package com.ionspin.kotlin.crypto.symmetric
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
|
import com.ionspin.kotlin.crypto.util.hexStringToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
@ -10,15 +10,15 @@ import kotlin.test.assertTrue
|
|||||||
class AesTest {
|
class AesTest {
|
||||||
|
|
||||||
val irrelevantKey = "01234567890123345678901234567890"
|
val irrelevantKey = "01234567890123345678901234567890"
|
||||||
val irrelevantInput = UByteArray(16) { 0U }.toTypedArray()
|
val irrelevantInput = UByteArray(16) { 0U }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSubBytes() {
|
fun testSubBytes() {
|
||||||
val fakeState = arrayOf(
|
val fakeState = arrayOf(
|
||||||
ubyteArrayOf(0x53U, 0U, 0U, 0U).toTypedArray(),
|
ubyteArrayOf(0x53U, 0U, 0U, 0U),
|
||||||
ubyteArrayOf(0U, 0U, 0U, 0U).toTypedArray(),
|
ubyteArrayOf(0U, 0U, 0U, 0U),
|
||||||
ubyteArrayOf(0U, 0U, 0U, 0U).toTypedArray(),
|
ubyteArrayOf(0U, 0U, 0U, 0U),
|
||||||
ubyteArrayOf(0U, 0U, 0U, 0U).toTypedArray()
|
ubyteArrayOf(0U, 0U, 0U, 0U)
|
||||||
)
|
)
|
||||||
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
|
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
|
||||||
fakeState.copyInto(aes.state)
|
fakeState.copyInto(aes.state)
|
||||||
@ -31,16 +31,16 @@ class AesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testShiftRows() {
|
fun testShiftRows() {
|
||||||
val fakeState = arrayOf(
|
val fakeState = arrayOf(
|
||||||
ubyteArrayOf(0U, 1U, 2U, 3U).toTypedArray(),
|
ubyteArrayOf(0U, 1U, 2U, 3U),
|
||||||
ubyteArrayOf(0U, 1U, 2U, 3U).toTypedArray(),
|
ubyteArrayOf(0U, 1U, 2U, 3U),
|
||||||
ubyteArrayOf(0U, 1U, 2U, 3U).toTypedArray(),
|
ubyteArrayOf(0U, 1U, 2U, 3U),
|
||||||
ubyteArrayOf(0U, 1U, 2U, 3U).toTypedArray()
|
ubyteArrayOf(0U, 1U, 2U, 3U)
|
||||||
)
|
)
|
||||||
val expectedState = arrayOf(
|
val expectedState = arrayOf(
|
||||||
ubyteArrayOf(0U, 1U, 2U, 3U).toTypedArray(),
|
ubyteArrayOf(0U, 1U, 2U, 3U),
|
||||||
ubyteArrayOf(1U, 2U, 3U, 0U).toTypedArray(),
|
ubyteArrayOf(1U, 2U, 3U, 0U),
|
||||||
ubyteArrayOf(2U, 3U, 0U, 1U).toTypedArray(),
|
ubyteArrayOf(2U, 3U, 0U, 1U),
|
||||||
ubyteArrayOf(3U, 0U, 1U, 2U).toTypedArray()
|
ubyteArrayOf(3U, 0U, 1U, 2U)
|
||||||
)
|
)
|
||||||
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
|
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
|
||||||
fakeState.copyInto(aes.state)
|
fakeState.copyInto(aes.state)
|
||||||
@ -76,17 +76,17 @@ class AesTest {
|
|||||||
fun testMixColumns() {
|
fun testMixColumns() {
|
||||||
//Test vectors from wikipedia
|
//Test vectors from wikipedia
|
||||||
val fakeState = arrayOf(
|
val fakeState = arrayOf(
|
||||||
ubyteArrayOf(0xdbU, 0xf2U, 0x01U, 0xc6U).toTypedArray(),
|
ubyteArrayOf(0xdbU, 0xf2U, 0x01U, 0xc6U),
|
||||||
ubyteArrayOf(0x13U, 0x0aU, 0x01U, 0xc6U).toTypedArray(),
|
ubyteArrayOf(0x13U, 0x0aU, 0x01U, 0xc6U),
|
||||||
ubyteArrayOf(0x53U, 0x22U, 0x01U, 0xc6U).toTypedArray(),
|
ubyteArrayOf(0x53U, 0x22U, 0x01U, 0xc6U),
|
||||||
ubyteArrayOf(0x45U, 0x5cU, 0x01U, 0xc6U).toTypedArray()
|
ubyteArrayOf(0x45U, 0x5cU, 0x01U, 0xc6U)
|
||||||
)
|
)
|
||||||
|
|
||||||
val expectedState = arrayOf(
|
val expectedState = arrayOf(
|
||||||
ubyteArrayOf(0x8eU, 0x9fU, 0x01U, 0xc6U).toTypedArray(),
|
ubyteArrayOf(0x8eU, 0x9fU, 0x01U, 0xc6U),
|
||||||
ubyteArrayOf(0x4dU, 0xdcU, 0x01U, 0xc6U).toTypedArray(),
|
ubyteArrayOf(0x4dU, 0xdcU, 0x01U, 0xc6U),
|
||||||
ubyteArrayOf(0xa1U, 0x58U, 0x01U, 0xc6U).toTypedArray(),
|
ubyteArrayOf(0xa1U, 0x58U, 0x01U, 0xc6U),
|
||||||
ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U).toTypedArray()
|
ubyteArrayOf(0xbcU, 0x9dU, 0x01U, 0xc6U)
|
||||||
)
|
)
|
||||||
|
|
||||||
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
|
val aes = Aes(AesKey.Aes128Key(irrelevantKey), irrelevantInput)
|
||||||
@ -183,10 +183,10 @@ class AesTest {
|
|||||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||||
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
|
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
|
||||||
|
|
||||||
val aes = Aes(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
val aes = Aes(AesKey.Aes128Key(key), input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
val result = aes.encrypt()
|
val result = aes.encrypt()
|
||||||
assertTrue {
|
assertTrue {
|
||||||
result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
result.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,11 +196,11 @@ class AesTest {
|
|||||||
val input = "3243f6a8885a308d313198a2e0370734"
|
val input = "3243f6a8885a308d313198a2e0370734"
|
||||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||||
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
|
val expectedResult = "3925841d02dc09fbdc118597196a0b32"
|
||||||
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()
|
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
|
||||||
val aes = Aes(AesKey.Aes128Key(key), original)
|
val aes = Aes(AesKey.Aes128Key(key), original)
|
||||||
val encrypted = aes.encrypt()
|
val encrypted = aes.encrypt()
|
||||||
assertTrue {
|
assertTrue {
|
||||||
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
}
|
}
|
||||||
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
|
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
|
||||||
|
|
||||||
@ -210,57 +210,57 @@ class AesTest {
|
|||||||
val input = "00112233445566778899aabbccddeeff"
|
val input = "00112233445566778899aabbccddeeff"
|
||||||
val key = "000102030405060708090a0b0c0d0e0f"
|
val key = "000102030405060708090a0b0c0d0e0f"
|
||||||
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
|
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
|
||||||
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()
|
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
|
||||||
val aes = Aes(AesKey.Aes128Key(key), original)
|
val aes = Aes(AesKey.Aes128Key(key), original)
|
||||||
val encrypted = aes.encrypt()
|
val encrypted = aes.encrypt()
|
||||||
assertTrue {
|
assertTrue {
|
||||||
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
}
|
}
|
||||||
val aesDec = Aes(AesKey.Aes128Key(key), encrypted)
|
val aesDec = Aes(AesKey.Aes128Key(key), encrypted)
|
||||||
val decrypted = aesDec.decrypt()
|
val decrypted = aesDec.decrypt()
|
||||||
assertTrue {
|
assertTrue {
|
||||||
aesDec.expandedKey.contentDeepEquals(aes.expandedKey)
|
aesDec.expandedKey.contentDeepEquals(aes.expandedKey)
|
||||||
}
|
}
|
||||||
decrypted.contentDeepEquals(original)
|
decrypted.contentEquals(original)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
val input = "00112233445566778899aabbccddeeff"
|
val input = "00112233445566778899aabbccddeeff"
|
||||||
val key = "000102030405060708090a0b0c0d0e0f"
|
val key = "000102030405060708090a0b0c0d0e0f"
|
||||||
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
|
val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a"
|
||||||
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()
|
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
|
||||||
val encrypted = Aes.encrypt(AesKey.Aes128Key(key), original)
|
val encrypted = Aes.encrypt(AesKey.Aes128Key(key), original)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
}
|
}
|
||||||
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
|
val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted)
|
||||||
decrypted.contentDeepEquals(original)
|
decrypted.contentEquals(original)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
val input = "00112233445566778899aabbccddeeff"
|
val input = "00112233445566778899aabbccddeeff"
|
||||||
val key = "000102030405060708090a0b0c0d0e0f1011121314151617"
|
val key = "000102030405060708090a0b0c0d0e0f1011121314151617"
|
||||||
val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191"
|
val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191"
|
||||||
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()
|
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
|
||||||
val encrypted = Aes.encrypt(AesKey.Aes192Key(key), original)
|
val encrypted = Aes.encrypt(AesKey.Aes192Key(key), original)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
}
|
}
|
||||||
val decrypted = Aes.decrypt(AesKey.Aes192Key(key), encrypted)
|
val decrypted = Aes.decrypt(AesKey.Aes192Key(key), encrypted)
|
||||||
decrypted.contentDeepEquals(original)
|
decrypted.contentEquals(original)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
val input = "00112233445566778899aabbccddeeff"
|
val input = "00112233445566778899aabbccddeeff"
|
||||||
val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
||||||
val expectedResult = "8ea2b7ca516745bfeafc49904b496089"
|
val expectedResult = "8ea2b7ca516745bfeafc49904b496089"
|
||||||
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()
|
val original = input.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray()
|
||||||
val encrypted = Aes.encrypt(AesKey.Aes256Key(key), original)
|
val encrypted = Aes.encrypt(AesKey.Aes256Key(key), original)
|
||||||
assertTrue {
|
assertTrue {
|
||||||
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray())
|
encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toUByteArray())
|
||||||
}
|
}
|
||||||
val decrypted = Aes.decrypt(AesKey.Aes256Key(key), encrypted)
|
val decrypted = Aes.decrypt(AesKey.Aes256Key(key), encrypted)
|
||||||
decrypted.contentDeepEquals(original)
|
decrypted.contentEquals(original)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,10 @@ actual object SRNG {
|
|||||||
actual fun getRandomBytes(amount: Int): UByteArray {
|
actual fun getRandomBytes(amount: Int): UByteArray {
|
||||||
val runningOnNode = jsTypeOf(window) == "undefined"
|
val runningOnNode = jsTypeOf(window) == "undefined"
|
||||||
val randomBytes = if (runningOnNode) {
|
val randomBytes = if (runningOnNode) {
|
||||||
|
println("Running on node")
|
||||||
js("require('crypto')").randomBytes(amount).toJSON().data
|
js("require('crypto')").randomBytes(amount).toJSON().data
|
||||||
} else {
|
} else {
|
||||||
|
println("Running in browser")
|
||||||
js(
|
js(
|
||||||
"""
|
"""
|
||||||
var randomArray = new Uint8Array(amount);
|
var randomArray = new Uint8Array(amount);
|
||||||
@ -41,7 +43,21 @@ actual object SRNG {
|
|||||||
var randomArrayResult = js("Array.prototype.slice.call(randomArray);")
|
var randomArrayResult = js("Array.prototype.slice.call(randomArray);")
|
||||||
randomArrayResult
|
randomArrayResult
|
||||||
}
|
}
|
||||||
|
println("Random bytes: $randomBytes")
|
||||||
return randomBytes as UByteArray
|
print("Byte at ${randomBytes[0]}")
|
||||||
|
val randomBytesUByteArray = UByteArray(amount) {
|
||||||
|
0U
|
||||||
}
|
}
|
||||||
|
for (i in 0 until amount) {
|
||||||
|
println("Setting ${randomBytes[i]}")
|
||||||
|
js("""
|
||||||
|
randomBytesUByteArray[i] = randomBytes[i]
|
||||||
|
""")
|
||||||
|
println("Set value ${randomBytesUByteArray[i]}")
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomBytesUByteArray
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -31,6 +31,14 @@ class SRNGJsTest {
|
|||||||
fun testJsSrng() {
|
fun testJsSrng() {
|
||||||
val bytes1 = SRNG.getRandomBytes(10)
|
val bytes1 = SRNG.getRandomBytes(10)
|
||||||
val bytes2 = SRNG.getRandomBytes(10)
|
val bytes2 = SRNG.getRandomBytes(10)
|
||||||
|
println("BYTES1")
|
||||||
|
bytes1.forEach {
|
||||||
|
print(it.toString(16).padStart(2, '0'))
|
||||||
|
}
|
||||||
|
println("BYTES2")
|
||||||
|
bytes2.forEach {
|
||||||
|
print(it.toString(16).padStart(2, '0'))
|
||||||
|
}
|
||||||
assertTrue {
|
assertTrue {
|
||||||
!bytes1.contentEquals(bytes2) &&
|
!bytes1.contentEquals(bytes2) &&
|
||||||
bytes1.size == 10 &&
|
bytes1.size == 10 &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user