Foundations(iOS Sourceset): Provide implementation for AESGCM. Duplicate AESGCM tests for iOS. Move dependency to 'cryptography-optimal' make use of all iOS crypto providers.
This commit is contained in:
@@ -230,7 +230,7 @@ kotlin {
|
||||
implementation(libs.charlietap.cachemap)
|
||||
implementation(libs.net.thauvin.erik.urlencoder.lib)
|
||||
implementation(libs.com.ditchoom.buffer.compression)
|
||||
implementation(libs.dev.whyoleg.cryptography.provider.apple)
|
||||
implementation(libs.dev.whyoleg.cryptography.provider.apple.optimal)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,23 +20,47 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.utils.ciphers
|
||||
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import dev.whyoleg.cryptography.CryptographyProvider
|
||||
import dev.whyoleg.cryptography.DelicateCryptographyApi
|
||||
import dev.whyoleg.cryptography.algorithms.AES
|
||||
|
||||
actual class AESGCM actual constructor(
|
||||
actual val keyBytes: ByteArray,
|
||||
actual val nonce: ByteArray,
|
||||
) : NostrCipher {
|
||||
actual override fun name(): String {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
private val provider = CryptographyProvider.Default
|
||||
private val aesGcm = provider.get(AES.GCM)
|
||||
|
||||
actual override fun encrypt(bytesToEncrypt: ByteArray): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
private val keyDecoder =
|
||||
aesGcm
|
||||
.keyDecoder()
|
||||
.decodeFromByteArrayBlocking(AES.Key.Format.RAW, keyBytes)
|
||||
|
||||
actual override fun decrypt(bytesToDecrypt: ByteArray): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
private fun cipher() = keyDecoder.cipher()
|
||||
|
||||
actual override fun decryptOrNull(bytesToDecrypt: ByteArray): ByteArray? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
actual override fun name(): String = "aes-gcm"
|
||||
|
||||
@OptIn(DelicateCryptographyApi::class)
|
||||
actual override fun encrypt(bytesToEncrypt: ByteArray): ByteArray =
|
||||
with(cipher()) {
|
||||
encryptWithIvBlocking(nonce, bytesToEncrypt)
|
||||
}
|
||||
|
||||
@OptIn(DelicateCryptographyApi::class)
|
||||
actual override fun decrypt(bytesToDecrypt: ByteArray): ByteArray =
|
||||
with(cipher()) {
|
||||
decryptWithIvBlocking(nonce, bytesToDecrypt)
|
||||
}
|
||||
|
||||
@OptIn(DelicateCryptographyApi::class)
|
||||
actual override fun decryptOrNull(bytesToDecrypt: ByteArray): ByteArray? =
|
||||
try {
|
||||
with(cipher()) {
|
||||
decryptWithIvBlocking(nonce, bytesToDecrypt)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w("AESGCM", "Failed to decrypt", e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,15 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz
|
||||
|
||||
import dev.whyoleg.cryptography.CryptographyProviderApi
|
||||
import dev.whyoleg.cryptography.providers.base.toByteArray
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import kotlinx.cinterop.toKString
|
||||
import kotlinx.io.files.FileNotFoundException
|
||||
import platform.Foundation.NSData
|
||||
import platform.Foundation.NSString
|
||||
import platform.Foundation.NSUTF8StringEncoding
|
||||
import platform.Foundation.dataWithContentsOfFile
|
||||
import platform.Foundation.stringWithContentsOfFile
|
||||
import platform.posix.getenv
|
||||
|
||||
@@ -34,4 +39,11 @@ actual class TestResourceLoader {
|
||||
val filePath = "$resourceDir/$file"
|
||||
return NSString.stringWithContentsOfFile(filePath, encoding = NSUTF8StringEncoding, error = null) as String
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class, CryptographyProviderApi::class)
|
||||
fun loadFileData(file: String): ByteArray {
|
||||
val resourceDir = getenv("TEST_RESOURCES_ROOT")?.toKString()
|
||||
val filePath = "$resourceDir/$file"
|
||||
return NSData.dataWithContentsOfFile(filePath)?.toByteArray() ?: throw FileNotFoundException("Resource $file was not found.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip17Dm
|
||||
|
||||
import com.vitorpamplona.quartz.TestResourceLoader
|
||||
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
|
||||
import com.vitorpamplona.quartz.utils.ciphers.AESGCM
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class AESGCMTest {
|
||||
val decryptionNonce = "01e77c94bd5aba3e3cbb69594e7ba07c"
|
||||
val decryptionKey = "c128ecffab90ee7810e3df08e7fb2cc39a8d40f24201f48b2b36e23b34ac50ee"
|
||||
|
||||
val cipher =
|
||||
AESGCM(
|
||||
decryptionKey.hexToByteArray(),
|
||||
decryptionNonce.encodeToByteArray(),
|
||||
)
|
||||
|
||||
@Test
|
||||
fun encryptDecrypt() {
|
||||
val encrypted = cipher.encrypt("Testing".encodeToByteArray())
|
||||
val decrypted = cipher.decrypt(encrypted)
|
||||
|
||||
assertEquals("Testing", decrypted.decodeToString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun imageTest() {
|
||||
val image =
|
||||
TestResourceLoader().loadFileData("ovxxk2vz.jpg")
|
||||
|
||||
val decrypted = cipher.decrypt(image)
|
||||
|
||||
assertEquals(44201, decrypted.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun videoTest2() {
|
||||
val myCipher =
|
||||
AESGCM(
|
||||
"373d19850ebc8ed5b0fefcca5cd6f27fde9cb6ac54fd32f6b4fad9d68ebe8ee0".hexToByteArray(),
|
||||
"95e67b6874784a54299b58b8990499bd".hexToByteArray(),
|
||||
)
|
||||
|
||||
val encrypted =
|
||||
TestResourceLoader().loadFileData("trouble_video")
|
||||
|
||||
val decrypted = myCipher.decrypt(encrypted)
|
||||
|
||||
assertEquals(1277122, decrypted.size)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip17Dm
|
||||
|
||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
|
||||
import kotlinx.collections.immutable.persistentSetOf
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ChatroomKeyTest {
|
||||
@Test
|
||||
fun testEquals() {
|
||||
val k1 = ChatroomKey(persistentSetOf("Key1", "Key2"))
|
||||
val k2 = ChatroomKey(persistentSetOf("Key1", "Key2"))
|
||||
|
||||
assertEquals(k1, k2)
|
||||
assertEquals(k1.hashCode(), k2.hashCode())
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user