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_hash_sha512_update | :heavy_check_mark: |
|
||||||
| crypto_kdf_derive_from_key | :heavy_check_mark: |
|
| crypto_kdf_derive_from_key | :heavy_check_mark: |
|
||||||
| crypto_kdf_keygen | :heavy_check_mark: |
|
| crypto_kdf_keygen | :heavy_check_mark: |
|
||||||
| crypto_kx_client_session_keys | |
|
| crypto_kx_client_session_keys | :heavy_check_mark: |
|
||||||
| crypto_kx_keypair | |
|
| crypto_kx_keypair | :heavy_check_mark: |
|
||||||
| crypto_kx_seed_keypair | |
|
| crypto_kx_seed_keypair | :heavy_check_mark: |
|
||||||
| crypto_kx_server_session_keys | |
|
| crypto_kx_server_session_keys | :heavy_check_mark: |
|
||||||
| crypto_onetimeauth | not present in LazySodium |
|
| crypto_onetimeauth | not present in LazySodium |
|
||||||
| crypto_onetimeauth_final | not present in LazySodium |
|
| crypto_onetimeauth_final | not present in LazySodium |
|
||||||
| crypto_onetimeauth_init | not present in LazySodium |
|
| crypto_onetimeauth_init | not present in LazySodium |
|
||||||
@ -99,8 +99,8 @@
|
|||||||
| crypto_pwhash_str_verify | :heavy_check_mark: |
|
| crypto_pwhash_str_verify | :heavy_check_mark: |
|
||||||
| crypto_scalarmult | |
|
| crypto_scalarmult | |
|
||||||
| crypto_scalarmult_base | |
|
| crypto_scalarmult_base | |
|
||||||
| crypto_scalarmult_ristretto255 | |
|
| crypto_scalarmult_ristretto255 | not present in LazySodium |
|
||||||
| crypto_scalarmult_ristretto255_base | |
|
| crypto_scalarmult_ristretto255_base | not present in LazySodium |
|
||||||
| crypto_secretbox_detached | :heavy_check_mark: |
|
| crypto_secretbox_detached | :heavy_check_mark: |
|
||||||
| crypto_secretbox_easy | :heavy_check_mark: |
|
| crypto_secretbox_easy | :heavy_check_mark: |
|
||||||
| crypto_secretbox_keygen | :heavy_check_mark: |
|
| crypto_secretbox_keygen | :heavy_check_mark: |
|
||||||
@ -135,7 +135,7 @@
|
|||||||
| crypto_stream_chacha20_keygen | |
|
| crypto_stream_chacha20_keygen | |
|
||||||
| crypto_stream_chacha20_xor | |
|
| crypto_stream_chacha20_xor | |
|
||||||
| crypto_stream_chacha20_xor_ic | |
|
| 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_keygen | not present in LazySodium Android |
|
||||||
| crypto_stream_xchacha20_xor | not present in LazySodium Android|
|
| crypto_stream_xchacha20_xor | not present in LazySodium Android|
|
||||||
| crypto_stream_xchacha20_xor_ic | not present in LazySodium Android |
|
| crypto_stream_xchacha20_xor_ic | not present in LazySodium Android |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user