Add high level AEAD tests, implement missing initializations, implement pure decryption
This commit is contained in:
1 parent
579c44fcc7
commit
55b5641f14
10 files changed
+237
-22
No files matched your search
+1
-1
@@ -7,7 +7,7 @@ package com.ionspin.kotlin.crypto.authenticated
|
||||
* on 14-Jun-2020
|
||||
*/
|
||||
expect class XChaCha20Poly1305Delegated internal constructor() {
|
||||
internal constructor(key: UByteArray, testState : UByteArray, testHeader: UByteArray)
|
||||
internal constructor(key: UByteArray, testState : UByteArray, testHeader: UByteArray, isDecryptor: Boolean)
|
||||
companion object {
|
||||
fun encrypt(key: UByteArray, nonce: UByteArray, message: UByteArray, additionalData: UByteArray) : UByteArray
|
||||
fun decrypt(key: UByteArray, nonce: UByteArray, ciphertext: UByteArray, additionalData: UByteArray) : UByteArray
|
||||
|
||||
+3
-3
@@ -211,8 +211,8 @@ class XChaCha20Poly1305Test {
|
||||
0xDEU, 0xFBU, 0x5CU, 0x7FU, 0x1CU, 0x26U, 0x32U, 0x2CU, 0x51U, 0xF6U, 0xEFU, 0xC6U, 0x34U, 0xC4U, 0xACU, 0x6CU,
|
||||
0xE8U, 0xF9U, 0x4BU, 0xABU, 0xA3U,
|
||||
)
|
||||
val encryptor = XChaCha20Poly1305Delegated(key, state, header)
|
||||
val decryptor = XChaCha20Poly1305Delegated(key, state, header)
|
||||
val encryptor = XChaCha20Poly1305Delegated(key, state, header, false)
|
||||
val decryptor = XChaCha20Poly1305Delegated(key, state, header, true)
|
||||
val data = UByteArray(100) { 0U }
|
||||
val result = encryptor.encrypt(data)
|
||||
val decrypted = decryptor.decrypt(result)
|
||||
@@ -228,7 +228,7 @@ class XChaCha20Poly1305Test {
|
||||
val messedUpTag = result.copyOf()
|
||||
messedUpTag[messedUpTag.size - 2] = 0U
|
||||
assertFails {
|
||||
val decryptorForWrongTag = XChaCha20Poly1305Delegated(key, state, header)
|
||||
val decryptorForWrongTag = XChaCha20Poly1305Delegated(key, state, header, true)
|
||||
val plaintext = decryptorForWrongTag.decrypt(messedUpTag)
|
||||
println("Decrypted with wrong tag -----------")
|
||||
plaintext.hexColumsPrint()
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.ionspin.kotlin.crypto.highlevel
|
||||
|
||||
import com.ionspin.kotlin.crypto.Crypto
|
||||
import com.ionspin.kotlin.crypto.Initializer
|
||||
import com.ionspin.kotlin.crypto.SymmetricKey
|
||||
import com.ionspin.kotlin.crypto.hash.decodeToString
|
||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
||||
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Created by Ugljesa Jovanovic
|
||||
* ugljesa.jovanovic@ionspin.com
|
||||
* on 09-Jul-2020
|
||||
*/
|
||||
class EncryptionTest {
|
||||
@Test
|
||||
fun testMultipartEncryption() = testBlocking {
|
||||
Initializer.initialize()
|
||||
val plaintext = ("Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
|
||||
"Vestibulum maximus tincidunt urna. " +
|
||||
"Nullam sit amet erat id arcu porttitor varius ut at metus. " +
|
||||
"Nunc sit amet felis vel velit ornare gravida. " +
|
||||
"Curabitur tellus lacus, pulvinar a diam at tincidunt.").encodeToUByteArray()
|
||||
val additionalData = "Additional data 1".encodeToUByteArray()
|
||||
val keyValue = UByteArray(32) { it.toUByte() }
|
||||
val key = SymmetricKey(keyValue)
|
||||
val encryptor = Crypto.Encryption.createMultipartEncryptor(key)
|
||||
val header = encryptor.startEncryption()
|
||||
val ciphertext1 = encryptor.encryptPartialData(plaintext.sliceArray(0 until 100), additionalData)
|
||||
val ciphertext2 = encryptor.encryptPartialData(plaintext.sliceArray(100 until 200))
|
||||
val ciphertext3 = encryptor.encryptPartialData(plaintext.sliceArray(200 until 250))
|
||||
//decrypt
|
||||
val decryptor = Crypto.Encryption.createMultipartDecryptor(key, header)
|
||||
println("Initialized")
|
||||
val plaintext1 = decryptor.decryptPartialData(ciphertext1, additionalData)
|
||||
val plaintext2 = decryptor.decryptPartialData(ciphertext2)
|
||||
val plaintext3 = decryptor.decryptPartialData(ciphertext3)
|
||||
|
||||
val combinedPlaintext = plaintext1.data + plaintext2.data + plaintext3.data
|
||||
println("---- Plaintext -----")
|
||||
plaintext.hexColumsPrint()
|
||||
println("---- Plaintext result -----")
|
||||
combinedPlaintext.hexColumsPrint()
|
||||
assertTrue {
|
||||
plaintext.contentEquals(combinedPlaintext)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
+30
-6
@@ -54,41 +54,65 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
}
|
||||
|
||||
var state : dynamic = null
|
||||
var isInitialized = false
|
||||
var isEncryptor = false
|
||||
|
||||
actual fun initializeForEncryption(key: UByteArray) : UByteArray {
|
||||
println("Initializaing for encryption")
|
||||
val stateAndHeader = getSodium().crypto_secretstream_xchacha20poly1305_init_push(key.toUInt8Array())
|
||||
val state = stateAndHeader.state
|
||||
val header = stateAndHeader.header
|
||||
state = stateAndHeader.state
|
||||
val header = stateAndHeader.header as Uint8Array
|
||||
console.log(state)
|
||||
console.log(header)
|
||||
println("Done initializaing for encryption")
|
||||
return header
|
||||
isInitialized = true
|
||||
isEncryptor = true
|
||||
return header.toUByteArray()
|
||||
}
|
||||
|
||||
actual fun initializeForDecryption(key: UByteArray, header: UByteArray) {
|
||||
|
||||
println("Initializing for decryption")
|
||||
header.hexColumsPrint()
|
||||
state = getSodium().crypto_secretstream_xchacha20poly1305_init_pull(header.toUInt8Array(), key.toUInt8Array())
|
||||
console.log(state)
|
||||
isInitialized = true
|
||||
isEncryptor = false
|
||||
}
|
||||
|
||||
internal actual constructor(
|
||||
key: UByteArray,
|
||||
testState: UByteArray,
|
||||
testHeader: UByteArray
|
||||
testHeader: UByteArray,
|
||||
isDecryptor: Boolean
|
||||
) : this() {
|
||||
state = getSodium().crypto_secretstream_xchacha20poly1305_init_pull(testHeader.toUInt8Array(), key.toUInt8Array())
|
||||
console.log(state)
|
||||
println("Done initializaing test state")
|
||||
isInitialized = true
|
||||
isEncryptor = !isDecryptor
|
||||
}
|
||||
|
||||
actual fun encrypt(data: UByteArray, additionalData: UByteArray): UByteArray {
|
||||
if (!isInitialized) {
|
||||
throw RuntimeException("Not initalized!")
|
||||
}
|
||||
if (!isEncryptor) {
|
||||
throw RuntimeException("Initialized as decryptor, attempted to use as encryptor")
|
||||
}
|
||||
val encrypted = getSodium().crypto_secretstream_xchacha20poly1305_push(state, data.toUInt8Array(), additionalData.toUInt8Array(), 0U)
|
||||
return encrypted.toUByteArray()
|
||||
}
|
||||
|
||||
actual fun decrypt(data: UByteArray, additionalData: UByteArray): UByteArray {
|
||||
if (!isInitialized) {
|
||||
throw RuntimeException("Not initalized!")
|
||||
}
|
||||
if (isEncryptor) {
|
||||
throw RuntimeException("Initialized as encryptor, attempted to use as decryptor")
|
||||
}
|
||||
val decryptedWithTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(state, data.toUInt8Array(), additionalData.toUInt8Array())
|
||||
val decrypted = decryptedWithTag.message as Uint8Array
|
||||
val validTag = decryptedWithTag.tag as UInt
|
||||
val validTag = decryptedWithTag.tag
|
||||
|
||||
if (validTag != 0U) {
|
||||
println("Tag validation failed")
|
||||
|
||||
+27
-2
@@ -60,23 +60,42 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
val state : SecretStream.State = SecretStream.State()
|
||||
val sodium = SodiumJava()
|
||||
|
||||
var isInitialized = false
|
||||
var isEncryptor = false
|
||||
|
||||
internal actual constructor(
|
||||
key: UByteArray,
|
||||
testState: UByteArray,
|
||||
testHeader: UByteArray
|
||||
testHeader: UByteArray,
|
||||
isDecryptor: Boolean
|
||||
) : this() {
|
||||
state.k = testState.sliceArray(0 until 32).toByteArray()
|
||||
state.nonce = testState.sliceArray(32 until 44).toByteArray()
|
||||
isInitialized = true
|
||||
isEncryptor = !isDecryptor
|
||||
}
|
||||
|
||||
actual fun initializeForEncryption(key: UByteArray) : UByteArray {
|
||||
TODO()
|
||||
val header = UByteArray(24)
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header.asByteArray(), key.asByteArray())
|
||||
isInitialized = true
|
||||
isEncryptor = true
|
||||
return header
|
||||
}
|
||||
|
||||
actual fun initializeForDecryption(key: UByteArray, header: UByteArray) {
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header.asByteArray(), key.asByteArray())
|
||||
isInitialized = true
|
||||
isEncryptor = false
|
||||
}
|
||||
|
||||
actual fun encrypt(data: UByteArray, additionalData: UByteArray): UByteArray {
|
||||
if (!isInitialized) {
|
||||
throw RuntimeException("Not initalized!")
|
||||
}
|
||||
if (!isEncryptor) {
|
||||
throw RuntimeException("Initialized as decryptor, attempted to use as encryptor")
|
||||
}
|
||||
val ciphertext = ByteArray(1 + data.size + 16)
|
||||
sodium.crypto_secretstream_xchacha20poly1305_push(
|
||||
state, ciphertext, null,
|
||||
@@ -88,6 +107,12 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
}
|
||||
|
||||
actual fun decrypt(data: UByteArray, additionalData: UByteArray): UByteArray {
|
||||
if (!isInitialized) {
|
||||
throw RuntimeException("Not initalized!")
|
||||
}
|
||||
if (isEncryptor) {
|
||||
throw RuntimeException("Initialized as encryptor, attempted to use as decryptor")
|
||||
}
|
||||
val plaintext = ByteArray(data.size - 17)
|
||||
|
||||
val validTag = sodium.crypto_secretstream_xchacha20poly1305_pull(
|
||||
|
||||
+11
-4
@@ -69,10 +69,14 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
|
||||
val header = UByteArray(crypto_secretstream_xchacha20poly1305_HEADERBYTES.toInt()) { 0U }
|
||||
|
||||
var isInitialized = false
|
||||
var isEncryptor = false
|
||||
|
||||
actual internal constructor(
|
||||
key: UByteArray,
|
||||
testState: UByteArray,
|
||||
testHeader: UByteArray
|
||||
testHeader: UByteArray,
|
||||
isDecryptor: Boolean
|
||||
) : this() {
|
||||
val pointer = state.ptr.reinterpret<UByteVar>()
|
||||
for (i in 0 until crypto_secretstream_xchacha20poly1305_state.size.toInt()) {
|
||||
@@ -85,6 +89,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
testHeader.copyInto(header)
|
||||
header.hexColumsPrint()
|
||||
println("header after setting-----------")
|
||||
isInitialized = true
|
||||
isEncryptor = !isDecryptor
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +109,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
}
|
||||
|
||||
actual fun initializeForDecryption(key: UByteArray, header: UByteArray) {
|
||||
|
||||
crypto_secretstream_xchacha20poly1305_init_pull(state.ptr, header.toCValues(), key.toCValues())
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +122,8 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
null,
|
||||
data.toCValues(),
|
||||
data.size.convert(),
|
||||
null,
|
||||
0U,
|
||||
additionalData.toCValues(),
|
||||
additionalData.size.convert(),
|
||||
0U,
|
||||
)
|
||||
println("Encrypt partial")
|
||||
@@ -141,6 +147,7 @@ actual class XChaCha20Poly1305Delegated internal actual constructor() {
|
||||
additionalData.size.convert()
|
||||
)
|
||||
plaintextPinned.unpin()
|
||||
println("tag: $validTag")
|
||||
if (validTag != 0) {
|
||||
println("Tag validation failed")
|
||||
throw InvalidTagException()
|
||||
|
||||
Reference in new issue
Block a user