From 91cd41c8c1ae780065774e52e620b6d6a6f665ee Mon Sep 17 00:00:00 2001 From: Ugljesa Jovanovic Date: Fri, 28 Aug 2020 22:35:33 +0200 Subject: [PATCH] Short hash implementation and test, updated cbc tests as they ignored padding --- js_checklist.txt | 395 ++++++++++++++++++ .../shortinputhash/ShortHash.kt | 15 + .../shortinputhash/ShortInputHashing.kt | 10 - .../com.ionspin.kotlin.crypto/util/Util.kt | 24 ++ .../kotlin/crypto/shorthash/ShortHashTest.kt | 41 ++ .../ionspin/kotlin/crypto/util/TestUtil.kt | 12 - .../kotlin/crypto/JsSodiumInterface.kt | 5 + .../kotlin/crypto/shortinputhash/ShortHash.kt | 21 + .../kotlin/crypto/shortinputhash/ShortHash.kt | 25 ++ .../kotlin/crypto/shortinputhash/ShortHash.kt | 35 ++ .../kotlin/crypto/symmetric/AesCtrPure.kt | 6 +- .../kotlin/crypto/symmetric/AesCbcTest.kt | 8 +- 12 files changed, 570 insertions(+), 27 deletions(-) create mode 100644 js_checklist.txt create mode 100644 multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortHash.kt delete mode 100644 multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortInputHashing.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/Util.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/shorthash/ShortHashTest.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt create mode 100644 multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt diff --git a/js_checklist.txt b/js_checklist.txt new file mode 100644 index 0000000..8c2bdc3 --- /dev/null +++ b/js_checklist.txt @@ -0,0 +1,395 @@ +add +base64_variants +ORIGINAL_NO_PADDING +URLSAFE +URLSAFE_NO_PADDING +compare +from_base64 +from_hex +from_string +increment +is_zero +libsodium +print +printErr +onRuntimeInitialized +useBackupModule +... +memcmp +memzero +output_formats +pad +unpad +ready +[[ +symbols +to_base64 +to_hex +to_string +crypto_aead_chacha20poly1305_decrypt +crypto_aead_chacha20poly1305_decrypt_detached +crypto_aead_chacha20poly1305_encrypt +crypto_aead_chacha20poly1305_encrypt_detached +crypto_aead_chacha20poly1305_ietf_decrypt +crypto_aead_chacha20poly1305_ietf_decrypt_detached +crypto_aead_chacha20poly1305_ietf_encrypt +crypto_aead_chacha20poly1305_ietf_encrypt_detached +crypto_aead_chacha20poly1305_ietf_keygen +crypto_aead_chacha20poly1305_keygen +crypto_aead_xchacha20poly1305_ietf_decrypt +crypto_aead_xchacha20poly1305_ietf_decrypt_detached +crypto_aead_xchacha20poly1305_ietf_encrypt +crypto_aead_xchacha20poly1305_ietf_encrypt_detached +crypto_aead_xchacha20poly1305_ietf_keygen +crypto_auth +crypto_auth_hmacsha256 +crypto_auth_hmacsha256_keygen +crypto_auth_hmacsha256_verify +crypto_auth_hmacsha512 +crypto_auth_hmacsha512_keygen +crypto_auth_hmacsha512_verify +crypto_auth_keygen +crypto_auth_verify +crypto_box_beforenm +crypto_box_curve25519xchacha20poly1305_keypair +crypto_box_curve25519xchacha20poly1305_seal +crypto_box_curve25519xchacha20poly1305_seal_open +crypto_box_detached +crypto_box_easy +crypto_box_easy_afternm +crypto_box_keypair +crypto_box_open_detached +crypto_box_open_easy +crypto_box_open_easy_afternm +crypto_box_seal +crypto_box_seal_open +crypto_box_seed_keypair +crypto_core_ristretto255_add +crypto_core_ristretto255_from_hash +crypto_core_ristretto255_is_valid_point +crypto_core_ristretto255_random +crypto_core_ristretto255_scalar_add +crypto_core_ristretto255_scalar_complement +crypto_core_ristretto255_scalar_invert +crypto_core_ristretto255_scalar_mul +crypto_core_ristretto255_scalar_negate +crypto_core_ristretto255_scalar_random +crypto_core_ristretto255_scalar_reduce +crypto_core_ristretto255_scalar_sub +crypto_core_ristretto255_sub +crypto_generichash DONE +crypto_generichash_blake2b_salt_personal +crypto_generichash_final DONE +crypto_generichash_init DONE +crypto_generichash_keygen +crypto_generichash_update DONE +crypto_hash +crypto_hash_sha256 +crypto_hash_sha256_final +crypto_hash_sha256_init +crypto_hash_sha256_update +crypto_hash_sha512 +crypto_hash_sha512_final +crypto_hash_sha512_init +crypto_hash_sha512_update +crypto_kdf_derive_from_key +crypto_kdf_keygen +crypto_kx_client_session_keys +crypto_kx_keypair +crypto_kx_seed_keypair +crypto_kx_server_session_keys +crypto_onetimeauth +crypto_onetimeauth_final +crypto_onetimeauth_init +crypto_onetimeauth_keygen +crypto_onetimeauth_update +crypto_onetimeauth_verify +crypto_pwhash +crypto_pwhash_scryptsalsa208sha256 +crypto_pwhash_scryptsalsa208sha256_ll +crypto_pwhash_scryptsalsa208sha256_str +crypto_pwhash_scryptsalsa208sha256_str_verify +crypto_pwhash_str +crypto_pwhash_str_needs_rehash +crypto_pwhash_str_verify +crypto_scalarmult +crypto_scalarmult_base +crypto_scalarmult_ristretto255 +crypto_scalarmult_ristretto255_base +crypto_secretbox_detached +crypto_secretbox_easy +crypto_secretbox_keygen +crypto_secretbox_open_detached +crypto_secretbox_open_easy +crypto_secretstream_xchacha20poly1305_init_pull DONE +crypto_secretstream_xchacha20poly1305_init_push DONE +crypto_secretstream_xchacha20poly1305_keygen +crypto_secretstream_xchacha20poly1305_pull DONE +crypto_secretstream_xchacha20poly1305_push DONE +crypto_secretstream_xchacha20poly1305_rekey +crypto_shorthash DONE +crypto_shorthash_keygen DONE +crypto_shorthash_siphashx24 +crypto_sign +crypto_sign_detached +crypto_sign_ed25519_pk_to_curve25519 +crypto_sign_ed25519_sk_to_curve25519 +crypto_sign_ed25519_sk_to_pk +crypto_sign_ed25519_sk_to_seed +crypto_sign_final_create +crypto_sign_final_verify +crypto_sign_init +crypto_sign_keypair +crypto_sign_open +crypto_sign_seed_keypair +crypto_sign_update +crypto_sign_verify_detached +crypto_stream_chacha20 +crypto_stream_chacha20_ietf_xor +crypto_stream_chacha20_ietf_xor_ic +crypto_stream_chacha20_keygen +crypto_stream_chacha20_xor +crypto_stream_chacha20_xor_ic +crypto_stream_keygen +crypto_stream_xchacha20_keygen +crypto_stream_xchacha20_xor +crypto_stream_xchacha20_xor_ic +randombytes_buf +randombytes_buf_deterministic +randombytes_close +randombytes_random +randombytes_stir +randombytes_uniform +sodium_version_string +SODIUM_LIBRARY_VERSION_MAJOR +SODIUM_LIBRARY_VERSION_MINOR +crypto_aead_chacha20poly1305_ABYTES +crypto_aead_chacha20poly1305_IETF_ABYTES +crypto_aead_chacha20poly1305_IETF_KEYBYTES +crypto_aead_chacha20poly1305_IETF_MESSAGEBYTES_MAX +crypto_aead_chacha20poly1305_IETF_NPUBBYTES +crypto_aead_chacha20poly1305_IETF_NSECBYTES +crypto_aead_chacha20poly1305_KEYBYTES +crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX +crypto_aead_chacha20poly1305_NPUBBYTES +crypto_aead_chacha20poly1305_NSECBYTES +crypto_aead_chacha20poly1305_ietf_ABYTES +crypto_aead_chacha20poly1305_ietf_KEYBYTES +crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX +crypto_aead_chacha20poly1305_ietf_NPUBBYTES +crypto_aead_chacha20poly1305_ietf_NSECBYTES +crypto_aead_xchacha20poly1305_IETF_ABYTES +crypto_aead_xchacha20poly1305_IETF_KEYBYTES +crypto_aead_xchacha20poly1305_IETF_MESSAGEBYTES_MAX +crypto_aead_xchacha20poly1305_IETF_NPUBBYTES +crypto_aead_xchacha20poly1305_IETF_NSECBYTES +crypto_aead_xchacha20poly1305_ietf_ABYTES +crypto_aead_xchacha20poly1305_ietf_KEYBYTES +crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX +crypto_aead_xchacha20poly1305_ietf_NPUBBYTES +crypto_aead_xchacha20poly1305_ietf_NSECBYTES +crypto_auth_BYTES +crypto_auth_KEYBYTES +crypto_auth_hmacsha256_BYTES +crypto_auth_hmacsha256_KEYBYTES +crypto_auth_hmacsha512256_BYTES +crypto_auth_hmacsha512256_KEYBYTES +crypto_auth_hmacsha512_BYTES +crypto_auth_hmacsha512_KEYBYTES +crypto_box_BEFORENMBYTES +crypto_box_MACBYTES +crypto_box_MESSAGEBYTES_MAX +crypto_box_NONCEBYTES +crypto_box_PUBLICKEYBYTES +crypto_box_SEALBYTES +crypto_box_SECRETKEYBYTES +crypto_box_SEEDBYTES +crypto_box_curve25519xchacha20poly1305_BEFORENMBYTES +crypto_box_curve25519xchacha20poly1305_MACBYTES +crypto_box_curve25519xchacha20poly1305_MESSAGEBYTES_MAX +crypto_box_curve25519xchacha20poly1305_NONCEBYTES +crypto_box_curve25519xchacha20poly1305_PUBLICKEYBYTES +crypto_box_curve25519xchacha20poly1305_SEALBYTES +crypto_box_curve25519xchacha20poly1305_SECRETKEYBYTES +crypto_box_curve25519xchacha20poly1305_SEEDBYTES +crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES +crypto_box_curve25519xsalsa20poly1305_MACBYTES +crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX +crypto_box_curve25519xsalsa20poly1305_NONCEBYTES +crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES +crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES +crypto_box_curve25519xsalsa20poly1305_SEEDBYTES +crypto_core_ed25519_BYTES +crypto_core_ed25519_HASHBYTES +crypto_core_ed25519_NONREDUCEDSCALARBYTES +crypto_core_ed25519_SCALARBYTES +crypto_core_ed25519_UNIFORMBYTES +crypto_core_hchacha20_CONSTBYTES +crypto_core_hchacha20_INPUTBYTES +crypto_core_hchacha20_KEYBYTES +crypto_core_hchacha20_OUTPUTBYTES +crypto_core_hsalsa20_CONSTBYTES +crypto_core_hsalsa20_INPUTBYTES +crypto_core_hsalsa20_KEYBYTES +crypto_core_hsalsa20_OUTPUTBYTES +crypto_core_ristretto255_BYTES +crypto_core_ristretto255_HASHBYTES +crypto_core_ristretto255_NONREDUCEDSCALARBYTES +crypto_core_ristretto255_SCALARBYTES +crypto_core_salsa2012_CONSTBYTES +crypto_core_salsa2012_INPUTBYTES +crypto_core_salsa2012_KEYBYTES +crypto_core_salsa2012_OUTPUTBYTES +crypto_core_salsa20_CONSTBYTES +crypto_core_salsa20_INPUTBYTES +crypto_core_salsa20_KEYBYTES +crypto_core_salsa20_OUTPUTBYTES +crypto_generichash_BYTES +crypto_generichash_BYTES_MAX +crypto_generichash_BYTES_MIN +crypto_generichash_KEYBYTES +crypto_generichash_KEYBYTES_MAX +crypto_generichash_KEYBYTES_MIN +crypto_generichash_blake2b_BYTES +crypto_generichash_blake2b_BYTES_MAX +crypto_generichash_blake2b_BYTES_MIN +crypto_generichash_blake2b_KEYBYTES +crypto_generichash_blake2b_KEYBYTES_MAX +crypto_generichash_blake2b_KEYBYTES_MIN +crypto_generichash_blake2b_PERSONALBYTES +crypto_generichash_blake2b_SALTBYTES +crypto_hash_BYTES +crypto_hash_sha256_BYTES +crypto_hash_sha512_BYTES +crypto_kdf_BYTES_MAX +crypto_kdf_BYTES_MIN +crypto_kdf_CONTEXTBYTES +crypto_kdf_KEYBYTES +crypto_kdf_blake2b_BYTES_MAX +crypto_kdf_blake2b_BYTES_MIN +crypto_kdf_blake2b_CONTEXTBYTES +crypto_kdf_blake2b_KEYBYTES +crypto_kx_PUBLICKEYBYTES +crypto_kx_SECRETKEYBYTES +crypto_kx_SEEDBYTES +crypto_kx_SESSIONKEYBYTES +crypto_onetimeauth_BYTES +crypto_onetimeauth_KEYBYTES +crypto_onetimeauth_poly1305_BYTES +crypto_onetimeauth_poly1305_KEYBYTES +crypto_pwhash_ALG_ARGON2I13 +crypto_pwhash_ALG_ARGON2ID13 +crypto_pwhash_ALG_DEFAULT +crypto_pwhash_BYTES_MAX +crypto_pwhash_BYTES_MIN +crypto_pwhash_MEMLIMIT_INTERACTIVE +crypto_pwhash_MEMLIMIT_MAX +crypto_pwhash_MEMLIMIT_MIN +crypto_pwhash_MEMLIMIT_MODERATE +crypto_pwhash_MEMLIMIT_SENSITIVE +crypto_pwhash_OPSLIMIT_INTERACTIVE +crypto_pwhash_OPSLIMIT_MAX +crypto_pwhash_OPSLIMIT_MIN +crypto_pwhash_OPSLIMIT_MODERATE +crypto_pwhash_OPSLIMIT_SENSITIVE +crypto_pwhash_PASSWD_MAX +crypto_pwhash_PASSWD_MIN +crypto_pwhash_SALTBYTES +crypto_pwhash_STRBYTES +crypto_pwhash_argon2i_BYTES_MAX +crypto_pwhash_argon2i_BYTES_MIN +crypto_pwhash_argon2i_SALTBYTES +crypto_pwhash_argon2i_STRBYTES +crypto_pwhash_argon2id_BYTES_MAX +crypto_pwhash_argon2id_BYTES_MIN +crypto_pwhash_argon2id_SALTBYTES +crypto_pwhash_argon2id_STRBYTES +crypto_pwhash_scryptsalsa208sha256_BYTES_MAX +crypto_pwhash_scryptsalsa208sha256_BYTES_MIN +crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE +crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX +crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN +crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE +crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE +crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX +crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN +crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE +crypto_pwhash_scryptsalsa208sha256_SALTBYTES +crypto_pwhash_scryptsalsa208sha256_STRBYTES +crypto_scalarmult_BYTES +crypto_scalarmult_SCALARBYTES +crypto_scalarmult_curve25519_BYTES +crypto_scalarmult_curve25519_SCALARBYTES +crypto_scalarmult_ed25519_BYTES +crypto_scalarmult_ed25519_SCALARBYTES +crypto_scalarmult_ristretto255_BYTES +crypto_scalarmult_ristretto255_SCALARBYTES +crypto_secretbox_KEYBYTES +crypto_secretbox_MACBYTES +crypto_secretbox_MESSAGEBYTES_MAX +crypto_secretbox_NONCEBYTES +crypto_secretbox_xchacha20poly1305_KEYBYTES +crypto_secretbox_xchacha20poly1305_MACBYTES +crypto_secretbox_xchacha20poly1305_MESSAGEBYTES_MAX +crypto_secretbox_xchacha20poly1305_NONCEBYTES +crypto_secretbox_xsalsa20poly1305_KEYBYTES +crypto_secretbox_xsalsa20poly1305_MACBYTES +crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX +crypto_secretbox_xsalsa20poly1305_NONCEBYTES +crypto_secretstream_xchacha20poly1305_ABYTES +crypto_secretstream_xchacha20poly1305_HEADERBYTES +crypto_secretstream_xchacha20poly1305_KEYBYTES +crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX +crypto_secretstream_xchacha20poly1305_TAG_FINAL +crypto_secretstream_xchacha20poly1305_TAG_MESSAGE +crypto_secretstream_xchacha20poly1305_TAG_PUSH +crypto_secretstream_xchacha20poly1305_TAG_REKEY +crypto_shorthash_BYTES +crypto_shorthash_KEYBYTES +crypto_shorthash_siphash24_BYTES +crypto_shorthash_siphash24_KEYBYTES +crypto_shorthash_siphashx24_BYTES +crypto_shorthash_siphashx24_KEYBYTES +crypto_sign_BYTES +crypto_sign_MESSAGEBYTES_MAX +crypto_sign_PUBLICKEYBYTES +crypto_sign_SECRETKEYBYTES +crypto_sign_SEEDBYTES +crypto_sign_ed25519_BYTES +crypto_sign_ed25519_MESSAGEBYTES_MAX +crypto_sign_ed25519_PUBLICKEYBYTES +crypto_sign_ed25519_SECRETKEYBYTES +crypto_sign_ed25519_SEEDBYTES +crypto_stream_KEYBYTES +crypto_stream_MESSAGEBYTES_MAX +crypto_stream_NONCEBYTES +crypto_stream_chacha20_IETF_KEYBYTES +crypto_stream_chacha20_IETF_MESSAGEBYTES_MAX +crypto_stream_chacha20_IETF_NONCEBYTES +crypto_stream_chacha20_KEYBYTES +crypto_stream_chacha20_MESSAGEBYTES_MAX +crypto_stream_chacha20_NONCEBYTES +crypto_stream_chacha20_ietf_KEYBYTES +crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX +crypto_stream_chacha20_ietf_NONCEBYTES +crypto_stream_salsa2012_KEYBYTES +crypto_stream_salsa2012_MESSAGEBYTES_MAX +crypto_stream_salsa2012_NONCEBYTES +crypto_stream_salsa208_KEYBYTES +crypto_stream_salsa208_MESSAGEBYTES_MAX +crypto_stream_salsa208_NONCEBYTES +crypto_stream_salsa20_KEYBYTES +crypto_stream_salsa20_MESSAGEBYTES_MAX +crypto_stream_salsa20_NONCEBYTES +crypto_stream_xchacha20_KEYBYTES +crypto_stream_xchacha20_MESSAGEBYTES_MAX +crypto_stream_xchacha20_NONCEBYTES +crypto_stream_xsalsa20_KEYBYTES +crypto_stream_xsalsa20_MESSAGEBYTES_MAX +crypto_stream_xsalsa20_NONCEBYTES +crypto_verify_16_BYTES +crypto_verify_32_BYTES +crypto_verify_64_BYTES +SODIUM_VERSION_STRING +crypto_pwhash_STRPREFIX +crypto_pwhash_scryptsalsa208sha256_STRPREFIX diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortHash.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortHash.kt new file mode 100644 index 0000000..cc9b927 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortHash.kt @@ -0,0 +1,15 @@ +package com.ionspin.kotlin.crypto.shortinputhash + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Aug-2020 + */ +const val crypto_shorthash_KEYBYTES = 16 +const val crypto_shorthash_BYTES = 8 + +expect object ShortHash { + + fun shortHash(data : UByteArray, key: UByteArray) : UByteArray + fun shortHashKeygen() : UByteArray +} diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortInputHashing.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortInputHashing.kt deleted file mode 100644 index 4f51c24..0000000 --- a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/shortinputhash/ShortInputHashing.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.ionspin.kotlin.crypto.shortinputhash - -/** - * Created by Ugljesa Jovanovic - * ugljesa.jovanovic@ionspin.com - * on 21-Aug-2020 - */ -object ShortInputHashing { - -} diff --git a/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/Util.kt b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/Util.kt new file mode 100644 index 0000000..b3034e7 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/commonMain/kotlin/com.ionspin.kotlin.crypto/util/Util.kt @@ -0,0 +1,24 @@ +package com.ionspin.kotlin.crypto.util + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 28-Aug-2020 + */ +fun String.hexStringToUByteArray() : UByteArray { + return this.chunked(2).map { it.toUByte(16) }.toUByteArray() +} + +fun String.encodeToUByteArray() : UByteArray{ + return encodeToByteArray().asUByteArray() +} + +fun UByteArray.toHexString() : String { + return this.joinToString(separator = "") { + if (it <= 0x0FU) { + "0${it.toString(16)}" + } else { + it.toString(16) + } + } +} diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/shorthash/ShortHashTest.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/shorthash/ShortHashTest.kt new file mode 100644 index 0000000..cae34ca --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/shorthash/ShortHashTest.kt @@ -0,0 +1,41 @@ +package com.ionspin.kotlin.crypto.shorthash + +import com.ionspin.kotlin.crypto.LibsodiumInitializer +import com.ionspin.kotlin.crypto.shortinputhash.ShortHash +import com.ionspin.kotlin.crypto.util.encodeToUByteArray +import com.ionspin.kotlin.crypto.util.hexStringToUByteArray +import com.ionspin.kotlin.crypto.util.toHexString +import kotlin.test.Test +import kotlin.test.assertTrue + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 28-Aug-2020 + */ +class ShortHashTest { + + @Test + fun testShortHash() { + LibsodiumInitializer.initializeWithCallback { + val expected = "00e5d509c14e81bb".hexStringToUByteArray() + val input = "Libsodium test" + val key = "key1key1key1key1" + val hash = ShortHash.shortHash(input.encodeToUByteArray(), key.encodeToUByteArray()) + println(hash.toHexString()) + assertTrue { + expected.contentEquals(hash) + } + } + } + + @Test + fun testKeygen() { + LibsodiumInitializer.initializeWithCallback { + assertTrue { + val key = ShortHash.shortHashKeygen() + key.size == 16 + } + } + } +} diff --git a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/TestUtil.kt b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/TestUtil.kt index da2e924..6358a90 100644 --- a/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/TestUtil.kt +++ b/multiplatform-crypto-libsodium-bindings/src/commonTest/kotlin/com/ionspin/kotlin/crypto/util/TestUtil.kt @@ -35,16 +35,4 @@ fun testBlocking(block : suspend () -> Unit) { block.startCoroutine(continuation) } -fun String.encodeToUByteArray() : UByteArray{ - return encodeToByteArray().asUByteArray() -} -fun UByteArray.toHexString() : String { - return this.joinToString(separator = "") { - if (it <= 0x0FU) { - "0${it.toString(16)}" - } else { - it.toString(16) - } - } -} diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt index 646e0ad..a811559 100644 --- a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/JsSodiumInterface.kt @@ -26,6 +26,11 @@ interface JsSodiumInterface { fun crypto_generichash_final(state: dynamic, hashLength: Int) : Uint8Array + //Short hash + fun crypto_shorthash(data : Uint8Array, key: Uint8Array) : Uint8Array + + fun crypto_shorthash_keygen() : Uint8Array + fun crypto_hash_sha256_init() : dynamic diff --git a/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt new file mode 100644 index 0000000..df47ed7 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jsMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt @@ -0,0 +1,21 @@ +package com.ionspin.kotlin.crypto.shortinputhash + +import com.ionspin.kotlin.crypto.getSodium +import ext.libsodium.com.ionspin.kotlin.crypto.toUByteArray +import ext.libsodium.com.ionspin.kotlin.crypto.toUInt8Array + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Aug-2020 + */ +actual object ShortHash { + actual fun shortHash(data: UByteArray, key: UByteArray): UByteArray { + return getSodium().crypto_shorthash(data.toUInt8Array(), key.toUInt8Array()).toUByteArray() + } + + actual fun shortHashKeygen(): UByteArray { + return getSodium().crypto_shorthash_keygen().toUByteArray() + } + +} diff --git a/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt new file mode 100644 index 0000000..f915ef7 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/jvmMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt @@ -0,0 +1,25 @@ +package com.ionspin.kotlin.crypto.shortinputhash + +import com.ionspin.kotlin.crypto.LibsodiumInitializer.sodium + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Aug-2020 + */ + + +actual object ShortHash { + actual fun shortHash(data: UByteArray, key: UByteArray): UByteArray { + val hashResult = UByteArray(crypto_shorthash_BYTES) + sodium.crypto_shorthash(hashResult.asByteArray(), data.asByteArray(), data.size.toLong(), key.asByteArray()) + return hashResult + } + + actual fun shortHashKeygen(): UByteArray { + val key = UByteArray(crypto_shorthash_KEYBYTES) + sodium.crypto_shorthash_keygen(key.asByteArray()) + return key + } + +} diff --git a/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt new file mode 100644 index 0000000..852f043 --- /dev/null +++ b/multiplatform-crypto-libsodium-bindings/src/nativeMain/kotlin/com/ionspin/kotlin/crypto/shortinputhash/ShortHash.kt @@ -0,0 +1,35 @@ +package com.ionspin.kotlin.crypto.shortinputhash + +import com.ionspin.kotlin.crypto.util.toPtr +import kotlinx.cinterop.convert +import kotlinx.cinterop.pin +import libsodium.crypto_shorthash +import libsodium.crypto_shorthash_keygen + +/** + * Created by Ugljesa Jovanovic + * ugljesa.jovanovic@ionspin.com + * on 21-Aug-2020 + */ +actual object ShortHash { + actual fun shortHash(data: UByteArray, key: UByteArray): UByteArray { + val hashResult = UByteArray(crypto_shorthash_BYTES) + val hashResultPinned = hashResult.pin() + val dataPinned = data.pin() + val keyPinned = key.pin() + crypto_shorthash(hashResultPinned.toPtr(), dataPinned.toPtr(), data.size.convert(), keyPinned.toPtr()) + hashResultPinned.unpin() + dataPinned.unpin() + keyPinned.unpin() + return hashResult + } + + actual fun shortHashKeygen(): UByteArray { + val keyResult = UByteArray(crypto_shorthash_KEYBYTES) + val keyResultPinned = keyResult.pin() + crypto_shorthash_keygen(keyResultPinned.toPtr()) + keyResultPinned.unpin() + return keyResult + } + +} diff --git a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCtrPure.kt b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCtrPure.kt index b9f4ff9..6b62b14 100644 --- a/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCtrPure.kt +++ b/multiplatform-crypto/src/commonMain/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCtrPure.kt @@ -55,7 +55,7 @@ internal class AesCtrPure internal constructor(val aesKey: InternalAesKey, val m * data call [decrypt] */ fun createDecryptor(aesKey : InternalAesKey, initialCounter: UByteArray) : AesCtrPure { - return AesCtrPure(aesKey, Mode.DECRYPT, initialCounter = initialCounter) + return AesCtrPure(aesKey, Mode.DECRYPT, initialCounter) } /** * Bulk encryption, returns encrypted data and a random initial counter @@ -68,8 +68,8 @@ internal class AesCtrPure internal constructor(val aesKey: InternalAesKey, val m /** * Bulk decryption, returns decrypted data */ - fun decrypt(aesKey: InternalAesKey, data: UByteArray, initialCounter: UByteArray): UByteArray { - val aesCtr = AesCtrPure(aesKey, Mode.DECRYPT, initialCounter = initialCounter) + fun decrypt(aesKey: InternalAesKey, data: UByteArray, initialCounter: UByteArray? = null): UByteArray { + val aesCtr = AesCtrPure(aesKey = aesKey, mode = Mode.DECRYPT, initialCounter = initialCounter) aesCtr.addData(data) return aesCtr.decrypt() } diff --git a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbcTest.kt b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbcTest.kt index 7b86d77..c84a345 100644 --- a/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbcTest.kt +++ b/multiplatform-crypto/src/commonTest/kotlin/com/ionspin/kotlin/crypto/symmetric/AesCbcTest.kt @@ -75,7 +75,9 @@ class AesCbcTest { assertTrue { val key = "4278b840fb44aaa757c1bf04acbe1a3e" val iv = "57f02a5c5339daeb0a2908a06ac6393f" - val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7" + val cipherText = "479c89ec14bc98994e62b2c705b5014e" + + "175bd7832e7e60a1e92aac568a861eb7" + + "fc2dc2f4a527ce39f79c56b31432c779" val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" val aesCbc = AesCbcPure(InternalAesKey.Aes128Key(key), mode = Mode.DECRYPT, initializationVector = iv.hexStringToUByteArray()) @@ -95,7 +97,9 @@ class AesCbcTest { assertTrue { val key = "4278b840fb44aaa757c1bf04acbe1a3e" val iv = "57f02a5c5339daeb0a2908a06ac6393f" - val cipherText = "479c89ec14bc98994e62b2c705b5014e175bd7832e7e60a1e92aac568a861eb7" + val cipherText = "479c89ec14bc98994e62b2c705b5014e" + + "175bd7832e7e60a1e92aac568a861eb7" + + "fc2dc2f4a527ce39f79c56b31432c779" val expectedPlainText = "3c888bbbb1a8eb9f3e9b87acaad986c466e2f7071c83083b8a557971918850e5" val decrypted = AesCbcPure.decrypt(InternalAesKey.Aes128Key(key), cipherText.hexStringToUByteArray(), iv.hexStringToUByteArray()) println("Decrypted: ${decrypted.toHexString()}")