From e88f6fe2916be8cb40b3d722456954c77b3806b7 Mon Sep 17 00:00:00 2001 From: Jeremy Klein Date: Wed, 21 Feb 2024 11:36:39 -0800 Subject: [PATCH] Switch to a full 64bit nonce --- .../lightspark/sdk/core/crypto/SecureRandom.kt | 4 ++-- .../lightspark/sdk/core/crypto/SecureRandom.kt | 2 +- .../lightspark/sdk/core/requester/Requester.kt | 7 ++++--- .../lightspark/sdk/ClientIntegrationTests.kt | 18 +++++++++--------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/core/src/commonJvmAndroidMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt b/core/src/commonJvmAndroidMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt index 4f7f68a9..8a227681 100644 --- a/core/src/commonJvmAndroidMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt +++ b/core/src/commonJvmAndroidMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt @@ -2,6 +2,6 @@ package com.lightspark.sdk.core.crypto import java.security.SecureRandom -internal actual fun nextInt(): Int { - return SecureRandom().nextInt() +internal actual fun nextLong(): Long { + return SecureRandom().nextLong() } diff --git a/core/src/commonMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt b/core/src/commonMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt index f5c7f003..3ba9b90a 100644 --- a/core/src/commonMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt +++ b/core/src/commonMain/kotlin/com/lightspark/sdk/core/crypto/SecureRandom.kt @@ -2,4 +2,4 @@ package com.lightspark.sdk.core.crypto -internal expect fun nextInt(): Int +internal expect fun nextLong(): Long diff --git a/core/src/commonMain/kotlin/com/lightspark/sdk/core/requester/Requester.kt b/core/src/commonMain/kotlin/com/lightspark/sdk/core/requester/Requester.kt index c00086e5..a0a740e5 100644 --- a/core/src/commonMain/kotlin/com/lightspark/sdk/core/requester/Requester.kt +++ b/core/src/commonMain/kotlin/com/lightspark/sdk/core/requester/Requester.kt @@ -7,7 +7,7 @@ import com.lightspark.sdk.core.LightsparkException import com.lightspark.sdk.core.auth.AuthProvider import com.lightspark.sdk.core.crypto.MissingKeyException import com.lightspark.sdk.core.crypto.NodeKeyCache -import com.lightspark.sdk.core.crypto.nextInt +import com.lightspark.sdk.core.crypto.nextLong import com.lightspark.sdk.core.util.getPlatform import io.ktor.client.HttpClient import io.ktor.client.plugins.websocket.WebSockets @@ -21,6 +21,7 @@ import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.set import kotlin.coroutines.cancellation.CancellationException +import kotlin.math.absoluteValue import kotlin.time.Duration.Companion.hours import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -203,8 +204,8 @@ class Requester constructor( val newBodyData = bodyData.toMutableMap().apply { // Note: The nonce is a 64-bit unsigned integer, but the Kotlin random number generator wants to - // spit out a signed int, which the backend can't decode. - put("nonce", JsonPrimitive(nextInt().toUInt().toLong())) + // spit out a signed int, which the backend can't decode, so we take the absolute value. + put("nonce", JsonPrimitive(nextLong().absoluteValue)) put("expires_at", JsonPrimitive(anHourFromNowISOString())) }.let { JsonObject(it) } val newBodyString = Json.encodeToString(newBodyData) diff --git a/lightspark-sdk/src/commonTest/kotlin/com/lightspark/sdk/ClientIntegrationTests.kt b/lightspark-sdk/src/commonTest/kotlin/com/lightspark/sdk/ClientIntegrationTests.kt index 279d901b..d23d19a9 100644 --- a/lightspark-sdk/src/commonTest/kotlin/com/lightspark/sdk/ClientIntegrationTests.kt +++ b/lightspark-sdk/src/commonTest/kotlin/com/lightspark/sdk/ClientIntegrationTests.kt @@ -184,7 +184,7 @@ class ClientIntegrationTests { @Test fun `create an LNURL invoice`() = runTest { - val node = getFirstNode() + val node = getFirstOskNode() val metadata = "[[\\\"text/plain\\\",\\\"Pay to domain.org user ktfan98\\\"],[\\\"text/identifier\\\",\\\"ktfan98@domain.org\\\"]]" val paymentRequest = client.createLnurlInvoice(node.id, 1000, metadata) @@ -193,7 +193,7 @@ class ClientIntegrationTests { @Test fun `create and cancel an invoice`() = runTest { - val node = getFirstNode() + val node = getFirstOskNode() val invoice = client.createInvoice(node.id, 1000) println("encoded invoice: $invoice.data.encodedPaymentRequest}") @@ -205,7 +205,7 @@ class ClientIntegrationTests { @Test fun `send a payment for an invoice`() = runTest { - val node = getFirstNode() + val node = getFirstOskNode() client.loadNodeSigningKey(node.id, PasswordRecoverySigningKeyLoader(node.id, NODE_PASSWORD)) // Just paying a pre-existing AMP invoice. @@ -220,7 +220,7 @@ class ClientIntegrationTests { @Test fun `get node channels`() = runTest { - val node = getFirstNode() + val node = getFirstOskNode() val channels = node.getChannelsQuery().execute(client) channels.shouldNotBeNull() channels.entities.shouldNotBeEmpty() @@ -230,7 +230,7 @@ class ClientIntegrationTests { @Test fun `test paying a test mode invoice`() = runTest { - val node = getFirstNode() + val node = getFirstOskNode() client.loadNodeSigningKey(node.id, PasswordRecoverySigningKeyLoader(node.id, NODE_PASSWORD)) val invoice = client.createTestModeInvoice(node.id, 100_000, "test invoice") var outgoingPayment: OutgoingPayment? = client.payInvoice(node.id, invoice, maxFeesMsats = 100_000) @@ -245,7 +245,7 @@ class ClientIntegrationTests { @Test fun `test creating a test mode payment`() = runTest { - val node = getFirstNode() + val node = getFirstOskNode() client.loadNodeSigningKey(node.id, PasswordRecoverySigningKeyLoader(node.id, NODE_PASSWORD)) val invoice = client.createInvoice(node.id, 100_000, "test invoice") var payment: IncomingPayment? = client.createTestModePayment(node.id, invoice.data.encodedPaymentRequest) @@ -260,16 +260,16 @@ class ClientIntegrationTests { // TODO: Add tests for withdrawals and deposits. - private suspend fun getFirstNode(): LightsparkNode { + private suspend fun getFirstOskNode(): LightsparkNode { val account = getCurrentAccount() val nodes = account.getNodesQuery().execute(client) nodes.shouldNotBeNull() nodes.entities.shouldNotBeEmpty() - return nodes.entities.first() + return nodes.entities.first { it.id.contains("OSK")} } private suspend fun getNodeId(): String { - return getFirstNode().id + return getFirstOskNode().id } private suspend fun getCurrentAccount(): Account {