Added tests, fixed bugs

This commit is contained in:
Ugljesa Jovanovic 2020-09-01 23:29:56 +02:00 committed by Ugljesa Jovanovic
parent 4762bd96d6
commit 9cb2701715
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
5 changed files with 143 additions and 19 deletions

View File

@ -0,0 +1,96 @@
package com.ionspin.kotlin.crypto.box
import com.ionspin.kotlin.bignum.integer.util.hexColumsPrint
import com.ionspin.kotlin.crypto.LibsodiumInitializer
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.random.Random
import kotlin.random.nextUBytes
import kotlin.test.Test
import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 01-Sep-2020
*/
class BoxTest {
@Test
fun keypairTest() {
LibsodiumInitializer.initializeWithCallback {
val keypair = Box.keypair()
assertTrue {
keypair.publicKey.size == crypto_box_PUBLICKEYBYTES
}
assertTrue {
keypair.secretKey.size == crypto_box_SECRETKEYBYTES
}
}
}
@Test
fun testBoxEasy() {
val message = "Message message message".encodeToUByteArray()
val senderKeypair = Box.keypair()
val recipientKeypair = Box.keypair()
val messageNonce = Random(0).nextUBytes(crypto_box_NONCEBYTES)
val encrypted = Box.easy(message, messageNonce, recipientKeypair.publicKey, senderKeypair.secretKey)
val decrypted = Box.openEasy(encrypted, messageNonce, senderKeypair.publicKey, recipientKeypair.secretKey)
assertTrue {
decrypted.contentEquals(message)
}
assertFailsWith<BoxCorruptedOrTamperedDataException>() {
val tampered = encrypted.copyOf()
tampered[1] = 0U
Box.openEasy(tampered, messageNonce, senderKeypair.publicKey, recipientKeypair.secretKey)
}
}
@Test
fun testBoxEasyDetached() {
val message = "Message message message".encodeToUByteArray()
val senderKeypair = Box.keypair()
val recipientKeypair = Box.keypair()
val messageNonce = Random(0).nextUBytes(crypto_box_NONCEBYTES)
val encrypted = Box.detached(message, messageNonce, recipientKeypair.publicKey, senderKeypair.secretKey)
val decrypted = Box.openDetached(encrypted.ciphertext, encrypted.tag, messageNonce, senderKeypair.publicKey, recipientKeypair.secretKey)
assertTrue {
decrypted.contentEquals(message)
}
assertFailsWith<BoxCorruptedOrTamperedDataException>() {
val tampered = encrypted.ciphertext.copyOf()
tampered[1] = 0U
Box.openDetached(tampered, encrypted.tag, messageNonce, senderKeypair.publicKey, recipientKeypair.secretKey)
}
}
@Test
fun testBeforeNonceAndMessage() {
val message = "Message message message".encodeToUByteArray()
val senderKeypair = Box.keypair()
val recipientKeypair = Box.keypair()
val messageNonce = Random(0).nextUBytes(crypto_box_NONCEBYTES)
val senderComputedSessionKey = Box.beforeNM(recipientKeypair.publicKey, senderKeypair.secretKey)
val recipientComputedSessionKey = Box.beforeNM(senderKeypair.publicKey, recipientKeypair.secretKey)
assertTrue {
senderComputedSessionKey.contentEquals(recipientComputedSessionKey)
}
val encrypted = Box.easyAfterNM(message, messageNonce, senderComputedSessionKey)
val decrypted = Box.openEasyAfterNM(encrypted, messageNonce, recipientComputedSessionKey)
assertTrue {
decrypted.contentEquals(message)
}
assertFailsWith<BoxCorruptedOrTamperedDataException>() {
val tampered = encrypted.copyOf()
tampered[1] = 0U
Box.openEasyAfterNM(tampered, messageNonce, recipientComputedSessionKey)
}
}
}

View File

@ -73,7 +73,7 @@ class SecretStreamTest {
assertTrue { assertTrue {
decrypted.decryptedData.contentEquals(message) decrypted.decryptedData.contentEquals(message)
} }
assertFailsWith(SecretStreamCorrupedOrTamperedDataException::class) { assertFailsWith(SecretStreamCorruptedOrTamperedDataException::class) {
encrypted[encrypted.size - 5] = 0U encrypted[encrypted.size - 5] = 0U
val decryptState = SecretStream.xChaCha20Poly1305InitPull(key, stateAndHeader.header) val decryptState = SecretStream.xChaCha20Poly1305InitPull(key, stateAndHeader.header)
val decrypted = val decrypted =

View File

@ -1,5 +1,6 @@
package com.ionspin.kotlin.crypto.box package com.ionspin.kotlin.crypto.box
import com.ionspin.kotlin.crypto.util.toHexString
import com.ionspin.kotlin.crypto.util.toPtr import com.ionspin.kotlin.crypto.util.toPtr
import kotlinx.cinterop.convert import kotlinx.cinterop.convert
import kotlinx.cinterop.pin import kotlinx.cinterop.pin
@ -9,6 +10,8 @@ import libsodium.crypto_box_easy
import libsodium.crypto_box_easy_afternm import libsodium.crypto_box_easy_afternm
import libsodium.crypto_box_keypair import libsodium.crypto_box_keypair
import libsodium.crypto_box_open_detached import libsodium.crypto_box_open_detached
import libsodium.crypto_box_open_easy
import libsodium.crypto_box_open_easy_afternm
import libsodium.crypto_box_seal import libsodium.crypto_box_seal
import libsodium.crypto_box_seal_open import libsodium.crypto_box_seal_open
import libsodium.crypto_box_seed_keypair import libsodium.crypto_box_seed_keypair
@ -38,7 +41,6 @@ actual object Box {
val secretKey = UByteArray(crypto_box_SECRETKEYBYTES) val secretKey = UByteArray(crypto_box_SECRETKEYBYTES)
val publicKeyPinned = publicKey.pin() val publicKeyPinned = publicKey.pin()
val secretKeyPinned = secretKey.pin() val secretKeyPinned = secretKey.pin()
val seed: UByteArray = UByteArray(crypto_box_SEEDBYTES)
val seedPinned = seed.pin() val seedPinned = seed.pin()
crypto_box_seed_keypair(publicKeyPinned.toPtr(), secretKeyPinned.toPtr(), seedPinned.toPtr()) crypto_box_seed_keypair(publicKeyPinned.toPtr(), secretKeyPinned.toPtr(), seedPinned.toPtr())
publicKeyPinned.unpin() publicKeyPinned.unpin()
@ -60,7 +62,7 @@ actual object Box {
recipientsPublicKey: UByteArray, recipientsPublicKey: UByteArray,
sendersSecretKey: UByteArray sendersSecretKey: UByteArray
): UByteArray { ): UByteArray {
val ciphertext = UByteArray(message.size - crypto_box_MACBYTES) val ciphertext = UByteArray(message.size + crypto_box_MACBYTES)
val ciphertextPinned = ciphertext.pin() val ciphertextPinned = ciphertext.pin()
val messagePinned = message.pin() val messagePinned = message.pin()
@ -83,7 +85,7 @@ actual object Box {
recipientsPublicKeyPinned.unpin() recipientsPublicKeyPinned.unpin()
sendersSecretKeyPinned.unpin() sendersSecretKeyPinned.unpin()
return message return ciphertext
} }
/** /**
@ -99,7 +101,7 @@ actual object Box {
sendersPublicKey: UByteArray, sendersPublicKey: UByteArray,
recipientsSecretKey: UByteArray recipientsSecretKey: UByteArray
): UByteArray { ): UByteArray {
val message = UByteArray(ciphertext.size + crypto_box_MACBYTES) val message = UByteArray(ciphertext.size - crypto_box_MACBYTES)
val messagePinned = message.pin() val messagePinned = message.pin()
val ciphertextPinned = ciphertext.pin() val ciphertextPinned = ciphertext.pin()
@ -107,7 +109,7 @@ actual object Box {
val sendersPublicKeyPinned = sendersPublicKey.pin() val sendersPublicKeyPinned = sendersPublicKey.pin()
val recipientsSecretKeyPinned = recipientsSecretKey.pin() val recipientsSecretKeyPinned = recipientsSecretKey.pin()
crypto_box_easy( val validationResult = crypto_box_open_easy(
messagePinned.toPtr(), messagePinned.toPtr(),
ciphertextPinned.toPtr(), ciphertextPinned.toPtr(),
ciphertext.size.convert(), ciphertext.size.convert(),
@ -122,6 +124,10 @@ actual object Box {
sendersPublicKeyPinned.unpin() sendersPublicKeyPinned.unpin()
recipientsSecretKeyPinned.unpin() recipientsSecretKeyPinned.unpin()
if (validationResult != 0) {
throw BoxCorruptedOrTamperedDataException()
}
return message return message
} }
@ -173,6 +179,8 @@ actual object Box {
noncePinned.unpin() noncePinned.unpin()
precomputedKeyPinned.unpin() precomputedKeyPinned.unpin()
return ciphertext return ciphertext
} }
@ -191,7 +199,7 @@ actual object Box {
val noncePinned = nonce.pin() val noncePinned = nonce.pin()
val precomputedKeyPinned = precomputedKey.pin() val precomputedKeyPinned = precomputedKey.pin()
crypto_box_easy_afternm( val validationResult = crypto_box_open_easy_afternm(
messagePinned.toPtr(), messagePinned.toPtr(),
ciphertextPinned.toPtr(), ciphertextPinned.toPtr(),
ciphertext.size.convert(), ciphertext.size.convert(),
@ -204,7 +212,11 @@ actual object Box {
noncePinned.unpin() noncePinned.unpin()
precomputedKeyPinned.unpin() precomputedKeyPinned.unpin()
return ciphertext if (validationResult != 0) {
throw BoxCorruptedOrTamperedDataException()
}
return message
} }
/** /**
@ -232,8 +244,8 @@ actual object Box {
crypto_box_detached( crypto_box_detached(
ciphertextPinned.toPtr(), ciphertextPinned.toPtr(),
messagePinned.toPtr(),
tagPinned.toPtr(), tagPinned.toPtr(),
messagePinned.toPtr(),
message.size.convert(), message.size.convert(),
noncePinned.toPtr(), noncePinned.toPtr(),
recipientsPublicKeyPinned.toPtr(), recipientsPublicKeyPinned.toPtr(),
@ -246,7 +258,6 @@ actual object Box {
noncePinned.unpin() noncePinned.unpin()
recipientsPublicKeyPinned.unpin() recipientsPublicKeyPinned.unpin()
sendersSecretKeyPinned.unpin() sendersSecretKeyPinned.unpin()
return BoxEncryptedDataAndTag(ciphertext, tag) return BoxEncryptedDataAndTag(ciphertext, tag)
} }
@ -265,23 +276,22 @@ actual object Box {
): UByteArray { ): UByteArray {
val message = UByteArray(ciphertext.size) val message = UByteArray(ciphertext.size)
val messagePinned = message.pin()
val ciphertextPinned = ciphertext.pin() val ciphertextPinned = ciphertext.pin()
val tagPinned = tag.pin() val tagPinned = tag.pin()
val messagePinned = message.pin()
val noncePinned = nonce.pin() val noncePinned = nonce.pin()
val recipientsSecretKeyPinned = recipientsSecretKey.pin() val recipientsSecretKeyPinned = recipientsSecretKey.pin()
val sendersPublicKeyPinned = sendersPublicKey.pin() val sendersPublicKeyPinned = sendersPublicKey.pin()
crypto_box_open_detached( val validationResult = crypto_box_open_detached(
messagePinned.toPtr(), messagePinned.toPtr(),
ciphertextPinned.toPtr(), ciphertextPinned.toPtr(),
tagPinned.toPtr(), tagPinned.toPtr(),
message.size.convert(), ciphertext.size.convert(),
noncePinned.toPtr(), noncePinned.toPtr(),
recipientsSecretKeyPinned.toPtr(), sendersPublicKeyPinned.toPtr(),
sendersPublicKeyPinned.toPtr() recipientsSecretKeyPinned.toPtr()
) )
ciphertextPinned.unpin() ciphertextPinned.unpin()
@ -291,6 +301,10 @@ actual object Box {
recipientsSecretKeyPinned.unpin() recipientsSecretKeyPinned.unpin()
sendersPublicKeyPinned.unpin() sendersPublicKeyPinned.unpin()
if (validationResult != 0) {
throw BoxCorruptedOrTamperedDataException()
}
return message return message
} }
@ -318,16 +332,31 @@ actual object Box {
actual fun sealOpen(ciphertext: UByteArray, recipientsSecretKey: UByteArray): UByteArray { actual fun sealOpen(ciphertext: UByteArray, recipientsSecretKey: UByteArray): UByteArray {
val message = UByteArray(ciphertext.size - crypto_box_SEALBYTES) val message = UByteArray(ciphertext.size - crypto_box_SEALBYTES)
val senderPublicKey = UByteArray(crypto_box_SEALBYTES) {
message[ciphertext.size - crypto_box_SEALBYTES + it - 1]
}
val senderPublicKeyPinned = senderPublicKey.pin()
val messagePinned = message.pin() val messagePinned = message.pin()
val ciphertextPinned = ciphertext.pin() val ciphertextPinned = ciphertext.pin()
val recipientsSecretKeyPinned = recipientsSecretKey.pin() val recipientsSecretKeyPinned = recipientsSecretKey.pin()
crypto_box_seal_open(messagePinned.toPtr(), ciphertextPinned.toPtr(), recipientsSecretKeyPinned.toPtr()) val validationResult = crypto_box_seal_open(
messagePinned.toPtr(),
ciphertextPinned.toPtr(),
ciphertext.size.convert(),
senderPublicKeyPinned.toPtr(),
recipientsSecretKeyPinned.toPtr()
)
messagePinned.unpin() messagePinned.unpin()
ciphertextPinned.unpin() ciphertextPinned.unpin()
senderPublicKeyPinned.unpin()
recipientsSecretKeyPinned.unpin() recipientsSecretKeyPinned.unpin()
if (validationResult != 0) {
throw BoxCorruptedOrTamperedDataException()
}
return message return message
} }

View File

@ -1,6 +1,5 @@
package com.ionspin.kotlin.crypto.secretbox package com.ionspin.kotlin.crypto.secretbox
import com.ionspin.kotlin.crypto.secretstream.SecretStreamCorrupedOrTamperedDataException
import com.ionspin.kotlin.crypto.util.toPtr import com.ionspin.kotlin.crypto.util.toPtr
import kotlinx.cinterop.convert import kotlinx.cinterop.convert
import kotlinx.cinterop.pin import kotlinx.cinterop.pin

View File

@ -116,7 +116,7 @@ actual object SecretStream {
associatedDataPinned?.unpin() associatedDataPinned?.unpin()
tagPinned.unpin() tagPinned.unpin()
if (validationResult != 0) { if (validationResult != 0) {
throw SecretStreamCorrupedOrTamperedDataException() throw SecretStreamCorruptedOrTamperedDataException()
} }
return DecryptedDataAndTag(message, tag[0]) return DecryptedDataAndTag(message, tag[0])
} }