Fix missing leading zeroes in counter

This commit is contained in:
Ugljesa Jovanovic 2019-09-24 00:52:49 +02:00 committed by Ugljesa Jovanovic
parent ec3b87db49
commit d8ea3d2693
No known key found for this signature in database
GPG Key ID: 33A5F353387711A5
7 changed files with 63 additions and 32 deletions

View File

@ -149,8 +149,6 @@ kotlin {
} }
val nativeMain by creating { val nativeMain by creating {
dependsOn(commonMain) dependsOn(commonMain)
dependencies {
}
} }
val nativeTest by creating { val nativeTest by creating {

View File

@ -64,12 +64,6 @@ internal class Aes internal constructor(val aesKey: AesKey, val input: Array<UBy
} }
init {
if (input.size != 16) {
throw RuntimeException("Invalid input size ${input.size}")
}
}
val state: Array<Array<UByte>> = (0 until 4).map { outerCounter -> val state: Array<Array<UByte>> = (0 until 4).map { outerCounter ->
Array<UByte>(4) { innerCounter -> input[innerCounter * 4 + outerCounter] } Array<UByte>(4) { innerCounter -> input[innerCounter * 4 + outerCounter] }
}.toTypedArray() }.toTypedArray()

View File

@ -97,7 +97,11 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
var currentOutput: Array<UByte> = arrayOf() var currentOutput: Array<UByte> = arrayOf()
var previousEncrypted: Array<UByte> = arrayOf() var previousEncrypted: Array<UByte> = arrayOf()
val iv = initializationVector ?: SRNG.getRandomBytes(16) val initVector = if (initializationVector.isNullOrEmpty()) {
SRNG.getRandomBytes(16)
} else {
initializationVector
}
val output = MutableList<Array<UByte>>(0) { arrayOf() } val output = MutableList<Array<UByte>>(0) { arrayOf() }
@ -158,7 +162,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(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
iv initVector
) )
} }
@ -193,7 +197,8 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
return when (mode) { return when (mode) {
Mode.ENCRYPT -> { Mode.ENCRYPT -> {
currentOutput = if (currentOutput.isEmpty()) { currentOutput = if (currentOutput.isEmpty()) {
Aes.encrypt(aesKey, data xor iv) println("IV: $initVector")
Aes.encrypt(aesKey, data xor initVector)
} else { } else {
Aes.encrypt(aesKey, data xor currentOutput) Aes.encrypt(aesKey, data xor currentOutput)
} }
@ -201,7 +206,7 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
} }
Mode.DECRYPT -> { Mode.DECRYPT -> {
if (currentOutput.isEmpty()) { if (currentOutput.isEmpty()) {
currentOutput = Aes.decrypt(aesKey, data) xor iv currentOutput = Aes.decrypt(aesKey, data) xor initVector
} else { } else {
currentOutput = Aes.decrypt(aesKey, data) xor previousEncrypted currentOutput = Aes.decrypt(aesKey, data) xor previousEncrypted
} }

View File

@ -78,7 +78,11 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
var currentOutput: Array<UByte> = arrayOf() var currentOutput: Array<UByte> = arrayOf()
var previousEncrypted: Array<UByte> = arrayOf() var previousEncrypted: Array<UByte> = arrayOf()
val counterStart = initialCounter ?: SRNG.getRandomBytes(16) val counterStart = if (initialCounter.isNullOrEmpty()) {
SRNG.getRandomBytes(16)
} else {
initialCounter
}
var blockCounter = modularCreator.fromBigInteger(BigInteger.fromUByteArray(counterStart, Endianness.BIG)) var blockCounter = modularCreator.fromBigInteger(BigInteger.fromUByteArray(counterStart, Endianness.BIG))
val output = MutableList<Array<UByte>>(0) { arrayOf() } val output = MutableList<Array<UByte>>(0) { arrayOf() }
@ -158,17 +162,29 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
} }
private fun consumeBlock(data: Array<UByte>, blockCount: ModularBigInteger): Array<UByte> { private fun consumeBlock(data: Array<UByte>, blockCount: ModularBigInteger): Array<UByte> {
val blockCountAsByteArray = blockCount.toUByteArray(Endianness.BIG).expandCounterTo16Bytes()
return when (mode) { return when (mode) {
Mode.ENCRYPT -> { Mode.ENCRYPT -> {
Aes.encrypt(aesKey, blockCount.toUByteArray(Endianness.BIG)) xor data Aes.encrypt(aesKey, blockCountAsByteArray) xor data
} }
Mode.DECRYPT -> { Mode.DECRYPT -> {
Aes.encrypt(aesKey, blockCount.toUByteArray(Endianness.BIG)) xor data Aes.encrypt(aesKey, blockCountAsByteArray) xor data
} }
} }
} }
private fun Array<UByte>.expandCounterTo16Bytes() : Array<UByte> {
return if (this.size < 16) {
println("Expanding")
val diff = 16 - this.size
val pad = Array<UByte>(diff) { 0U }
pad + this
} else {
this
}
}
} }
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes

View File

@ -46,6 +46,12 @@ class AesCbcTest {
iv == encrypted.initilizationVector.toHexString() iv == encrypted.initilizationVector.toHexString()
} }
}
@Test
fun testEncryptionApi() {
assertTrue { assertTrue {
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e" val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
val key = AesKey.Aes128Key(keyString) val key = AesKey.Aes128Key(keyString)
@ -60,8 +66,6 @@ class AesCbcTest {
) )
plainText == decrypted.toHexString() plainText == decrypted.toHexString()
} }
} }
@Test @Test
@ -80,6 +84,12 @@ class AesCbcTest {
expectedPlainText == decrypted.toHexString() expectedPlainText == decrypted.toHexString()
} }
}
@Test
fun testDecryptionApi() {
assertTrue { assertTrue {
val key = "4278b840fb44aaa757c1bf04acbe1a3e" val key = "4278b840fb44aaa757c1bf04acbe1a3e"
val iv = "57f02a5c5339daeb0a2908a06ac6393f" val iv = "57f02a5c5339daeb0a2908a06ac6393f"
@ -90,8 +100,8 @@ class AesCbcTest {
expectedPlainText == decrypted.toHexString() expectedPlainText == decrypted.toHexString()
} }
} }
} }

View File

@ -49,7 +49,10 @@ class AesCtrTest {
ic == encrypted.initialCounter.toHexString() ic == encrypted.initialCounter.toHexString()
} }
assertTrue { }
@Test
fun testEncryptionApi() {
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e" val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
val key = AesKey.Aes128Key(keyString) val key = AesKey.Aes128Key(keyString)
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710" val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
@ -60,9 +63,9 @@ class AesCtrTest {
encryptedDataAndInitializationVector.encryptedData, encryptedDataAndInitializationVector.encryptedData,
encryptedDataAndInitializationVector.initialCounter encryptedDataAndInitializationVector.initialCounter
) )
assertTrue {
plainText == decrypted.toHexString() plainText == decrypted.toHexString()
} }
} }
@Test @Test
@ -81,6 +84,12 @@ class AesCtrTest {
expectedPlainText == decrypted.toHexString() expectedPlainText == decrypted.toHexString()
} }
}
@Test
fun testCtrDecryptionApi() {
assertTrue { assertTrue {
val key = "2b7e151628aed2a6abf7158809cf4f3c" val key = "2b7e151628aed2a6abf7158809cf4f3c"
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff" val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
@ -92,6 +101,5 @@ class AesCtrTest {
println("Decrypted: ${decrypted.toHexString()}") println("Decrypted: ${decrypted.toHexString()}")
expectedPlainText == decrypted.toHexString() expectedPlainText == decrypted.toHexString()
} }
} }
} }

View File

@ -31,6 +31,6 @@ actual object SRNG {
// } else { // } else {
// throw RuntimeException("Secure random not supported yet for non-nodejs environment") // throw RuntimeException("Secure random not supported yet for non-nodejs environment")
// } // }
return arrayOf((counter++).toUByte()) // TODO Wow. Such random. Very entropy. return Array<UByte>(amount) { (counter++).toUByte() } // TODO Wow. Such random. Very entropy.
} }
} }