Added tests, fixed bugs
This commit is contained in:
parent
4762bd96d6
commit
9cb2701715
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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 =
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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])
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user