Working single shot xchacha20poly1305 encryption and decryption in delegated flavour
This commit is contained in:
parent
6228263978
commit
e6f560ba8e
@ -5,6 +5,8 @@ package com.ionspin.kotlin.crypto.util
|
|||||||
* ugljesa.jovanovic@ionspin.com
|
* ugljesa.jovanovic@ionspin.com
|
||||||
* on 22-Jun-2020
|
* on 22-Jun-2020
|
||||||
*/
|
*/
|
||||||
|
val _emit = IntArray(0)
|
||||||
|
|
||||||
fun UByteArray.overwriteWithZeroes() {
|
fun UByteArray.overwriteWithZeroes() {
|
||||||
for (i in 0 until size) {
|
for (i in 0 until size) {
|
||||||
this[i] = 0U
|
this[i] = 0U
|
||||||
@ -15,4 +17,4 @@ fun UIntArray.overwriteWithZeroes() {
|
|||||||
for (i in 0 until size) {
|
for (i in 0 until size) {
|
||||||
this[i] = 0U
|
this[i] = 0U
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,19 +15,16 @@ import com.ionspin.kotlin.crypto.keyderivation.ArgonResult
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
object CryptoInitializerDelegated : CryptoInitializer {
|
object CryptoInitializerDelegated : CryptoInitializer {
|
||||||
private var initialized = false
|
|
||||||
override suspend fun initialize() {
|
override suspend fun initialize() {
|
||||||
Initializer.initialize()
|
Initializer.initialize()
|
||||||
initialized = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializeWithCallback(done: () -> Unit) {
|
fun initializeWithCallback(done: () -> Unit) {
|
||||||
initialized = true
|
|
||||||
Initializer.initializeWithCallback(done)
|
Initializer.initializeWithCallback(done)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isInitialized(): Boolean {
|
override fun isInitialized(): Boolean {
|
||||||
return initialized
|
return Initializer.isInitialized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package com.ionspin.kotlin.crypto.authenticated
|
|||||||
|
|
||||||
import com.ionspin.kotlin.crypto.CryptoInitializerDelegated
|
import com.ionspin.kotlin.crypto.CryptoInitializerDelegated
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
||||||
|
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -18,10 +19,9 @@ class XChaCha20Poly1305Test {
|
|||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun xChaCha20Poly1305() {
|
fun xChaCha20Poly1305() = testBlocking {
|
||||||
testBlocking {
|
CryptoInitializerDelegated.initialize()
|
||||||
CryptoInitializerDelegated.initialize()
|
|
||||||
}
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
|
val message = ("Ladies and Gentlemen of the class of '99: If I could offer you " +
|
||||||
"only one tip for the future, sunscreen would be it.").encodeToUByteArray()
|
"only one tip for the future, sunscreen would be it.").encodeToUByteArray()
|
||||||
@ -62,9 +62,12 @@ class XChaCha20Poly1305Test {
|
|||||||
0xcfU, 0x49U
|
0xcfU, 0x49U
|
||||||
)
|
)
|
||||||
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData)
|
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData)
|
||||||
// val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData)
|
encrypted.hexColumsPrint()
|
||||||
|
val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData)
|
||||||
encrypted.contentEquals(expected) // && decrypted.contentEquals(message)
|
println("Decrypted")
|
||||||
|
decrypted.hexColumsPrint()
|
||||||
|
println("----------")
|
||||||
|
encrypted.contentEquals(expected) && decrypted.contentEquals(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue {
|
assertTrue {
|
||||||
@ -91,9 +94,9 @@ class XChaCha20Poly1305Test {
|
|||||||
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
|
0x84U, 0x6fU, 0xfcU, 0x75U, 0x31U, 0xbfU, 0x0cU, 0x2dU
|
||||||
)
|
)
|
||||||
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData)
|
val encrypted = XChaCha20Poly1305Delegated.encrypt(key, nonce, message, additionalData)
|
||||||
// val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData)
|
val decrypted = XChaCha20Poly1305Delegated.decrypt(key, nonce, encrypted, additionalData)
|
||||||
|
|
||||||
encrypted.contentEquals(expected) // && decrypted.contentEquals(message)
|
encrypted.contentEquals(expected) && decrypted.contentEquals(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +40,8 @@ interface JsSodiumInterface {
|
|||||||
fun crypto_hash_sha512_final(state: dynamic): Uint8Array
|
fun crypto_hash_sha512_final(state: dynamic): Uint8Array
|
||||||
|
|
||||||
//XChaCha20Poly1305
|
//XChaCha20Poly1305
|
||||||
fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, additionalData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
fun crypto_aead_xchacha20poly1305_ietf_encrypt(message: Uint8Array, additionalData: Uint8Array, secretNonce: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
||||||
|
fun crypto_aead_xchacha20poly1305_ietf_decrypt(secretNonce: Uint8Array, ciphertext: Uint8Array, additionalData: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@ import org.khronos.webgl.set
|
|||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
* ugljesa.jovanovic@ionspin.com
|
* ugljesa.jovanovic@ionspin.com
|
||||||
* on 25-Jun-2020
|
* on 25-Jun-2020
|
||||||
|
*
|
||||||
|
* TODO investigate using unsafe cast
|
||||||
*/
|
*/
|
||||||
fun UByteArray.toUInt8Array() : Uint8Array {
|
fun UByteArray.toUInt8Array() : Uint8Array {
|
||||||
val uint8Result = Uint8Array(toByteArray().toTypedArray())
|
val uint8Result = Uint8Array(toByteArray().toTypedArray())
|
||||||
console.log("Uint8: $uint8Result")
|
// console.log("Uint8: $uint8Result")
|
||||||
return uint8Result
|
return uint8Result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +23,7 @@ fun Uint8Array.toUByteArray() : UByteArray {
|
|||||||
for (i in 0 until length) {
|
for (i in 0 until length) {
|
||||||
result[i] = get(i).toUByte()
|
result[i] = get(i).toUByte()
|
||||||
}
|
}
|
||||||
console.log("UbyteArray: ${result.joinToString()}")
|
// console.log("UbyteArray: ${result.joinToString()}")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.ionspin.kotlin.crypto.authenticated
|
|||||||
import com.ionspin.kotlin.crypto.getSodium
|
import com.ionspin.kotlin.crypto.getSodium
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
||||||
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
||||||
|
import org.khronos.webgl.Uint8Array
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
@ -26,8 +27,9 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
val encrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt(
|
val encrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||||
message.toUInt8Array(),
|
message.toUInt8Array(),
|
||||||
additionalData.toUInt8Array(),
|
additionalData.toUInt8Array(),
|
||||||
key.toUInt8Array(),
|
Uint8Array(0),
|
||||||
nonce.toUInt8Array()
|
nonce.toUInt8Array(),
|
||||||
|
key.toUInt8Array()
|
||||||
)
|
)
|
||||||
return encrypted.toUByteArray()
|
return encrypted.toUByteArray()
|
||||||
}
|
}
|
||||||
@ -38,7 +40,14 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
ciphertext: UByteArray,
|
ciphertext: UByteArray,
|
||||||
additionalData: UByteArray
|
additionalData: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
TODO("not implemented yet")
|
val decrypted = getSodium().crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
|
Uint8Array(0),
|
||||||
|
ciphertext.toUInt8Array(),
|
||||||
|
additionalData.toUInt8Array(),
|
||||||
|
nonce.toUInt8Array(),
|
||||||
|
key.toUInt8Array()
|
||||||
|
)
|
||||||
|
return decrypted.toUByteArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,16 +38,15 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
ciphertext: UByteArray,
|
ciphertext: UByteArray,
|
||||||
additionalData: UByteArray
|
additionalData: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
val message = ByteArray(ciphertext.size - sodium.crypto_secretstream_xchacha20poly1305_abytes())
|
val message = ByteArray(ciphertext.size - 16)
|
||||||
SodiumJava().crypto_aead_xchacha20poly1305_ietf_encrypt(
|
SodiumJava().crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
|
|
||||||
message,
|
message,
|
||||||
longArrayOf(ciphertext.size.toLong()),
|
longArrayOf(ciphertext.size.toLong()),
|
||||||
|
null,
|
||||||
ciphertext.toByteArray(),
|
ciphertext.toByteArray(),
|
||||||
ciphertext.size.toLong(),
|
ciphertext.size.toLong(),
|
||||||
additionalData.toByteArray(),
|
additionalData.toByteArray(),
|
||||||
additionalData.size.toLong(),
|
additionalData.size.toLong(),
|
||||||
null,
|
|
||||||
nonce.toByteArray(),
|
nonce.toByteArray(),
|
||||||
key.toByteArray()
|
key.toByteArray()
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
|
@file:Suppress("VARIABLE_IN_SINGLETON_WITHOUT_THREAD_LOCAL")
|
||||||
|
|
||||||
package com.ionspin.kotlin.crypto
|
package com.ionspin.kotlin.crypto
|
||||||
|
|
||||||
import kotlinx.atomicfu.AtomicBoolean
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import libsodium.sodium_init
|
import libsodium.sodium_init
|
||||||
import kotlin.native.concurrent.AtomicInt
|
import kotlin.native.concurrent.AtomicInt
|
||||||
|
|
||||||
@ -29,4 +27,4 @@ actual object Initializer {
|
|||||||
actual fun isInitialized(): Boolean {
|
actual fun isInitialized(): Boolean {
|
||||||
return isPlatformInitialized.value != 0
|
return isPlatformInitialized.value != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import kotlinx.cinterop.convert
|
|||||||
import kotlinx.cinterop.pin
|
import kotlinx.cinterop.pin
|
||||||
import kotlinx.cinterop.toCValues
|
import kotlinx.cinterop.toCValues
|
||||||
import libsodium.crypto_aead_xchacha20poly1305_IETF_ABYTES
|
import libsodium.crypto_aead_xchacha20poly1305_IETF_ABYTES
|
||||||
|
import libsodium.crypto_aead_xchacha20poly1305_ietf_decrypt
|
||||||
import libsodium.crypto_aead_xchacha20poly1305_ietf_encrypt
|
import libsodium.crypto_aead_xchacha20poly1305_ietf_encrypt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +26,7 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
val ciphertextPinned = ciphertext.pin()
|
val ciphertextPinned = ciphertext.pin()
|
||||||
crypto_aead_xchacha20poly1305_ietf_encrypt(
|
crypto_aead_xchacha20poly1305_ietf_encrypt(
|
||||||
ciphertextPinned.addressOf(0),
|
ciphertextPinned.addressOf(0),
|
||||||
ciphertextLength.convert(),
|
ulongArrayOf(ciphertextLength.convert()).toCValues(),
|
||||||
message.toCValues(),
|
message.toCValues(),
|
||||||
message.size.convert(),
|
message.size.convert(),
|
||||||
additionalData.toCValues(),
|
additionalData.toCValues(),
|
||||||
@ -44,7 +45,22 @@ actual class XChaCha20Poly1305Delegated actual constructor(key: UByteArray, addi
|
|||||||
ciphertext: UByteArray,
|
ciphertext: UByteArray,
|
||||||
additionalData: UByteArray
|
additionalData: UByteArray
|
||||||
): UByteArray {
|
): UByteArray {
|
||||||
TODO("not implemented yet")
|
val messageLength = ciphertext.size - crypto_aead_xchacha20poly1305_IETF_ABYTES.toInt()
|
||||||
|
val message = UByteArray(messageLength)
|
||||||
|
val messagePinned = message.pin()
|
||||||
|
crypto_aead_xchacha20poly1305_ietf_decrypt(
|
||||||
|
messagePinned.addressOf(0),
|
||||||
|
ulongArrayOf(messageLength.convert()).toCValues(),
|
||||||
|
null,
|
||||||
|
ciphertext.toCValues(),
|
||||||
|
ciphertext.size.convert(),
|
||||||
|
additionalData.toCValues(),
|
||||||
|
additionalData.size.convert(),
|
||||||
|
nonce.toCValues(),
|
||||||
|
key.toCValues()
|
||||||
|
)
|
||||||
|
messagePinned.unpin()
|
||||||
|
return message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,6 @@ class XChaCha20Pure(key: UByteArray, nonce: UByteArray, initialCounter: UInt = 0
|
|||||||
)
|
)
|
||||||
keystreamRemainingCounter = 64 - remainingBytes
|
keystreamRemainingCounter = 64 - remainingBytes
|
||||||
processedBytesSoFar += data.size
|
processedBytesSoFar += data.size
|
||||||
state.overwriteWithZeroes()
|
|
||||||
return ciphertext
|
return ciphertext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.ionspin.kotlin.crypto.symmetric
|
package com.ionspin.kotlin.crypto.symmetric
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
||||||
|
import com.ionspin.kotlin.crypto.util.hexColumsPrint
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
@ -239,9 +240,9 @@ class XChaCha20Test {
|
|||||||
val firstChunk = xChaCha.xorWithKeystream(message.sliceArray(0 until 5))
|
val firstChunk = xChaCha.xorWithKeystream(message.sliceArray(0 until 5))
|
||||||
val secondChunk = xChaCha.xorWithKeystream(message.sliceArray(5 until 90))
|
val secondChunk = xChaCha.xorWithKeystream(message.sliceArray(5 until 90))
|
||||||
val thirdChunk = xChaCha.xorWithKeystream(message.sliceArray(90 until message.size))
|
val thirdChunk = xChaCha.xorWithKeystream(message.sliceArray(90 until message.size))
|
||||||
|
val result = firstChunk + secondChunk + thirdChunk
|
||||||
assertTrue {
|
assertTrue {
|
||||||
(firstChunk + secondChunk + thirdChunk).contentEquals(expected)
|
(result).contentEquals(expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package com.ionspin.kotlin.crypto.sample
|
package com.ionspin.kotlin.crypto.sample
|
||||||
|
|
||||||
import com.ionspin.kotlin.crypto.Crypto
|
import com.ionspin.kotlin.crypto.Crypto
|
||||||
|
import com.ionspin.kotlin.crypto.CryptoInitializerDelegated
|
||||||
|
import com.ionspin.kotlin.crypto.CryptoPrimitives
|
||||||
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.hash.encodeToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.toHexString
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
|
|
||||||
object Sample {
|
object Sample {
|
||||||
fun runSample() {
|
fun runSample() {
|
||||||
println("Initializing crypto library")
|
println("Initializing crypto library")
|
||||||
Crypto.initializeWithCallback {
|
CryptoInitializerDelegated.initializeWithCallback {
|
||||||
blake2b()
|
blake2b()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,11 +18,11 @@ object Sample {
|
|||||||
|
|
||||||
fun blake2b() {
|
fun blake2b() {
|
||||||
println("Blake2b updateable")
|
println("Blake2b updateable")
|
||||||
val blake2bUpdateable = Crypto.Blake2b.updateable()
|
val blake2bUpdateable = CryptoPrimitives.Blake2b.updateable()
|
||||||
blake2bUpdateable.update("test".encodeToUByteArray())
|
blake2bUpdateable.update("test".encodeToUByteArray())
|
||||||
println(blake2bUpdateable.digest().toHexString())
|
println(blake2bUpdateable.digest().toHexString())
|
||||||
println("Blake2b stateless")
|
println("Blake2b stateless")
|
||||||
val statelessResult = Crypto.Blake2b.stateless("test".encodeToByteArray().toUByteArray())
|
val statelessResult = CryptoPrimitives.Blake2b.stateless("test".encodeToByteArray().toUByteArray())
|
||||||
println("Blake2b stateless: ${statelessResult.toHexString()}")
|
println("Blake2b stateless: ${statelessResult.toHexString()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,5 @@
|
|||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bDelegated
|
|
||||||
import com.ionspin.kotlin.crypto.hash.blake2b.Blake2bStateless
|
|
||||||
import com.ionspin.kotlin.crypto.sample.Sample
|
import com.ionspin.kotlin.crypto.sample.Sample
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import platform.posix.pthread_self
|
|
||||||
import platform.posix.sleep
|
|
||||||
import kotlin.native.concurrent.TransferMode
|
|
||||||
import kotlin.native.concurrent.Worker
|
|
||||||
import kotlin.time.ExperimentalTime
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.measureTime
|
|
||||||
|
|
||||||
@ExperimentalTime
|
@ExperimentalTime
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user