Added secretbox functions and constants
This commit is contained in:
parent
555b69f15c
commit
99b9ee5e9d
@ -61,8 +61,9 @@ object Deps {
|
|||||||
val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.kotlinSerialization}"
|
val serialization = "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:${Versions.kotlinSerialization}"
|
||||||
|
|
||||||
object Npm {
|
object Npm {
|
||||||
val libsodium = Pair("libsodium-wrappers-sumo", "0.7.6")
|
val libsodium = Pair("libsodium-wrappers-sumo", "0.7.8")
|
||||||
val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "file:${getProjectPath()}/multiplatform-crypto-delegated/libsodium-wrappers-sumo-0.7.6.tgz")
|
//val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "file:${getProjectPath()}/multiplatform-crypto-delegated/libsodium-wrappers-sumo-0.7.6.tgz")
|
||||||
|
val libsodiumWrappers = Pair("libsodium-wrappers-sumo", "0.7.8")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.secretbox
|
||||||
|
|
||||||
|
import kotlin.js.JsName
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ugljesa Jovanovic
|
||||||
|
* ugljesa.jovanovic@ionspin.com
|
||||||
|
* on 29-Aug-2020
|
||||||
|
*/
|
||||||
|
|
||||||
|
val crypto_secretbox_KEYBYTES = 32
|
||||||
|
val crypto_secretbox_MACBYTES = 16
|
||||||
|
val crypto_secretbox_NONCEBYTES = 24
|
||||||
|
|
||||||
|
class SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey() : RuntimeException("MAC validation failed. Data is corrupted or tampered with.")
|
||||||
|
|
||||||
|
data class SecretBoxEncryptedDataAndTag(
|
||||||
|
@JsName("data")
|
||||||
|
val data: UByteArray, val tag: UByteArray)
|
||||||
|
|
||||||
|
expect object SecretBox {
|
||||||
|
|
||||||
|
fun easy(message : UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray
|
||||||
|
fun openEasy(ciphertext: UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray
|
||||||
|
|
||||||
|
fun detached(message: UByteArray, nonce: UByteArray, key: UByteArray) : SecretBoxEncryptedDataAndTag
|
||||||
|
fun openDetached(ciphertext: UByteArray, tag: UByteArray, nonce: UByteArray, key: UByteArray) : UByteArray
|
||||||
|
|
||||||
|
fun keygen() : UByteArray
|
||||||
|
}
|
@ -4,6 +4,8 @@ package com.ionspin.kotlin.crypto.secretstream
|
|||||||
* Created by Ugljesa Jovanovic
|
* Created by Ugljesa Jovanovic
|
||||||
* ugljesa.jovanovic@ionspin.com
|
* ugljesa.jovanovic@ionspin.com
|
||||||
* on 26-Aug-2020
|
* on 26-Aug-2020
|
||||||
|
*
|
||||||
|
* This file is named with Jvm suffix because of https://youtrack.jetbrains.com/issue/KT-21186
|
||||||
*/
|
*/
|
||||||
expect class SecretStreamState
|
expect class SecretStreamState
|
||||||
|
|
||||||
@ -20,6 +22,8 @@ val crypto_secretstream_xchacha20poly1305_HEADERBYTES = 24
|
|||||||
val crypto_secretstream_xchacha20poly1305_KEYBYTES = 32
|
val crypto_secretstream_xchacha20poly1305_KEYBYTES = 32
|
||||||
val crypto_secretstream_xchacha20poly1305_ABYTES = 17
|
val crypto_secretstream_xchacha20poly1305_ABYTES = 17
|
||||||
|
|
||||||
|
class SecretStreamCorrupedOrTamperedDataException() : RuntimeException("MAC validation failed. Data is corrupted or tampered with.")
|
||||||
|
|
||||||
expect object SecretStream {
|
expect object SecretStream {
|
||||||
|
|
||||||
fun xChaCha20Poly1305InitPush(key: UByteArray) : SecretStreamStateAndHeader
|
fun xChaCha20Poly1305InitPush(key: UByteArray) : SecretStreamStateAndHeader
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.secretbox
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer
|
||||||
|
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||||
|
import com.ionspin.kotlin.crypto.util.toHexString
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ugljesa Jovanovic
|
||||||
|
* ugljesa.jovanovic@ionspin.com
|
||||||
|
* on 29-Aug-2020
|
||||||
|
*/
|
||||||
|
class SecretBoxTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun secretBoxTestEasy() {
|
||||||
|
LibsodiumInitializer.initializeWithCallback {
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
val key = ubyteArrayOf(
|
||||||
|
0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
|
||||||
|
0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU,
|
||||||
|
0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
|
||||||
|
0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU,
|
||||||
|
)
|
||||||
|
|
||||||
|
val nonce = ubyteArrayOf(
|
||||||
|
0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
|
||||||
|
0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU,
|
||||||
|
0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
|
||||||
|
)
|
||||||
|
|
||||||
|
val encrypted = SecretBox.easy(message, nonce, key)
|
||||||
|
val decrypted = SecretBox.openEasy(encrypted, nonce, key)
|
||||||
|
assertTrue { decrypted.contentEquals(message) }
|
||||||
|
assertFailsWith(SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey::class) {
|
||||||
|
val tamperedTag = encrypted.copyOf()
|
||||||
|
tamperedTag[2] = 0U
|
||||||
|
SecretBox.openEasy(tamperedTag, nonce, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun secretBoxTestDetached() {
|
||||||
|
LibsodiumInitializer.initializeWithCallback {
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
val key = ubyteArrayOf(
|
||||||
|
0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U,
|
||||||
|
0x88U, 0x89U, 0x8aU, 0x8bU, 0x8cU, 0x8dU, 0x8eU, 0x8fU,
|
||||||
|
0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U,
|
||||||
|
0x98U, 0x99U, 0x9aU, 0x9bU, 0x9cU, 0x9dU, 0x9eU, 0x9fU,
|
||||||
|
)
|
||||||
|
|
||||||
|
val nonce = ubyteArrayOf(
|
||||||
|
0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U,
|
||||||
|
0x48U, 0x49U, 0x4aU, 0x4bU, 0x4cU, 0x4dU, 0x4eU, 0x4fU,
|
||||||
|
0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U,
|
||||||
|
)
|
||||||
|
|
||||||
|
println("Debug")
|
||||||
|
val encrypted = SecretBox.detached(message, nonce, key)
|
||||||
|
val decrypted = SecretBox.openDetached(encrypted.data, encrypted.tag, nonce, key)
|
||||||
|
assertTrue { decrypted.contentEquals(message) }
|
||||||
|
assertFailsWith(SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey::class) {
|
||||||
|
val tamperedTag = encrypted.tag.copyOf()
|
||||||
|
tamperedTag[2] = 0U
|
||||||
|
SecretBox.openDetached(encrypted.data, tamperedTag, nonce, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import com.ionspin.kotlin.crypto.LibsodiumInitializer
|
|||||||
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
import com.ionspin.kotlin.crypto.util.encodeToUByteArray
|
||||||
import com.ionspin.kotlin.crypto.util.testBlocking
|
import com.ionspin.kotlin.crypto.util.testBlocking
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,7 +72,12 @@ class SecretStreamTest {
|
|||||||
decrypted.decryptedData.hexColumsPrint()
|
decrypted.decryptedData.hexColumsPrint()
|
||||||
assertTrue {
|
assertTrue {
|
||||||
decrypted.decryptedData.contentEquals(message)
|
decrypted.decryptedData.contentEquals(message)
|
||||||
|
}
|
||||||
|
assertFailsWith(SecretStreamCorrupedOrTamperedDataException::class) {
|
||||||
|
encrypted[encrypted.size - 5] = 0U
|
||||||
|
val decryptState = SecretStream.xChaCha20Poly1305InitPull(key, stateAndHeader.header)
|
||||||
|
val decrypted =
|
||||||
|
SecretStream.xChaCha20Poly1305Pull(decryptState.state, encrypted, ubyteArrayOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,7 +86,8 @@ class SecretStreamTest {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// TODO modify nonce in state so we can have reproducible tests, theres already a similar way of doing this
|
||||||
|
// in crypto delegated project XChaCha20Poly1305 test
|
||||||
expect fun modifyState(state: SecretStreamState, forceNonce: UByteArray)
|
expect fun modifyState(state: SecretStreamState, forceNonce: UByteArray)
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +61,16 @@ interface JsSodiumInterface {
|
|||||||
fun crypto_secretstream_xchacha20poly1305_keygen() : Uint8Array
|
fun crypto_secretstream_xchacha20poly1305_keygen() : Uint8Array
|
||||||
fun crypto_secretstream_xchacha20poly1305_rekey(state: dynamic)
|
fun crypto_secretstream_xchacha20poly1305_rekey(state: dynamic)
|
||||||
|
|
||||||
|
// ---- SecretBox ----
|
||||||
|
fun crypto_secretbox_detached(message: Uint8Array, nonce: Uint8Array, key: Uint8Array) : dynamic
|
||||||
|
fun crypto_secretbox_easy(message: Uint8Array, nonce: Uint8Array, key: Uint8Array) : Uint8Array
|
||||||
|
fun crypto_secretbox_keygen() : Uint8Array
|
||||||
|
fun crypto_secretbox_open_detached(ciphertext : Uint8Array, tag : Uint8Array, nonce: Uint8Array, key: Uint8Array) : dynamic
|
||||||
|
fun crypto_secretbox_open_easy(ciphertext : Uint8Array, nonce: Uint8Array, key: Uint8Array) : dynamic
|
||||||
|
|
||||||
|
|
||||||
|
// ---- SecretBox End ----
|
||||||
|
|
||||||
//util
|
//util
|
||||||
fun memzero(array: Uint8Array)
|
fun memzero(array: Uint8Array)
|
||||||
|
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.secretbox
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.getSodium
|
||||||
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray
|
||||||
|
import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array
|
||||||
|
import org.khronos.webgl.Uint8Array
|
||||||
|
|
||||||
|
actual object SecretBox {
|
||||||
|
actual fun easy(message: UByteArray, nonce: UByteArray, key: UByteArray): UByteArray {
|
||||||
|
return getSodium().crypto_secretbox_easy(
|
||||||
|
message.toUInt8Array(),
|
||||||
|
nonce.toUInt8Array(),
|
||||||
|
key.toUInt8Array()
|
||||||
|
).toUByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openEasy(
|
||||||
|
ciphertext: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
try {
|
||||||
|
val decryptionResult = getSodium().crypto_secretbox_open_easy(
|
||||||
|
ciphertext.toUInt8Array(),
|
||||||
|
nonce.toUInt8Array(),
|
||||||
|
key.toUInt8Array()
|
||||||
|
)
|
||||||
|
return (decryptionResult as Uint8Array).toUByteArray()
|
||||||
|
} catch (error: Throwable) {
|
||||||
|
throw SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun detached(
|
||||||
|
message: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): SecretBoxEncryptedDataAndTag {
|
||||||
|
val result = getSodium().crypto_secretbox_detached(
|
||||||
|
message.toUInt8Array(),
|
||||||
|
nonce.toUInt8Array(),
|
||||||
|
key.toUInt8Array()
|
||||||
|
)
|
||||||
|
return SecretBoxEncryptedDataAndTag(
|
||||||
|
(result.cipher as Uint8Array).toUByteArray(),
|
||||||
|
(result.mac as Uint8Array).toUByteArray()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openDetached(
|
||||||
|
ciphertext: UByteArray,
|
||||||
|
tag: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
try {
|
||||||
|
val decryptionResult = getSodium().crypto_secretbox_open_detached(
|
||||||
|
ciphertext.toUInt8Array(),
|
||||||
|
tag.toUInt8Array(),
|
||||||
|
nonce.toUInt8Array(),
|
||||||
|
key.toUInt8Array()
|
||||||
|
)
|
||||||
|
return (decryptionResult as Uint8Array).toUByteArray()
|
||||||
|
} catch (error: Throwable) {
|
||||||
|
throw SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun keygen(): UByteArray {
|
||||||
|
return getSodium().crypto_secretbox_keygen().toUByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -40,6 +40,9 @@ actual object SecretStream {
|
|||||||
val dataAndTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(
|
val dataAndTag = getSodium().crypto_secretstream_xchacha20poly1305_pull(
|
||||||
state, ciphertext.toUInt8Array(), additionalData.toUInt8Array()
|
state, ciphertext.toUInt8Array(), additionalData.toUInt8Array()
|
||||||
)
|
)
|
||||||
|
if (dataAndTag == false) {
|
||||||
|
throw SecretStreamCorrupedOrTamperedDataException()
|
||||||
|
}
|
||||||
return DecryptedDataAndTag((dataAndTag.message as Uint8Array).toUByteArray(), dataAndTag.tag)
|
return DecryptedDataAndTag((dataAndTag.message as Uint8Array).toUByteArray(), dataAndTag.tag)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.secretbox
|
||||||
|
|
||||||
|
import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium
|
||||||
|
|
||||||
|
actual object SecretBox {
|
||||||
|
actual fun easy(message: UByteArray, nonce: UByteArray, key: UByteArray): UByteArray {
|
||||||
|
val ciphertext = UByteArray(message.size + crypto_secretbox_MACBYTES)
|
||||||
|
sodium.crypto_secretbox_easy(
|
||||||
|
ciphertext.asByteArray(),
|
||||||
|
message.asByteArray(),
|
||||||
|
message.size.toLong(),
|
||||||
|
nonce.asByteArray(),
|
||||||
|
key.asByteArray()
|
||||||
|
)
|
||||||
|
return ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openEasy(
|
||||||
|
ciphertext: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val decrypted = UByteArray(ciphertext.size - crypto_secretbox_MACBYTES)
|
||||||
|
val validationResult = sodium.crypto_secretbox_open_easy(
|
||||||
|
decrypted.asByteArray(),
|
||||||
|
ciphertext.asByteArray(),
|
||||||
|
ciphertext.size.toLong(),
|
||||||
|
nonce.asByteArray(),
|
||||||
|
key.asByteArray()
|
||||||
|
)
|
||||||
|
if (validationResult != 0) {
|
||||||
|
throw SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey()
|
||||||
|
}
|
||||||
|
return decrypted
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun detached(
|
||||||
|
message: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): SecretBoxEncryptedDataAndTag {
|
||||||
|
val ciphertext = UByteArray(message.size)
|
||||||
|
val authenticationTag = UByteArray(crypto_secretbox_MACBYTES)
|
||||||
|
sodium.crypto_secretbox_detached(
|
||||||
|
ciphertext.asByteArray(),
|
||||||
|
authenticationTag.asByteArray(),
|
||||||
|
message.asByteArray(),
|
||||||
|
message.size.toLong(),
|
||||||
|
nonce.asByteArray(),
|
||||||
|
key.asByteArray()
|
||||||
|
)
|
||||||
|
return SecretBoxEncryptedDataAndTag(ciphertext, authenticationTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openDetached(
|
||||||
|
ciphertext: UByteArray,
|
||||||
|
tag: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val message = UByteArray(ciphertext.size)
|
||||||
|
val validationResult = sodium.crypto_secretbox_open_detached(
|
||||||
|
message.asByteArray(),
|
||||||
|
ciphertext.asByteArray(),
|
||||||
|
tag.asByteArray(),
|
||||||
|
ciphertext.size.toLong(),
|
||||||
|
nonce.asByteArray(),
|
||||||
|
key.asByteArray()
|
||||||
|
)
|
||||||
|
if (validationResult != 0) {
|
||||||
|
throw SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey()
|
||||||
|
}
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun keygen() : UByteArray {
|
||||||
|
val generatedKey = UByteArray(crypto_secretbox_KEYBYTES)
|
||||||
|
sodium.crypto_secretbox_keygen(generatedKey.asByteArray())
|
||||||
|
return generatedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -49,7 +49,7 @@ actual object SecretStream {
|
|||||||
): DecryptedDataAndTag {
|
): DecryptedDataAndTag {
|
||||||
val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES)
|
val result = UByteArray(ciphertext.size - crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
val tagArray = UByteArray(1) { 0U }
|
val tagArray = UByteArray(1) { 0U }
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_pull(
|
val validationResult = sodium.crypto_secretstream_xchacha20poly1305_pull(
|
||||||
state,
|
state,
|
||||||
result.asByteArray(),
|
result.asByteArray(),
|
||||||
null,
|
null,
|
||||||
@ -59,11 +59,14 @@ actual object SecretStream {
|
|||||||
additionalData.asByteArray(),
|
additionalData.asByteArray(),
|
||||||
additionalData.size.toLong()
|
additionalData.size.toLong()
|
||||||
)
|
)
|
||||||
|
if (validationResult != 0) {
|
||||||
|
throw SecretStreamCorrupedOrTamperedDataException()
|
||||||
|
}
|
||||||
return DecryptedDataAndTag(result, tagArray[0])
|
return DecryptedDataAndTag(result, tagArray[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun xChaCha20Poly1305Keygen(): UByteArray {
|
actual fun xChaCha20Poly1305Keygen(): UByteArray {
|
||||||
val generatedKey = UByteArray(crypto_aead_xchacha20poly1305_ietf_KEYBYTES)
|
val generatedKey = UByteArray(crypto_secretstream_xchacha20poly1305_KEYBYTES)
|
||||||
sodium.crypto_secretstream_xchacha20poly1305_keygen(generatedKey.asByteArray())
|
sodium.crypto_secretstream_xchacha20poly1305_keygen(generatedKey.asByteArray())
|
||||||
return generatedKey
|
return generatedKey
|
||||||
}
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
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
|
||||||
|
import libsodium.crypto_secretbox_detached
|
||||||
|
import libsodium.crypto_secretbox_easy
|
||||||
|
import libsodium.crypto_secretbox_keygen
|
||||||
|
import libsodium.crypto_secretbox_open_detached
|
||||||
|
import libsodium.crypto_secretbox_open_easy
|
||||||
|
|
||||||
|
actual object SecretBox {
|
||||||
|
actual fun easy(message: UByteArray, nonce: UByteArray, key: UByteArray): UByteArray {
|
||||||
|
val ciphertext = UByteArray(message.size + crypto_secretbox_MACBYTES)
|
||||||
|
val ciphertextPinned = ciphertext.pin()
|
||||||
|
val messagePinned = message.pin()
|
||||||
|
val noncePinned = nonce.pin()
|
||||||
|
val keyPinned = key.pin()
|
||||||
|
crypto_secretbox_easy(
|
||||||
|
ciphertextPinned.toPtr(),
|
||||||
|
messagePinned.toPtr(),
|
||||||
|
message.size.convert(),
|
||||||
|
noncePinned.toPtr(),
|
||||||
|
keyPinned.toPtr()
|
||||||
|
)
|
||||||
|
ciphertextPinned.unpin()
|
||||||
|
messagePinned.unpin()
|
||||||
|
noncePinned.unpin()
|
||||||
|
keyPinned.unpin()
|
||||||
|
return ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openEasy(
|
||||||
|
ciphertext: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val message = UByteArray(ciphertext.size - crypto_secretbox_MACBYTES)
|
||||||
|
val messagePinned = message.pin()
|
||||||
|
val ciphertextPinned = ciphertext.pin()
|
||||||
|
val noncePinned = nonce.pin()
|
||||||
|
val keyPinned = key.pin()
|
||||||
|
val verificationResult = crypto_secretbox_open_easy(
|
||||||
|
messagePinned.toPtr(),
|
||||||
|
ciphertextPinned.toPtr(),
|
||||||
|
ciphertext.size.convert(),
|
||||||
|
noncePinned.toPtr(),
|
||||||
|
keyPinned.toPtr()
|
||||||
|
)
|
||||||
|
ciphertextPinned.unpin()
|
||||||
|
messagePinned.unpin()
|
||||||
|
noncePinned.unpin()
|
||||||
|
keyPinned.unpin()
|
||||||
|
if (verificationResult != 0) {
|
||||||
|
throw SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey()
|
||||||
|
}
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun detached(
|
||||||
|
message: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): SecretBoxEncryptedDataAndTag {
|
||||||
|
val ciphertext = UByteArray(message.size)
|
||||||
|
val authenticationTag = UByteArray(crypto_secretbox_MACBYTES)
|
||||||
|
val ciphertextPinned = ciphertext.pin()
|
||||||
|
val authenticationTagPinned = authenticationTag.pin()
|
||||||
|
val messagePinned = message.pin()
|
||||||
|
val noncePinned = nonce.pin()
|
||||||
|
val keyPinned = key.pin()
|
||||||
|
crypto_secretbox_detached(
|
||||||
|
ciphertextPinned.toPtr(),
|
||||||
|
authenticationTagPinned.toPtr(),
|
||||||
|
messagePinned.toPtr(),
|
||||||
|
message.size.convert(),
|
||||||
|
noncePinned.toPtr(),
|
||||||
|
keyPinned.toPtr()
|
||||||
|
)
|
||||||
|
ciphertextPinned.unpin()
|
||||||
|
authenticationTagPinned.unpin()
|
||||||
|
messagePinned.unpin()
|
||||||
|
noncePinned.unpin()
|
||||||
|
keyPinned.unpin()
|
||||||
|
return SecretBoxEncryptedDataAndTag(ciphertext, authenticationTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun openDetached(
|
||||||
|
ciphertext: UByteArray,
|
||||||
|
tag: UByteArray,
|
||||||
|
nonce: UByteArray,
|
||||||
|
key: UByteArray
|
||||||
|
): UByteArray {
|
||||||
|
val message = UByteArray(ciphertext.size)
|
||||||
|
val messagePinned = message.pin()
|
||||||
|
val ciphertextPinned = ciphertext.pin()
|
||||||
|
val tagPinned = tag.pin()
|
||||||
|
val noncePinned = nonce.pin()
|
||||||
|
val keyPinned = key.pin()
|
||||||
|
val verificationResult = crypto_secretbox_open_detached(
|
||||||
|
messagePinned.toPtr(),
|
||||||
|
ciphertextPinned.toPtr(),
|
||||||
|
tagPinned.toPtr(),
|
||||||
|
ciphertext.size.convert(),
|
||||||
|
noncePinned.toPtr(),
|
||||||
|
keyPinned.toPtr()
|
||||||
|
)
|
||||||
|
ciphertextPinned.unpin()
|
||||||
|
messagePinned.unpin()
|
||||||
|
noncePinned.unpin()
|
||||||
|
keyPinned.unpin()
|
||||||
|
if (verificationResult != 0) {
|
||||||
|
throw SecretBoxCorruptedOrTamperedDataExceptionOrInvalidKey()
|
||||||
|
}
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun keygen() :UByteArray {
|
||||||
|
val generatedKey = UByteArray(crypto_secretbox_KEYBYTES)
|
||||||
|
val generatedKeyPinned = generatedKey.pin()
|
||||||
|
crypto_secretbox_keygen(generatedKeyPinned.toPtr())
|
||||||
|
generatedKeyPinned.unpin()
|
||||||
|
return generatedKey
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -101,7 +101,7 @@ actual object SecretStream {
|
|||||||
}
|
}
|
||||||
val tag = UByteArray(1) { 0U }
|
val tag = UByteArray(1) { 0U }
|
||||||
val tagPinned = tag.pin()
|
val tagPinned = tag.pin()
|
||||||
val validTag = crypto_secretstream_xchacha20poly1305_pull(
|
val validationResult = crypto_secretstream_xchacha20poly1305_pull(
|
||||||
state.ptr,
|
state.ptr,
|
||||||
messagePinned.toPtr(),
|
messagePinned.toPtr(),
|
||||||
null,
|
null,
|
||||||
@ -115,8 +115,8 @@ actual object SecretStream {
|
|||||||
messagePinned.unpin()
|
messagePinned.unpin()
|
||||||
additionalDataPinned?.unpin()
|
additionalDataPinned?.unpin()
|
||||||
tagPinned.unpin()
|
tagPinned.unpin()
|
||||||
if (validTag != 0) {
|
if (validationResult != 0) {
|
||||||
throw RuntimeException("Invalid tag")
|
throw SecretStreamCorrupedOrTamperedDataException()
|
||||||
}
|
}
|
||||||
return DecryptedDataAndTag(message, tag[0])
|
return DecryptedDataAndTag(message, tag[0])
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.ionspin.kotlin.crypto.util
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ugljesa Jovanovic
|
||||||
|
* ugljesa.jovanovic@ionspin.com
|
||||||
|
* on 29-Aug-2020
|
||||||
|
*/
|
||||||
|
//fun randomBytesBuf()
|
@ -102,19 +102,19 @@
|
|||||||
| crypto_scalarmult_base | |
|
| crypto_scalarmult_base | |
|
||||||
| crypto_scalarmult_ristretto255 | |
|
| crypto_scalarmult_ristretto255 | |
|
||||||
| crypto_scalarmult_ristretto255_base | |
|
| crypto_scalarmult_ristretto255_base | |
|
||||||
| crypto_secretbox_detached | |
|
| crypto_secretbox_detached | :heavy_check_mark: |
|
||||||
| crypto_secretbox_easy | |
|
| crypto_secretbox_easy | :heavy_check_mark: |
|
||||||
| crypto_secretbox_keygen | |
|
| crypto_secretbox_keygen | :heavy_check_mark: |
|
||||||
| crypto_secretbox_open_detached | |
|
| crypto_secretbox_open_detached | :heavy_check_mark: |
|
||||||
| crypto_secretbox_open_easy | |
|
| crypto_secretbox_open_easy | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_init_pull | :heavy_check_mark: | DONE
|
| crypto_secretstream_xchacha20poly1305_init_pull | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_init_push | :heavy_check_mark: | DONE
|
| crypto_secretstream_xchacha20poly1305_init_push | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_keygen | :heavy_check_mark: | DONE
|
| crypto_secretstream_xchacha20poly1305_keygen | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_pull | :heavy_check_mark: | DONE
|
| crypto_secretstream_xchacha20poly1305_pull | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_push | :heavy_check_mark: | DONE
|
| crypto_secretstream_xchacha20poly1305_push | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_rekey | :heavy_check_mark: | DONE
|
| crypto_secretstream_xchacha20poly1305_rekey | :heavy_check_mark: |
|
||||||
| crypto_shorthash |:heavy_check_mark: | DONE
|
| crypto_shorthash |:heavy_check_mark: |
|
||||||
| crypto_shorthash_keygen | :heavy_check_mark: | DONE
|
| crypto_shorthash_keygen | :heavy_check_mark: |
|
||||||
| crypto_shorthash_siphashx24 | |
|
| crypto_shorthash_siphashx24 | |
|
||||||
| crypto_sign | |
|
| crypto_sign | |
|
||||||
| crypto_sign_detached | |
|
| crypto_sign_detached | |
|
||||||
@ -310,10 +310,10 @@
|
|||||||
| crypto_scalarmult_ed25519_SCALARBYTES | |
|
| crypto_scalarmult_ed25519_SCALARBYTES | |
|
||||||
| crypto_scalarmult_ristretto255_BYTES | |
|
| crypto_scalarmult_ristretto255_BYTES | |
|
||||||
| crypto_scalarmult_ristretto255_SCALARBYTES | |
|
| crypto_scalarmult_ristretto255_SCALARBYTES | |
|
||||||
| crypto_secretbox_KEYBYTES | |
|
| crypto_secretbox_KEYBYTES | :heavy_check_mark: |
|
||||||
| crypto_secretbox_MACBYTES | |
|
| crypto_secretbox_MACBYTES | :heavy_check_mark: |
|
||||||
| crypto_secretbox_MESSAGEBYTES_MAX | |
|
| crypto_secretbox_MESSAGEBYTES_MAX | |
|
||||||
| crypto_secretbox_NONCEBYTES | |
|
| crypto_secretbox_NONCEBYTES | :heavy_check_mark: |
|
||||||
| crypto_secretbox_xchacha20poly1305_KEYBYTES | |
|
| crypto_secretbox_xchacha20poly1305_KEYBYTES | |
|
||||||
| crypto_secretbox_xchacha20poly1305_MACBYTES | |
|
| crypto_secretbox_xchacha20poly1305_MACBYTES | |
|
||||||
| crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX | |
|
| crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX | |
|
||||||
@ -322,14 +322,14 @@
|
|||||||
| crypto_secretbox_xsalsa20poly1305_MACBYTES | |
|
| crypto_secretbox_xsalsa20poly1305_MACBYTES | |
|
||||||
| crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX | |
|
| crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX | |
|
||||||
| crypto_secretbox_xsalsa20poly1305_NONCEBYTES | |
|
| crypto_secretbox_xsalsa20poly1305_NONCEBYTES | |
|
||||||
| crypto_secretstream_xchacha20poly1305_ABYTES | |
|
| crypto_secretstream_xchacha20poly1305_ABYTES | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_HEADERBYTES | |
|
| crypto_secretstream_xchacha20poly1305_HEADERBYTES | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_KEYBYTES | |
|
| crypto_secretstream_xchacha20poly1305_KEYBYTES | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX | |
|
| crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX | |
|
||||||
| crypto_secretstream_xchacha20poly1305_TAG_FINAL | |
|
| crypto_secretstream_xchacha20poly1305_TAG_FINAL | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_TAG_MESSAGE | |
|
| crypto_secretstream_xchacha20poly1305_TAG_MESSAGE | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_TAG_PUSH | |
|
| crypto_secretstream_xchacha20poly1305_TAG_PUSH | :heavy_check_mark: |
|
||||||
| crypto_secretstream_xchacha20poly1305_TAG_REKEY | |
|
| crypto_secretstream_xchacha20poly1305_TAG_REKEY | :heavy_check_mark: |
|
||||||
| crypto_shorthash_BYTES | |
|
| crypto_shorthash_BYTES | |
|
||||||
| crypto_shorthash_KEYBYTES | |
|
| crypto_shorthash_KEYBYTES | |
|
||||||
| crypto_shorthash_siphash24_BYTES | |
|
| crypto_shorthash_siphash24_BYTES | |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user