diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt new file mode 100644 index 0000000..174801d --- /dev/null +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Ugljesa Jovanovic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ionspin.kotlin.crypto + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Sep-2019 + */ +expect object SRNG { + fun getRandomBytes(amount : Int) : Array +} \ No newline at end of file diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Util.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Util.kt index 0a59b5f..64e3783 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Util.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/Util.kt @@ -63,4 +63,12 @@ infix fun UInt.rotateRight(places: Int): UInt { @ExperimentalUnsignedTypes infix fun ULong.rotateRight(places: Int): ULong { return (this shr places) xor (this shl (64 - places)) +} + +@ExperimentalUnsignedTypes +infix fun Array.xor(other : Array) : Array { + if (this.size != other.size) { + throw RuntimeException("Operands of different sizes are not supported yet") + } + return this.copyOf().mapIndexed { index, it -> it xor other[index] }.toTypedArray() } \ No newline at end of file diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/Aes.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/Aes.kt index aa18506..427cc74 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/Aes.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/Aes.kt @@ -6,6 +6,8 @@ package com.ionspin.kotlin.crypto.symmetric @ExperimentalUnsignedTypes internal class Aes internal constructor(val aesKey: AesKey, val input: Array) { companion object { + private val debug = false + private val sBox: UByteArray = ubyteArrayOf( // @formatter:off @@ -317,14 +319,22 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array>) { + private fun printState(specific : Array>) { + if (!debug) { + return + } println() specific.forEach { println(it.joinToString(separator = " ") { it.toString(16) }) diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbc.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbc.kt new file mode 100644 index 0000000..cdbfd30 --- /dev/null +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbc.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2019 Ugljesa Jovanovic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ionspin.kotlin.crypto.symmetric + +import com.ionspin.kotlin.crypto.SRNG +import com.ionspin.kotlin.crypto.xor + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Sep-2019 + */ +@ExperimentalUnsignedTypes +class AesCbc (val aesKey: AesKey) { + + companion object { + val BLOCK_BYTES = 16 + } + + var currentOutput : Array = arrayOf() + val iv = SRNG.getRandomBytes(16) + + val output = MutableList>(0) { arrayOf() } + + val buffer : Array = UByteArray(16) { 0U }.toTypedArray() + var bufferCounter = 0 + + +// fun addData(data : UByteArray) { +// //Padding +// when { +// bufferCounter + data.size < BLOCK_BYTES -> appendToBuffer(data, bufferCounter) +// bufferCounter + data.size >= BLOCK_BYTES -> { +// val chunked = data.chunked(BLOCK_BYTES) +// chunked.forEach { chunk -> +// if (bufferCounter + chunk.size < BLOCK_BYTES) { +// appendToBuffer(chunk, bufferCounter) +// } else { +// chunk.copyInto( +// destination = buffer, +// destinationOffset = bufferCounter, +// startIndex = 0, +// endIndex = BLOCK_BYTES - bufferCounter +// ) +// counter += BLOCK_BYTES +// consumeBlock(buffer) +// buffer = Array(BLOCK_BYTES) { +// when (it) { +// in (0 until (chunk.size - (BLOCK_BYTES - bufferCounter))) -> { +// chunk[it + (BLOCK_BYTES - bufferCounter)] +// } +// else -> { +// 0U +// } +// } +// +// } +// bufferCounter = chunk.size - (BLOCK_BYTES - bufferCounter) +// } +// } +// +// } +// data.size < 16 -> { +// val paddingSize = 16 - data.size +// val padding = UByteArray(16 - data.size) { paddingSize.toUByte() } +// output += processBlock(data + padding) +// } +// data.size == 16 -> { +// +// } +// data.size > 16 -> { +// +// } +// } +// +// if (data.size < 16) { +// +// } +// +// } + + private fun appendToBuffer(array: Array, start: Int) { + array.copyInto(destination = buffer, destinationOffset = start, startIndex = 0, endIndex = array.size) + bufferCounter += array.size + } + + private fun processBlock(data : Array) : Array { + if (currentOutput.isEmpty()) { + currentOutput = Aes.encrypt(aesKey, data xor iv) + } else { + currentOutput = Aes.encrypt(aesKey, data xor currentOutput) + } + return currentOutput + } + +} \ No newline at end of file diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesTest.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesTest.kt index 8f4e77e..1ac2f90 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesTest.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesTest.kt @@ -191,42 +191,79 @@ class AesTest { } @Test - fun testDecryption() { - val input = "3243f6a8885a308d313198a2e0370734" - val key = "2b7e151628aed2a6abf7158809cf4f3c" - val expectedResult = "3925841d02dc09fbdc118597196a0b32" - val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() - val aes = Aes(AesKey.Aes128Key(key), original) - val encrypted = aes.encrypt() - assertTrue { - encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) - } - val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted) + fun testEncryptionAndDecryption() { assertTrue { + val input = "3243f6a8885a308d313198a2e0370734" + val key = "2b7e151628aed2a6abf7158809cf4f3c" + val expectedResult = "3925841d02dc09fbdc118597196a0b32" + val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() + val aes = Aes(AesKey.Aes128Key(key), original) + val encrypted = aes.encrypt() + assertTrue { + encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) + } + val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted) + decrypted.contentEquals(original) } - } + assertTrue { + val input = "00112233445566778899aabbccddeeff" + val key = "000102030405060708090a0b0c0d0e0f" + val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a" + val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() + val aes = Aes(AesKey.Aes128Key(key), original) + val encrypted = aes.encrypt() + assertTrue { + encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) + } + val aesDec = Aes(AesKey.Aes128Key(key), encrypted) + val decrypted = aesDec.decrypt() + assertTrue { + aesDec.expandedKey.contentDeepEquals(aes.expandedKey) + } + decrypted.contentDeepEquals(original) + } - @Test - fun testDecryption2() { - val input = "00112233445566778899aabbccddeeff" - val key = "000102030405060708090a0b0c0d0e0f" - val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a" - val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() - val aes = Aes(AesKey.Aes128Key(key), original) - val encrypted = aes.encrypt() assertTrue { - encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) + val input = "00112233445566778899aabbccddeeff" + val key = "000102030405060708090a0b0c0d0e0f" + val expectedResult = "69c4e0d86a7b0430d8cdb78070b4c55a" + val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() + val encrypted = Aes.encrypt(AesKey.Aes128Key(key), original) + assertTrue { + encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) + } + val decrypted = Aes.decrypt(AesKey.Aes128Key(key), encrypted) + decrypted.contentDeepEquals(original) } - val aesDec = Aes(AesKey.Aes128Key(key), encrypted) - val decrypted = aesDec.decrypt() + assertTrue { - aesDec.expandedKey.contentDeepEquals(aes.expandedKey) + val input = "00112233445566778899aabbccddeeff" + val key = "000102030405060708090a0b0c0d0e0f1011121314151617" + val expectedResult = "dda97ca4864cdfe06eaf70a0ec0d7191" + val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() + val encrypted = Aes.encrypt(AesKey.Aes192Key(key), original) + assertTrue { + encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) + } + val decrypted = Aes.decrypt(AesKey.Aes192Key(key), encrypted) + decrypted.contentDeepEquals(original) } + assertTrue { + val input = "00112233445566778899aabbccddeeff" + val key = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + val expectedResult = "8ea2b7ca516745bfeafc49904b496089" + val original = input.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray() + val encrypted = Aes.encrypt(AesKey.Aes256Key(key), original) + assertTrue { + encrypted.contentEquals(expectedResult.chunked(2).map { it.toInt(16).toUByte() }.toTypedArray()) + } + val decrypted = Aes.decrypt(AesKey.Aes256Key(key), encrypted) decrypted.contentDeepEquals(original) } } + } \ No newline at end of file diff --git a/multiplatform-crypto/src/iosCommonMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt b/multiplatform-crypto/src/iosCommonMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt new file mode 100644 index 0000000..8e8bbd7 --- /dev/null +++ b/multiplatform-crypto/src/iosCommonMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Ugljesa Jovanovic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ionspin.kotlin.crypto + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Sep-2019 + */ +actual object SRNG { + actual fun getRandomBytes(amount: Int): Array { + TODO("not implemented yet") + } +} \ No newline at end of file diff --git a/multiplatform-crypto/src/jsMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt b/multiplatform-crypto/src/jsMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt new file mode 100644 index 0000000..8e8bbd7 --- /dev/null +++ b/multiplatform-crypto/src/jsMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Ugljesa Jovanovic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ionspin.kotlin.crypto + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Sep-2019 + */ +actual object SRNG { + actual fun getRandomBytes(amount: Int): Array { + TODO("not implemented yet") + } +} \ No newline at end of file diff --git a/multiplatform-crypto/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt b/multiplatform-crypto/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt new file mode 100644 index 0000000..8e8bbd7 --- /dev/null +++ b/multiplatform-crypto/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Ugljesa Jovanovic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ionspin.kotlin.crypto + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Sep-2019 + */ +actual object SRNG { + actual fun getRandomBytes(amount: Int): Array { + TODO("not implemented yet") + } +} \ No newline at end of file diff --git a/multiplatform-crypto/src/nativeMain/kotlin/com/ionspin/kotlin/bignum/integer/Placeholder b/multiplatform-crypto/src/nativeMain/kotlin/com/ionspin/kotlin/bignum/integer/Placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/multiplatform-crypto/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt b/multiplatform-crypto/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt new file mode 100644 index 0000000..8e8bbd7 --- /dev/null +++ b/multiplatform-crypto/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/SRNG.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2019 Ugljesa Jovanovic + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ionspin.kotlin.crypto + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Sep-2019 + */ +actual object SRNG { + actual fun getRandomBytes(amount: Int): Array { + TODO("not implemented yet") + } +} \ No newline at end of file