Aes implemented
This commit is contained in:
parent
69c81ec8e9
commit
ec3b87db49
58
README.md
58
README.md
@ -7,6 +7,9 @@ Kotlin Multiplatform Crypto is a library for various cryptographic applications.
|
||||
|
||||
This is an extremely early release, currently only consisting of Blake2b and SHA256 and 512.
|
||||
|
||||
API is very opinionated, ment to be used on both encrypting and decrypting side. The idea is that API leaves less room for
|
||||
errors when using it.
|
||||
|
||||
## Notes & Roadmap
|
||||
|
||||
**The API will move fast and break often until v1.0**
|
||||
@ -28,8 +31,6 @@ No.
|
||||
This is an experimental implementation, mostly for expanding personal understanding of cryptography.
|
||||
It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be secure.
|
||||
|
||||
## Supported
|
||||
|
||||
## Hashing functions
|
||||
* Blake2b
|
||||
* SHA512
|
||||
@ -37,6 +38,7 @@ It's not peer reviewed, not guaranteed to be bug free, and not guaranteed to be
|
||||
|
||||
## Symmetric cipher
|
||||
* AES
|
||||
* Modes: CBC, CTR
|
||||
|
||||
More to come.
|
||||
|
||||
@ -129,6 +131,58 @@ val sha512 = Sha512()
|
||||
sha512.update("abc")
|
||||
val result = sha512.digest()
|
||||
```
|
||||
### Symmetric encryption
|
||||
|
||||
#### AES
|
||||
|
||||
Aes is available with CBC and CTR mode through `AesCbc` and `AesCtr` classes/objects.
|
||||
Similarly to hashes you can either use stateless or updateable version.
|
||||
|
||||
Initialization vector, or counter states are chosen by the SDK automaticaly, and returned alongside encrypted data
|
||||
|
||||
##### Stateless AesCbc and AesCtr
|
||||
|
||||
AesCtr
|
||||
|
||||
```kotlin
|
||||
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val key = AesKey.Aes128Key(keyString)
|
||||
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
|
||||
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray())
|
||||
val decrypted = AesCtr.decrypt(
|
||||
key,
|
||||
encryptedDataAndInitializationVector.encryptedData,
|
||||
encryptedDataAndInitializationVector.initialCounter
|
||||
)
|
||||
plainText == decrypted.toHexString()
|
||||
```
|
||||
|
||||
AesCbc
|
||||
|
||||
```kotlin
|
||||
|
||||
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val key = AesKey.Aes128Key(keyString)
|
||||
|
||||
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
|
||||
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray())
|
||||
val decrypted = AesCbc.decrypt(
|
||||
key,
|
||||
encryptedDataAndInitializationVector.encryptedData,
|
||||
encryptedDataAndInitializationVector.initilizationVector
|
||||
)
|
||||
plainText == decrypted.toHexString()
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,6 +21,12 @@ import com.ionspin.kotlin.crypto.chunked
|
||||
import com.ionspin.kotlin.crypto.xor
|
||||
|
||||
/**
|
||||
* Advanced encryption standard with cipher block chaining and PKCS #5
|
||||
*
|
||||
* For bulk encryption/decryption use [AesCbc.encrypt] and [AesCbc.decrypt]
|
||||
*
|
||||
* To get an instance of AesCbc and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
|
||||
*
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 21-Sep-2019
|
||||
@ -30,13 +36,39 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
||||
|
||||
companion object {
|
||||
const val BLOCK_BYTES = 16
|
||||
/**
|
||||
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
|
||||
* data call [encrypt]
|
||||
*/
|
||||
fun createEncryptor(aesKey: AesKey) : AesCbc {
|
||||
return AesCbc(aesKey, Mode.ENCRYPT)
|
||||
}
|
||||
/**
|
||||
* Creates and returns AesCbc instance that can be fed data using [addData]. Once you have submitted all
|
||||
* data call [decrypt]
|
||||
*/
|
||||
fun createDecryptor(aesKey : AesKey) : AesCbc {
|
||||
return AesCbc(aesKey, Mode.DECRYPT)
|
||||
}
|
||||
|
||||
fun encrypt(aesKey: AesKey, data: Array<UByte>): Array<UByte> {
|
||||
/**
|
||||
* Bulk encryption, returns encrypted data and a random initialization vector
|
||||
*/
|
||||
fun encrypt(aesKey: AesKey, data: Array<UByte>): EncryptedDataAndInitializationVector {
|
||||
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
|
||||
aesCbc.addData(data)
|
||||
return aesCbc.encrypt()
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk decryption, returns decrypted data
|
||||
*/
|
||||
fun decrypt(aesKey: AesKey, data: Array<UByte>, initialCounter: Array<UByte>? = null): Array<UByte> {
|
||||
val aesCbc = AesCbc(aesKey, Mode.DECRYPT, initialCounter)
|
||||
aesCbc.addData(data)
|
||||
return aesCbc.decrypt()
|
||||
}
|
||||
|
||||
private fun padToBlock(unpadded: Array<UByte>): Array<UByte> {
|
||||
val paddingSize = 16 - unpadded.size
|
||||
if (unpadded.size == BLOCK_BYTES) {
|
||||
@ -109,7 +141,11 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
||||
|
||||
}
|
||||
|
||||
fun encrypt(): Array<UByte> {
|
||||
/**
|
||||
* Encrypt fed data and return it alongside the randomly chosen initialization vector
|
||||
* @return Encrypted data and initialization vector
|
||||
*/
|
||||
fun encrypt(): EncryptedDataAndInitializationVector {
|
||||
if (bufferCounter > 0) {
|
||||
val lastBlockPadded = padToBlock(buffer)
|
||||
if (lastBlockPadded.size > BLOCK_BYTES) {
|
||||
@ -120,9 +156,16 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
||||
output += consumeBlock(lastBlockPadded)
|
||||
}
|
||||
}
|
||||
return output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes }
|
||||
return EncryptedDataAndInitializationVector(
|
||||
output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
|
||||
iv
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt data
|
||||
* @return Decrypted data
|
||||
*/
|
||||
fun decrypt(): Array<UByte> {
|
||||
val removePaddingCount = output.last().last()
|
||||
|
||||
@ -169,4 +212,25 @@ class AesCbc internal constructor(val aesKey: AesKey, val mode: Mode, initializa
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
data class EncryptedDataAndInitializationVector(val encryptedData : Array<UByte>, val initilizationVector : Array<UByte>) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as EncryptedDataAndInitializationVector
|
||||
|
||||
if (!encryptedData.contentEquals(other.encryptedData)) return false
|
||||
if (!initilizationVector.contentEquals(other.initilizationVector)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = encryptedData.contentHashCode()
|
||||
result = 31 * result + initilizationVector.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
@ -21,9 +21,17 @@ import com.ionspin.kotlin.bignum.integer.BigInteger
|
||||
import com.ionspin.kotlin.bignum.modular.ModularBigInteger
|
||||
import com.ionspin.kotlin.crypto.SRNG
|
||||
import com.ionspin.kotlin.crypto.chunked
|
||||
import com.ionspin.kotlin.crypto.symmetric.AesCtr.Companion.encrypt
|
||||
import com.ionspin.kotlin.crypto.xor
|
||||
|
||||
/**
|
||||
*
|
||||
* Advanced encryption standard with counter mode
|
||||
*
|
||||
* For bulk encryption/decryption use [AesCtr.encrypt] and [AesCtr.decrypt]
|
||||
*
|
||||
* To get an instance of AesCtr and then feed it data sequentially with [addData] use [createEncryptor] and [createDecryptor]
|
||||
*
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 22-Sep-2019
|
||||
@ -34,38 +42,38 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
||||
companion object {
|
||||
const val BLOCK_BYTES = 16
|
||||
|
||||
val modularCreator = ModularBigInteger.creatorForModulo(BigInteger.ONE.shl(129) - 1)
|
||||
|
||||
fun encrypt(aesKey: AesKey, data: Array<UByte>): Array<UByte> {
|
||||
val aesCbc = AesCbc(aesKey, Mode.ENCRYPT)
|
||||
aesCbc.addData(data)
|
||||
return aesCbc.encrypt()
|
||||
val modularCreator = ModularBigInteger.creatorForModulo(BigInteger.ONE.shl(128) - 1)
|
||||
/**
|
||||
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
|
||||
* data call [encrypt]
|
||||
*/
|
||||
fun createEncryptor(aesKey: AesKey) : AesCtr {
|
||||
return AesCtr(aesKey, Mode.ENCRYPT)
|
||||
}
|
||||
/**
|
||||
* Creates and returns AesCtr instance that can be fed data using [addData]. Once you have submitted all
|
||||
* data call [decrypt]
|
||||
*/
|
||||
fun createDecryptor(aesKey : AesKey) : AesCtr {
|
||||
return AesCtr(aesKey, Mode.DECRYPT)
|
||||
}
|
||||
/**
|
||||
* Bulk encryption, returns encrypted data and a random initial counter
|
||||
*/
|
||||
fun encrypt(aesKey: AesKey, data: Array<UByte>): EncryptedDataAndInitialCounter {
|
||||
val aesCtr = AesCtr(aesKey, Mode.ENCRYPT)
|
||||
aesCtr.addData(data)
|
||||
return aesCtr.encrypt()
|
||||
}
|
||||
/**
|
||||
* Bulk decryption, returns decrypted data
|
||||
*/
|
||||
fun decrypt(aesKey: AesKey, data: Array<UByte>, initialCounter: Array<UByte>? = null): Array<UByte> {
|
||||
val aesCtr = AesCtr(aesKey, Mode.DECRYPT, initialCounter)
|
||||
aesCtr.addData(data)
|
||||
return aesCtr.decrypt()
|
||||
}
|
||||
|
||||
private fun padToBlock(unpadded: Array<UByte>): Array<UByte> {
|
||||
val paddingSize = 16 - unpadded.size
|
||||
if (unpadded.size == BLOCK_BYTES) {
|
||||
return unpadded
|
||||
}
|
||||
|
||||
if (unpadded.size == BLOCK_BYTES) {
|
||||
return Array(BLOCK_BYTES) {
|
||||
BLOCK_BYTES.toUByte()
|
||||
}
|
||||
}
|
||||
|
||||
if (unpadded.size > BLOCK_BYTES) {
|
||||
throw IllegalStateException("Block larger than 128 bytes")
|
||||
}
|
||||
|
||||
return Array(BLOCK_BYTES) {
|
||||
when (it) {
|
||||
in unpadded.indices -> unpadded[it]
|
||||
else -> paddingSize.toUByte()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var currentOutput: Array<UByte> = arrayOf()
|
||||
@ -115,34 +123,32 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun encrypt(): Array<UByte> {
|
||||
/**
|
||||
* Encrypt fed data and return it alongside the randomly chosen initial counter state
|
||||
* @return Encrypted data and initial counter state
|
||||
*/
|
||||
fun encrypt(): EncryptedDataAndInitialCounter {
|
||||
if (bufferCounter > 0) {
|
||||
val lastBlockPadded = padToBlock(buffer)
|
||||
if (lastBlockPadded.size > BLOCK_BYTES) {
|
||||
val chunks = lastBlockPadded.chunked(BLOCK_BYTES)
|
||||
output += consumeBlock(chunks[0], blockCounter)
|
||||
blockCounter += 1
|
||||
output += consumeBlock(chunks[1], blockCounter)
|
||||
} else {
|
||||
output += consumeBlock(lastBlockPadded, blockCounter)
|
||||
}
|
||||
output += consumeBlock(buffer, blockCounter)
|
||||
}
|
||||
return output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes }
|
||||
return EncryptedDataAndInitialCounter(
|
||||
output.reversed().foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc -> acc + arrayOfUBytes },
|
||||
counterStart
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt data
|
||||
* @return Decrypted data
|
||||
*/
|
||||
fun decrypt(): Array<UByte> {
|
||||
val removePaddingCount = output.last().last()
|
||||
val removedPadding = if (removePaddingCount > 0U && removePaddingCount < 16U) {
|
||||
output.last().dropLast(removePaddingCount.toInt() and 0x7F)
|
||||
} else {
|
||||
output.last().toList()
|
||||
if (bufferCounter > 0) {
|
||||
output += consumeBlock(buffer, blockCounter)
|
||||
}
|
||||
val preparedOutput = output.dropLast(1).toTypedArray() + removedPadding.toTypedArray()
|
||||
//JS compiler freaks out here if we don't supply exact type
|
||||
val reversed : List<Array<UByte>> = preparedOutput.reversed() as List<Array<UByte>>
|
||||
val folded : Array<UByte> = reversed.foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc ->
|
||||
acc + arrayOfUBytes }
|
||||
val reversed: List<Array<UByte>> = output.reversed() as List<Array<UByte>>
|
||||
val folded: Array<UByte> = reversed.foldRight(Array<UByte>(0) { 0U }) { arrayOfUBytes, acc ->
|
||||
acc + arrayOfUBytes
|
||||
}
|
||||
return folded
|
||||
}
|
||||
|
||||
@ -163,4 +169,25 @@ class AesCtr internal constructor(val aesKey: AesKey, val mode: Mode, initialCou
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
data class EncryptedDataAndInitialCounter(val encryptedData : Array<UByte>, val initialCounter : Array<UByte>) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as EncryptedDataAndInitializationVector
|
||||
|
||||
if (!encryptedData.contentEquals(other.encryptedData)) return false
|
||||
if (!initialCounter.contentEquals(other.initilizationVector)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = encryptedData.contentHashCode()
|
||||
result = 31 * result + initialCounter.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
@ -31,43 +31,67 @@ class AesCbcTest {
|
||||
|
||||
@Test
|
||||
fun testCbcEncryption() {
|
||||
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
|
||||
val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
|
||||
val aesCbc = AesCbc(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray())
|
||||
aesCbc.addData(plaintext.hexStringToUByteArray())
|
||||
val encrypted = aesCbc.encrypt()
|
||||
println("Encrypted: ${encrypted.toHexString()}")
|
||||
assertTrue {
|
||||
expectedCipherText == encrypted.toHexString()
|
||||
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
|
||||
val plaintext = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
val expectedCipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
|
||||
val aesCbc =
|
||||
AesCbc(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initializationVector = iv.hexStringToUByteArray())
|
||||
aesCbc.addData(plaintext.hexStringToUByteArray())
|
||||
val encrypted = aesCbc.encrypt()
|
||||
println("Encrypted: ${encrypted.encryptedData.toHexString()}")
|
||||
|
||||
expectedCipherText == encrypted.encryptedData.toHexString() &&
|
||||
iv == encrypted.initilizationVector.toHexString()
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val key = AesKey.Aes128Key(keyString)
|
||||
|
||||
val plainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
|
||||
val encryptedDataAndInitializationVector = AesCbc.encrypt(key, plainText.hexStringToUByteArray())
|
||||
val decrypted = AesCbc.decrypt(
|
||||
key,
|
||||
encryptedDataAndInitializationVector.encryptedData,
|
||||
encryptedDataAndInitializationVector.initilizationVector
|
||||
)
|
||||
plainText == decrypted.toHexString()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCbcDecryption() {
|
||||
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
|
||||
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
|
||||
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
val aesCbc = AesCbc(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray())
|
||||
aesCbc.addData(cipherText.hexStringToUByteArray())
|
||||
val decrypted = aesCbc.decrypt()
|
||||
println("Decrypted: ${decrypted.toHexString()}")
|
||||
assertTrue {
|
||||
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
|
||||
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
|
||||
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
val aesCbc =
|
||||
AesCbc(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray())
|
||||
aesCbc.addData(cipherText.hexStringToUByteArray())
|
||||
val decrypted = aesCbc.decrypt()
|
||||
println("Decrypted: ${decrypted.toHexString()}")
|
||||
|
||||
expectedPlainText == decrypted.toHexString()
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val key = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val iv = "57f02a5c5339daeb0a2908a06ac6393f"
|
||||
val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7"
|
||||
val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5"
|
||||
val decrypted = AesCbc.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray())
|
||||
println("Decrypted: ${decrypted.toHexString()}")
|
||||
|
||||
expectedPlainText == decrypted.toHexString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -31,45 +31,67 @@ class AesCtrTest {
|
||||
|
||||
@Test
|
||||
fun testCtrEncryption() {
|
||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
||||
val plaintext = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
val expectedCipherText = "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
|
||||
val aesCbc = AesCtr(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray())
|
||||
aesCbc.addData(
|
||||
plaintext.hexStringToUByteArray()
|
||||
)
|
||||
val encrypted = aesCbc.encrypt()
|
||||
println("Encrypted: ${encrypted.toHexString()}")
|
||||
assertTrue {
|
||||
expectedCipherText == encrypted.toHexString()
|
||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
||||
val plaintext =
|
||||
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
val expectedCipherText =
|
||||
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
|
||||
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.ENCRYPT, initialCounter = ic.hexStringToUByteArray())
|
||||
aesCtr.addData(
|
||||
plaintext.hexStringToUByteArray()
|
||||
)
|
||||
val encrypted = aesCtr.encrypt()
|
||||
println("Encrypted: ${encrypted.encryptedData.toHexString()}")
|
||||
|
||||
expectedCipherText == encrypted.encryptedData.toHexString() &&
|
||||
ic == encrypted.initialCounter.toHexString()
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val keyString = "4278b840fb44aaa757c1bf04acbe1a3e"
|
||||
val key = AesKey.Aes128Key(keyString)
|
||||
val plainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
|
||||
val encryptedDataAndInitializationVector = AesCtr.encrypt(key, plainText.hexStringToUByteArray())
|
||||
val decrypted = AesCtr.decrypt(
|
||||
key,
|
||||
encryptedDataAndInitializationVector.encryptedData,
|
||||
encryptedDataAndInitializationVector.initialCounter
|
||||
)
|
||||
plainText == decrypted.toHexString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCtrDecryption() {
|
||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
||||
val cipherText = "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
|
||||
val expectedPlainText = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
val aesCbc = AesCtr(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray())
|
||||
aesCbc.addData(cipherText.hexStringToUByteArray())
|
||||
val decrypted = aesCbc.decrypt()
|
||||
println("Decrypted: ${decrypted.toHexString()}")
|
||||
assertTrue {
|
||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
||||
val cipherText =
|
||||
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
|
||||
val expectedPlainText =
|
||||
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
val aesCtr = AesCtr(AesKey.Aes128Key(key), mode = Mode.DECRYPT, initialCounter = ic.hexStringToUByteArray())
|
||||
aesCtr.addData(cipherText.hexStringToUByteArray())
|
||||
val decrypted = aesCtr.decrypt()
|
||||
println("Decrypted: ${decrypted.toHexString()}")
|
||||
expectedPlainText == decrypted.toHexString()
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
val key = "2b7e151628aed2a6abf7158809cf4f3c"
|
||||
val ic = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
||||
val cipherText =
|
||||
"874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee"
|
||||
val expectedPlainText =
|
||||
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710"
|
||||
val decrypted = AesCtr.decrypt(AesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), ic.hexStringToUByteArray())
|
||||
println("Decrypted: ${decrypted.toHexString()}")
|
||||
expectedPlainText == decrypted.toHexString()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user