Implemeting _stream_ primitives, at elast the ones available in lazy sodium

This commit is contained in:
Ugljesa Jovanovic 2020-10-11 19:47:23 +02:00
parent 8d782d2932
commit a18355adae
No known key found for this signature in database
GPG Key ID: 178E6DFCECCB0E0F
4 changed files with 242 additions and 7 deletions

View File

@ -0,0 +1,21 @@
package com.ionspin.kotlin.crypto.stream
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 11-Oct-2020
*/
const val crypto_stream_chacha20_KEYBYTES = 32
const val crypto_stream_chacha20_NONCEBYTES = 8
const val crypto_stream_chacha20_ietf_KEYBYTES = 32
const val crypto_stream_chacha20_ietf_NONCEBYTES = 12
expect object Stream {
fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray) : UByteArray
fun chacha20IetfXor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray
fun chacha20IetfXorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray
fun chacha20Keygen() : UByteArray
fun chacha20Xor(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray
fun chacha20XorIc(message : UByteArray, nonce: UByteArray, initialCounter: ULong, key: UByteArray) : UByteArray
}

View File

@ -0,0 +1,62 @@
package com.ionspin.kotlin.crypto.stream
import com.ionspin.kotlin.crypto.util.LibsodiumRandom
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
import com.ionspin.kotlin.crypto.util.randombytes_SEEDBYTES
import com.ionspin.kotlin.crypto.util.toHexString
import kotlin.random.Random
import kotlin.random.nextUBytes
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Created by Ugljesa Jovanovic
* ugljesa.jovanovic@ionspin.com
* on 11-Oct-2020
*/
class StreamTest {
val seed = UByteArray(randombytes_SEEDBYTES) { 0U }
@Test
fun testChaCha20Stream() {
val message = "This is a cha cha message".encodeToUByteArray()
val nonce = LibsodiumRandom.bufDeterministic(crypto_stream_chacha20_NONCEBYTES, seed)
val key = Stream.chacha20Keygen()
val stream = Stream.chacha20(message.size, nonce, key)
val encryptedManually = message.mapIndexed { index, it -> it xor stream[index] }.toUByteArray()
val encryptedUsingLibsodium = Stream.chacha20Xor(message, nonce, key)
val encryptedUsingLibsodiumWithInitialCounter = Stream.chacha20XorIc(message, nonce, 0U, key)
println(encryptedManually.toHexString())
println(encryptedUsingLibsodium.toHexString())
println(encryptedUsingLibsodiumWithInitialCounter.toHexString())
assertTrue {
encryptedManually.contentEquals(encryptedUsingLibsodium)
}
assertTrue {
encryptedManually.contentEquals(encryptedUsingLibsodiumWithInitialCounter)
}
val decryptedUsingLibsodium = Stream.chacha20Xor(encryptedUsingLibsodium, nonce, key)
assertTrue {
decryptedUsingLibsodium.contentEquals(message)
}
}
@Test
fun testChaCha20IetfStream() {
val message = "This is a cha cha message".encodeToUByteArray()
val nonce = LibsodiumRandom.bufDeterministic(crypto_stream_chacha20_NONCEBYTES, seed)
val key = Stream.chacha20Keygen()
val encryptedUsingLibsodium = Stream.chacha20IetfXor(message, nonce, key)
val encryptedUsingLibsodiumWithInitialCounter = Stream.chacha20IetfXorIc(message, nonce, 0U, key)
println(encryptedUsingLibsodium.toHexString())
println(encryptedUsingLibsodiumWithInitialCounter.toHexString())
assertTrue {
encryptedUsingLibsodium.contentEquals(encryptedUsingLibsodiumWithInitialCounter)
}
val decryptedUsingLibsodium = Stream.chacha20IetfXor(encryptedUsingLibsodium, nonce, key)
assertTrue {
decryptedUsingLibsodium.contentEquals(message)
}
}
}

View File

@ -0,0 +1,152 @@
package com.ionspin.kotlin.crypto.stream
import com.ionspin.kotlin.crypto.util.toPtr
import kotlinx.cinterop.convert
import kotlinx.cinterop.pin
import libsodium.crypto_stream_KEYBYTES
import libsodium.crypto_stream_chacha20
import libsodium.crypto_stream_chacha20_ietf_xor
import libsodium.crypto_stream_chacha20_ietf_xor_ic
import libsodium.crypto_stream_chacha20_keygen
import libsodium.crypto_stream_chacha20_xor
import libsodium.crypto_stream_chacha20_xor_ic
actual object Stream {
actual fun chacha20(clen: Int, nonce: UByteArray, key: UByteArray): UByteArray {
val result = UByteArray(clen)
val resultPinned = result.pin()
val noncePinned = nonce.pin()
val keyPinned = key.pin()
crypto_stream_chacha20(resultPinned.toPtr(), clen.convert(), noncePinned.toPtr(), keyPinned.toPtr())
resultPinned.unpin()
noncePinned.unpin()
keyPinned.unpin()
return result
}
actual fun chacha20IetfXor(
message: UByteArray,
nonce: UByteArray,
key: UByteArray
): UByteArray {
val result = UByteArray(message.size)
val messagePinned = message.pin()
val resultPinned = result.pin()
val noncePinned = nonce.pin()
val keyPinned = key.pin()
crypto_stream_chacha20_ietf_xor(
resultPinned.toPtr(),
messagePinned.toPtr(),
message.size.convert(),
noncePinned.toPtr(),
keyPinned.toPtr()
)
messagePinned.unpin()
resultPinned.unpin()
noncePinned.unpin()
keyPinned.unpin()
return result
}
actual fun chacha20IetfXorIc(
message: UByteArray,
nonce: UByteArray,
initialCounter: ULong,
key: UByteArray
): UByteArray {
val result = UByteArray(message.size)
val messagePinned = message.pin()
val resultPinned = result.pin()
val noncePinned = nonce.pin()
val keyPinned = key.pin()
crypto_stream_chacha20_ietf_xor_ic(
resultPinned.toPtr(),
messagePinned.toPtr(),
message.size.convert(),
noncePinned.toPtr(),
initialCounter.convert(),
keyPinned.toPtr()
)
messagePinned.unpin()
resultPinned.unpin()
noncePinned.unpin()
keyPinned.unpin()
return result
}
actual fun chacha20Keygen(): UByteArray {
val result = UByteArray(crypto_stream_chacha20_KEYBYTES)
val resultPinned = result.pin()
crypto_stream_chacha20_keygen(resultPinned.toPtr())
resultPinned.unpin()
return result
}
actual fun chacha20Xor(
message: UByteArray,
nonce: UByteArray,
key: UByteArray
): UByteArray {
val result = UByteArray(message.size)
val messagePinned = message.pin()
val resultPinned = result.pin()
val noncePinned = nonce.pin()
val keyPinned = key.pin()
crypto_stream_chacha20_xor(
resultPinned.toPtr(),
messagePinned.toPtr(),
message.size.convert(),
noncePinned.toPtr(),
keyPinned.toPtr()
)
messagePinned.unpin()
resultPinned.unpin()
noncePinned.unpin()
keyPinned.unpin()
return result
}
actual fun chacha20XorIc(
message: UByteArray,
nonce: UByteArray,
initialCounter: ULong,
key: UByteArray
): UByteArray {
val result = UByteArray(message.size)
val messagePinned = message.pin()
val resultPinned = result.pin()
val noncePinned = nonce.pin()
val keyPinned = key.pin()
crypto_stream_chacha20_xor_ic(
resultPinned.toPtr(),
messagePinned.toPtr(),
message.size.convert(),
noncePinned.toPtr(),
initialCounter.convert(),
keyPinned.toPtr()
)
messagePinned.unpin()
resultPinned.unpin()
noncePinned.unpin()
keyPinned.unpin()
return result
}
}

View File

@ -79,10 +79,10 @@
| crypto_hash_sha512_update | :heavy_check_mark: |
| crypto_kdf_derive_from_key | :heavy_check_mark: |
| crypto_kdf_keygen | :heavy_check_mark: |
| crypto_kx_client_session_keys | |
| crypto_kx_keypair | |
| crypto_kx_seed_keypair | |
| crypto_kx_server_session_keys | |
| crypto_kx_client_session_keys | :heavy_check_mark: |
| crypto_kx_keypair | :heavy_check_mark: |
| crypto_kx_seed_keypair | :heavy_check_mark: |
| crypto_kx_server_session_keys | :heavy_check_mark: |
| crypto_onetimeauth | not present in LazySodium |
| crypto_onetimeauth_final | not present in LazySodium |
| crypto_onetimeauth_init | not present in LazySodium |
@ -99,8 +99,8 @@
| crypto_pwhash_str_verify | :heavy_check_mark: |
| crypto_scalarmult | |
| crypto_scalarmult_base | |
| crypto_scalarmult_ristretto255 | |
| crypto_scalarmult_ristretto255_base | |
| crypto_scalarmult_ristretto255 | not present in LazySodium |
| crypto_scalarmult_ristretto255_base | not present in LazySodium |
| crypto_secretbox_detached | :heavy_check_mark: |
| crypto_secretbox_easy | :heavy_check_mark: |
| crypto_secretbox_keygen | :heavy_check_mark: |
@ -135,7 +135,7 @@
| crypto_stream_chacha20_keygen | |
| crypto_stream_chacha20_xor | |
| crypto_stream_chacha20_xor_ic | |
| crypto_stream_keygen | |
| crypto_stream_keygen | Other XSalsa20 primitives are not available, so I'm leaving this out as well|
| crypto_stream_xchacha20_keygen | not present in LazySodium Android |
| crypto_stream_xchacha20_xor | not present in LazySodium Android|
| crypto_stream_xchacha20_xor_ic | not present in LazySodium Android |