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 {
 | 
			
		||||
                decrypted.decryptedData.contentEquals(message)
 | 
			
		||||
            }
 | 
			
		||||
            assertFailsWith(SecretStreamCorrupedOrTamperedDataException::class) {
 | 
			
		||||
            assertFailsWith(SecretStreamCorruptedOrTamperedDataException::class) {
 | 
			
		||||
                encrypted[encrypted.size - 5] = 0U
 | 
			
		||||
                val decryptState = SecretStream.xChaCha20Poly1305InitPull(key, stateAndHeader.header)
 | 
			
		||||
                val decrypted =
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
package com.ionspin.kotlin.crypto.box
 | 
			
		||||
 | 
			
		||||
import com.ionspin.kotlin.crypto.util.toHexString
 | 
			
		||||
import com.ionspin.kotlin.crypto.util.toPtr
 | 
			
		||||
import kotlinx.cinterop.convert
 | 
			
		||||
import kotlinx.cinterop.pin
 | 
			
		||||
@ -9,6 +10,8 @@ import libsodium.crypto_box_easy
 | 
			
		||||
import libsodium.crypto_box_easy_afternm
 | 
			
		||||
import libsodium.crypto_box_keypair
 | 
			
		||||
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_open
 | 
			
		||||
import libsodium.crypto_box_seed_keypair
 | 
			
		||||
@ -38,7 +41,6 @@ actual object Box {
 | 
			
		||||
        val secretKey = UByteArray(crypto_box_SECRETKEYBYTES)
 | 
			
		||||
        val publicKeyPinned = publicKey.pin()
 | 
			
		||||
        val secretKeyPinned = secretKey.pin()
 | 
			
		||||
        val seed: UByteArray = UByteArray(crypto_box_SEEDBYTES)
 | 
			
		||||
        val seedPinned = seed.pin()
 | 
			
		||||
        crypto_box_seed_keypair(publicKeyPinned.toPtr(), secretKeyPinned.toPtr(), seedPinned.toPtr())
 | 
			
		||||
        publicKeyPinned.unpin()
 | 
			
		||||
@ -60,7 +62,7 @@ actual object Box {
 | 
			
		||||
        recipientsPublicKey: UByteArray,
 | 
			
		||||
        sendersSecretKey: UByteArray
 | 
			
		||||
    ): UByteArray {
 | 
			
		||||
        val ciphertext = UByteArray(message.size - crypto_box_MACBYTES)
 | 
			
		||||
        val ciphertext = UByteArray(message.size + crypto_box_MACBYTES)
 | 
			
		||||
        val ciphertextPinned = ciphertext.pin()
 | 
			
		||||
 | 
			
		||||
        val messagePinned = message.pin()
 | 
			
		||||
@ -83,7 +85,7 @@ actual object Box {
 | 
			
		||||
        recipientsPublicKeyPinned.unpin()
 | 
			
		||||
        sendersSecretKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
        return message
 | 
			
		||||
        return ciphertext
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -99,7 +101,7 @@ actual object Box {
 | 
			
		||||
        sendersPublicKey: UByteArray,
 | 
			
		||||
        recipientsSecretKey: UByteArray
 | 
			
		||||
    ): UByteArray {
 | 
			
		||||
        val message = UByteArray(ciphertext.size + crypto_box_MACBYTES)
 | 
			
		||||
        val message = UByteArray(ciphertext.size - crypto_box_MACBYTES)
 | 
			
		||||
        val messagePinned = message.pin()
 | 
			
		||||
 | 
			
		||||
        val ciphertextPinned = ciphertext.pin()
 | 
			
		||||
@ -107,7 +109,7 @@ actual object Box {
 | 
			
		||||
        val sendersPublicKeyPinned = sendersPublicKey.pin()
 | 
			
		||||
        val recipientsSecretKeyPinned = recipientsSecretKey.pin()
 | 
			
		||||
 | 
			
		||||
        crypto_box_easy(
 | 
			
		||||
        val validationResult = crypto_box_open_easy(
 | 
			
		||||
            messagePinned.toPtr(),
 | 
			
		||||
            ciphertextPinned.toPtr(),
 | 
			
		||||
            ciphertext.size.convert(),
 | 
			
		||||
@ -122,6 +124,10 @@ actual object Box {
 | 
			
		||||
        sendersPublicKeyPinned.unpin()
 | 
			
		||||
        recipientsSecretKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
        if (validationResult != 0) {
 | 
			
		||||
            throw BoxCorruptedOrTamperedDataException()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return message
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -173,6 +179,8 @@ actual object Box {
 | 
			
		||||
        noncePinned.unpin()
 | 
			
		||||
        precomputedKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return ciphertext
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -191,7 +199,7 @@ actual object Box {
 | 
			
		||||
        val noncePinned = nonce.pin()
 | 
			
		||||
        val precomputedKeyPinned = precomputedKey.pin()
 | 
			
		||||
 | 
			
		||||
        crypto_box_easy_afternm(
 | 
			
		||||
        val validationResult = crypto_box_open_easy_afternm(
 | 
			
		||||
            messagePinned.toPtr(),
 | 
			
		||||
            ciphertextPinned.toPtr(),
 | 
			
		||||
            ciphertext.size.convert(),
 | 
			
		||||
@ -204,7 +212,11 @@ actual object Box {
 | 
			
		||||
        noncePinned.unpin()
 | 
			
		||||
        precomputedKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
        return ciphertext
 | 
			
		||||
        if (validationResult != 0) {
 | 
			
		||||
            throw BoxCorruptedOrTamperedDataException()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return message
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -232,8 +244,8 @@ actual object Box {
 | 
			
		||||
 | 
			
		||||
        crypto_box_detached(
 | 
			
		||||
            ciphertextPinned.toPtr(),
 | 
			
		||||
            messagePinned.toPtr(),
 | 
			
		||||
            tagPinned.toPtr(),
 | 
			
		||||
            messagePinned.toPtr(),
 | 
			
		||||
            message.size.convert(),
 | 
			
		||||
            noncePinned.toPtr(),
 | 
			
		||||
            recipientsPublicKeyPinned.toPtr(),
 | 
			
		||||
@ -246,7 +258,6 @@ actual object Box {
 | 
			
		||||
        noncePinned.unpin()
 | 
			
		||||
        recipientsPublicKeyPinned.unpin()
 | 
			
		||||
        sendersSecretKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
        return BoxEncryptedDataAndTag(ciphertext, tag)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -265,23 +276,22 @@ actual object Box {
 | 
			
		||||
    ): UByteArray {
 | 
			
		||||
        val message = UByteArray(ciphertext.size)
 | 
			
		||||
 | 
			
		||||
        val messagePinned = message.pin()
 | 
			
		||||
        val ciphertextPinned = ciphertext.pin()
 | 
			
		||||
        val tagPinned = tag.pin()
 | 
			
		||||
 | 
			
		||||
        val messagePinned = message.pin()
 | 
			
		||||
        val noncePinned = nonce.pin()
 | 
			
		||||
        val recipientsSecretKeyPinned = recipientsSecretKey.pin()
 | 
			
		||||
        val sendersPublicKeyPinned = sendersPublicKey.pin()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        crypto_box_open_detached(
 | 
			
		||||
        val validationResult = crypto_box_open_detached(
 | 
			
		||||
            messagePinned.toPtr(),
 | 
			
		||||
            ciphertextPinned.toPtr(),
 | 
			
		||||
            tagPinned.toPtr(),
 | 
			
		||||
            message.size.convert(),
 | 
			
		||||
            ciphertext.size.convert(),
 | 
			
		||||
            noncePinned.toPtr(),
 | 
			
		||||
            recipientsSecretKeyPinned.toPtr(),
 | 
			
		||||
            sendersPublicKeyPinned.toPtr()
 | 
			
		||||
            sendersPublicKeyPinned.toPtr(),
 | 
			
		||||
            recipientsSecretKeyPinned.toPtr()
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        ciphertextPinned.unpin()
 | 
			
		||||
@ -291,6 +301,10 @@ actual object Box {
 | 
			
		||||
        recipientsSecretKeyPinned.unpin()
 | 
			
		||||
        sendersPublicKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
        if (validationResult != 0) {
 | 
			
		||||
            throw BoxCorruptedOrTamperedDataException()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return message
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -318,16 +332,31 @@ actual object Box {
 | 
			
		||||
 | 
			
		||||
    actual fun sealOpen(ciphertext: UByteArray, recipientsSecretKey: UByteArray): UByteArray {
 | 
			
		||||
        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 ciphertextPinned = ciphertext.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()
 | 
			
		||||
        ciphertextPinned.unpin()
 | 
			
		||||
        senderPublicKeyPinned.unpin()
 | 
			
		||||
        recipientsSecretKeyPinned.unpin()
 | 
			
		||||
 | 
			
		||||
        if (validationResult != 0) {
 | 
			
		||||
            throw BoxCorruptedOrTamperedDataException()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return message
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
package com.ionspin.kotlin.crypto.secretbox
 | 
			
		||||
 | 
			
		||||
import com.ionspin.kotlin.crypto.secretstream.SecretStreamCorrupedOrTamperedDataException
 | 
			
		||||
import com.ionspin.kotlin.crypto.util.toPtr
 | 
			
		||||
import kotlinx.cinterop.convert
 | 
			
		||||
import kotlinx.cinterop.pin
 | 
			
		||||
 | 
			
		||||
@ -116,7 +116,7 @@ actual object SecretStream {
 | 
			
		||||
        associatedDataPinned?.unpin()
 | 
			
		||||
        tagPinned.unpin()
 | 
			
		||||
        if (validationResult != 0) {
 | 
			
		||||
            throw SecretStreamCorrupedOrTamperedDataException()
 | 
			
		||||
            throw SecretStreamCorruptedOrTamperedDataException()
 | 
			
		||||
        }
 | 
			
		||||
        return DecryptedDataAndTag(message, tag[0])
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user