Implemeting _stream_ primitives, at elast the ones available in lazy sodium
This commit is contained in:
parent
8d782d2932
commit
a18355adae
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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 |
|
||||
|
Loading…
x
Reference in New Issue
Block a user