diff options
author | Torsten Grote <t@grobox.de> | 2020-07-31 15:02:47 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2020-07-31 15:02:47 -0300 |
commit | 53ae9a68cae1d6c30247ef91108c39702cde5233 (patch) | |
tree | 29b4e0f8ebdf1adc6068eea32f5549a141956575 | |
parent | 479f8015f8663507fd318aa29e863dac35683c64 (diff) | |
download | wallet-kotlin-53ae9a68cae1d6c30247ef91108c39702cde5233.tar.gz wallet-kotlin-53ae9a68cae1d6c30247ef91108c39702cde5233.tar.bz2 wallet-kotlin-53ae9a68cae1d6c30247ef91108c39702cde5233.zip |
clean up build script and remove duplicated code
15 files changed, 489 insertions, 265 deletions
@@ -1,2 +1,3 @@ /build -/.gradle
\ No newline at end of file +/.gradle +/local.properties diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 89a53dc..61a2480 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -6,6 +6,115 @@ <option name="IMPORT_NESTED_CLASSES" value="true" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> </JetCodeStyleSettings> + <codeStyleSettings language="XML"> + <arrangement> + <rules> + <section> + <rule> + <match> + <AND> + <NAME>xmlns:android</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>xmlns:.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*:id</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*:name</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>name</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>style</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>ANDROID_ATTRIBUTE_ORDER</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>.*</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + </rules> + </arrangement> + </codeStyleSettings> <codeStyleSettings language="kotlin"> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> </codeStyleSettings> diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml index b9b962c..59912a9 100644 --- a/.idea/jarRepositories.xml +++ b/.idea/jarRepositories.xml @@ -26,5 +26,15 @@ <option name="name" value="maven" /> <option name="url" value="https://dl.bintray.com/terl/lazysodium-maven" /> </remote-repository> + <remote-repository> + <option name="id" value="MavenLocal" /> + <option name="name" value="MavenLocal" /> + <option name="url" value="file:$MAVEN_REPOSITORY$/" /> + </remote-repository> + <remote-repository> + <option name="id" value="Google" /> + <option name="name" value="Google" /> + <option name="url" value="https://dl.google.com/dl/android/maven2/" /> + </remote-repository> </component> </project>
\ No newline at end of file diff --git a/build.gradle b/build.gradle index d053bc7..a4239f1 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,13 @@ buildscript { ext.kotlin_version = '1.3.72' + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:4.0.1' + } } plugins { @@ -26,16 +33,18 @@ plugins { repositories { mavenCentral() jcenter() + google() maven { url "https://dl.bintray.com/terl/lazysodium-maven" } } group 'net.taler' version '0.0.1' +apply plugin: 'com.android.library' apply plugin: 'maven-publish' kotlin { - jvm("android") + android {} js { browser { } @@ -66,7 +75,7 @@ kotlin { } } sourceSets { - def coroutines_version = "1.3.7" + def coroutines_version = "1.3.8" def ktor_version = "1.3.2" all { languageSettings { @@ -87,21 +96,7 @@ kotlin { dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') - api "io.ktor:ktor-client-mock:$ktor_version" - } - } - iosMain { - dependencies { - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version" - implementation "io.ktor:ktor-client-ios:$ktor_version" - implementation "io.ktor:ktor-client-logging-native:$ktor_version" - implementation "io.ktor:ktor-client-serialization-native:$ktor_version" - } - } - iosTest { - dependencies { - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version" - api "io.ktor:ktor-client-mock-native:$ktor_version" + implementation "io.ktor:ktor-client-mock:$ktor_version" } } androidMain { @@ -112,18 +107,18 @@ kotlin { implementation "io.ktor:ktor-client-logging-jvm:$ktor_version" implementation "io.ktor:ktor-client-serialization-jvm:$ktor_version" // TODO Android -// implementation "com.goterl.lazycode:lazysodium-android:4.1.1@aar" - implementation("com.goterl.lazycode:lazysodium-java:4.2.6") { +// implementation("com.goterl.lazycode:lazysodium-android:4.2.0@aar") { + implementation("com.goterl.lazycode:lazysodium-java:4.3.0") { exclude group: "org.slf4j" } - implementation 'net.java.dev.jna:jna:5.5.0@aar' + implementation 'net.java.dev.jna:jna:5.6.0@aar' } } androidTest { dependencies { implementation kotlin('test') implementation kotlin('test-junit') - api "io.ktor:ktor-client-mock-jvm:$ktor_version" + implementation "io.ktor:ktor-client-mock-jvm:$ktor_version" implementation "org.slf4j:slf4j-simple:1.7.30" } } @@ -150,21 +145,56 @@ kotlin { jsTest { dependencies { implementation kotlin('test-js') - api "io.ktor:ktor-client-mock-js:$ktor_version" + implementation "io.ktor:ktor-client-mock-js:$ktor_version" } } - linuxMain { + nativeMain { + dependsOn commonMain dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version" - implementation "io.ktor:ktor-client-curl:$ktor_version" implementation "io.ktor:ktor-client-logging-native:$ktor_version" implementation "io.ktor:ktor-client-serialization-native:$ktor_version" } } - linuxTest { + nativeTest { + dependsOn commonTest + dependencies { + implementation "io.ktor:ktor-client-mock-native:$ktor_version" + } + } + linuxMain { + dependsOn nativeMain dependencies { - api "io.ktor:ktor-client-mock-native:$ktor_version" + implementation "io.ktor:ktor-client-curl:$ktor_version" + } + } + iosMain { + dependsOn nativeMain + dependencies { + implementation "io.ktor:ktor-client-ios:$ktor_version" } } + configure([targets.linux, targets.iosArm64, targets.iosX64]) { + compilations.main.source(sourceSets.nativeMain) + compilations.test.source(sourceSets.nativeTest) + } + } +} + +android { + compileSdkVersion 29 + //noinspection GradleDependency + buildToolsVersion "29.0.2" + + defaultConfig { + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "0.1" + } + sourceSets { + main { + manifest.srcFile 'src/androidMain/AndroidManifest.xml' + } } } diff --git a/src/androidMain/AndroidManifest.xml b/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..77fbf4a --- /dev/null +++ b/src/androidMain/AndroidManifest.xml @@ -0,0 +1,23 @@ +<!-- + ~ This file is part of GNU Taler + ~ (C) 2020 Taler Systems S.A. + ~ + ~ GNU Taler is free software; you can redistribute it and/or modify it under the + ~ terms of the GNU General Public License as published by the Free Software + ~ Foundation; either version 3, or (at your option) any later version. + ~ + ~ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + ~ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + ~ A PARTICULAR PURPOSE. See the GNU General Public License for more details. + ~ + ~ You should have received a copy of the GNU General Public License along with + ~ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="net.taler.wallet.kotlin"> + + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.INTERNET" /> + +</manifest> diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt b/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt index ebf445e..4143389 100644 --- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt +++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt @@ -80,6 +80,6 @@ data class Duration( val ms: Long ) { companion object { - const val FOREVER: Long = -1 + const val FOREVER: Long = -1 // TODO or UINT64_MAX? } } diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/reserve/ReserveManager.kt b/src/commonMain/kotlin/net/taler/wallet/kotlin/reserve/ReserveManager.kt new file mode 100644 index 0000000..c8e7bd4 --- /dev/null +++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/reserve/ReserveManager.kt @@ -0,0 +1,126 @@ +/* + * This file is part of GNU Taler + * (C) 2020 Taler Systems S.A. + * + * GNU Taler is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3, or (at your option) any later version. + * + * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +package net.taler.wallet.kotlin.reserve + +import io.ktor.client.HttpClient +import net.taler.wallet.kotlin.Amount +import net.taler.wallet.kotlin.Base32Crockford +import net.taler.wallet.kotlin.Db +import net.taler.wallet.kotlin.DbFactory +import net.taler.wallet.kotlin.Timestamp +import net.taler.wallet.kotlin.crypto.Crypto +import net.taler.wallet.kotlin.crypto.CryptoFactory +import net.taler.wallet.kotlin.exchange.Exchange +import net.taler.wallet.kotlin.getDefaultHttpClient +import net.taler.wallet.kotlin.reserve.ReserveRecordStatus.REGISTERING_BANK +import net.taler.wallet.kotlin.reserve.ReserveRecordStatus.UNCONFIRMED + +internal class ReserveManager( + private val crypto: Crypto = CryptoFactory.getCrypto(), + private val httpClient: HttpClient = getDefaultHttpClient(), + private val db: Db = DbFactory().openDb() +) { + + /** + * Request to create a reserve. + */ + data class CreateReserveRequest( + /** + * The initial amount for the reserve. + */ + val amount: Amount, + + /** + * Exchange URL where the bank should create the reserve. + */ + val exchangeBaseUrl: String, + + /** + * Payto URI that identifies the exchange's account that the funds for this reserve go into. + */ + val exchangePaytoUri: String, + + /** + * Wire details (as a payto URI) for the bank account that sent the funds to the exchange. + */ + val senderPaytoUri: String? = null, + + /** + * URL to fetch the withdraw status from the bank. + */ + val bankWithdrawStatusUrl: String? = null + ) + + /** + * Response for the create reserve request to the wallet. + */ + data class CreateReserveResponse( + /** + * Exchange URL where the bank should create the reserve. + * The URL is normalized in the response. + */ + val exchangeBaseUrl: String, + + /** + * Reserve public key of the newly created reserve. + */ + val reservePub: String + ) + + /** + * Create a reserve, but do not flag it as confirmed yet. + */ + fun create(request: CreateReserveRequest): CreateReserveResponse { + val keyPair = crypto.createEddsaKeyPair() + val now = Timestamp.now() + val exchangeBaseUrl = Exchange.normalizeUrl(request.exchangeBaseUrl) + val bankInfo = request.bankWithdrawStatusUrl?.let { bankWithdrawStatusUrl -> + ReserveBankInfo( + statusUrl = bankWithdrawStatusUrl, + amount = request.amount, + bankWithdrawalGroupId = Base32Crockford.encode(crypto.getRandomBytes(32)), + withdrawalStarted = false + ) + } + val reserve = Reserve( + reservePub = keyPair.encodedPublicKey, + reservePriv = keyPair.encodedPrivateKey, + exchangeBaseUrl = exchangeBaseUrl, + currency = request.amount.currency, + timestampCreated = now, + senderPaytoUri = request.senderPaytoUri, + exchangePaytoUri = request.exchangePaytoUri, + bankInfo = bankInfo, + reserveStatus = if (request.bankWithdrawStatusUrl == null) UNCONFIRMED else REGISTERING_BANK, + retryInfo = RetryInfo.getInitial() + ) + // TODO store reserve history in DB + // TODO store senderPaytoUri in DB + // TODO store currency record in DB + // TODO store withdraw URI in DB +// db.put(reserve) + return CreateReserveResponse( + exchangeBaseUrl = exchangeBaseUrl, + reservePub = keyPair.encodedPublicKey + ) + } + + fun processBankStatus(reservePub: String) { + TODO("Not yet implemented") + } + +} diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/reserve/ReserveRecord.kt b/src/commonMain/kotlin/net/taler/wallet/kotlin/reserve/ReserveRecord.kt new file mode 100644 index 0000000..b618719 --- /dev/null +++ b/src/commonMain/kotlin/net/taler/wallet/kotlin/reserve/ReserveRecord.kt @@ -0,0 +1,160 @@ +/* + * This file is part of GNU Taler + * (C) 2020 Taler Systems S.A. + * + * GNU Taler is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3, or (at your option) any later version. + * + * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +package net.taler.wallet.kotlin.reserve + +import net.taler.wallet.kotlin.Amount +import net.taler.wallet.kotlin.Timestamp +import net.taler.wallet.kotlin.exchange.DenominationSelectionInfo + +/** + * A reserve record as stored in the wallet's database. + */ +data class Reserve( + /** + * The reserve public key. + */ + val reservePub: String, + + /** + * The reserve private key. + */ + val reservePriv: String, + + /** + * The exchange base URL. + */ + val exchangeBaseUrl: String, + + /** + * Currency of the reserve. + */ + val currency: String, + + /** + * Time when the reserve was created. + */ + val timestampCreated: Timestamp, + + /** + * Time when the information about this reserve was posted to the bank. + * + * Only applies if bankWithdrawStatusUrl is not null. + * + * Set to 0 if that hasn't happened yet. + */ + val timestampReserveInfoPosted: Timestamp? = null, + + /** + * Time when the reserve was confirmed, either manually by the user or by the bank. + * + * Set to undefined if not confirmed yet. + */ + val timestampConfirmed: Timestamp? = null, + + /** + * Wire information (as payto URI) for the bank account that transferred funds for this reserve. + */ + val senderPaytoUri: String?, + + /** + * Wire information (as payto URI) for the exchange, + * specifically the account that was transferred to when creating the reserve. + */ + val exchangePaytoUri: String, + + /** + * Extra state for when this is a withdrawal involving a Taler-integrated bank. + */ + val bankInfo: ReserveBankInfo?, + + val reserveStatus: ReserveRecordStatus, + + /** + * Time of the last successful status query. + */ + val lastSuccessfulStatusQuery: Timestamp? = null, + + /** + * Retry info. This field is present even if no retry is scheduled, + * because we need it to be present for the index on the object store + * to work. + */ + val retryInfo: RetryInfo +) + +enum class ReserveRecordStatus(val value: String) { + /** + * Waiting for manual confirmation. + */ + UNCONFIRMED("unconfirmed"), + + /** + * Reserve must be registered with the bank. + */ + REGISTERING_BANK("registering-bank"), + + /** + * We've registered reserve's information with the bank + * and are now waiting for the user to confirm the withdraw + * with the bank (typically 2nd factor auth). + */ + WAIT_CONFIRM_BANK("wait-confirm-bank"), + + /** + * Querying reserve status with the exchange. + */ + QUERYING_STATUS("querying-status"), + + /** + * Status is queried, the wallet must now select coins + * and start withdrawing. + */ + WITHDRAWING("withdrawing"), + + /** + * The corresponding withdraw record has been created. + * No further processing is done, unless explicitly requested + * by the user. + */ + DORMANT("dormant") +} + +data class ReserveBankInfo( + val statusUrl: String, + val confirmUrl: String? = null, + val amount: Amount, + val bankWithdrawalGroupId: String, + val withdrawalStarted: Boolean, + val denomSel: DenominationSelectionInfo? = null // TODO do we really need this? nullable for now +) + +data class RetryInfo( + val firstTry: Timestamp, + val nextRetry: Timestamp, + val retryCounter: Int, + val active: Boolean +) { + // TODO implement retry policies and set proper nextRetry + companion object { + fun getInitial() = RetryInfo( + firstTry = Timestamp.now(), + nextRetry = Timestamp(0), + retryCounter = 0, + active = true + ) + } +} diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt index 42f297a..0ece68e 100644 --- a/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt +++ b/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt @@ -32,9 +32,8 @@ import kotlinx.serialization.json.Json enum class PlatformTarget { ANDROID, - NATIVE_IOS, JS, - NATIVE_LINUX, + NATIVE, } /** diff --git a/src/linuxMain/kotlin/net/taler/wallet/kotlin/Db.kt b/src/linuxMain/kotlin/net/taler/wallet/kotlin/Db.kt deleted file mode 100644 index 45cbfc3..0000000 --- a/src/linuxMain/kotlin/net/taler/wallet/kotlin/Db.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2020 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -package net.taler.wallet.kotlin - -internal actual class DbFactory { - actual fun openDb(): Db { - return FakeDb() - } -} diff --git a/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt b/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt deleted file mode 100644 index 7860607..0000000 --- a/src/linuxMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2020 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -package net.taler.wallet.kotlin.crypto - -import kotlinx.cinterop.CValuesRef -import kotlinx.cinterop.UByteVar -import kotlinx.cinterop.alloc -import kotlinx.cinterop.free -import kotlinx.cinterop.nativeHeap -import kotlinx.cinterop.ptr -import kotlinx.cinterop.refTo -import org.libsodium.crypto_hash_sha256 -import org.libsodium.crypto_hash_sha256_bytes -import org.libsodium.crypto_hash_sha512 -import org.libsodium.crypto_hash_sha512_bytes -import org.libsodium.crypto_hash_sha512_final -import org.libsodium.crypto_hash_sha512_init -import org.libsodium.crypto_hash_sha512_state -import org.libsodium.crypto_hash_sha512_update -import org.libsodium.crypto_scalarmult -import org.libsodium.crypto_scalarmult_BYTES -import org.libsodium.crypto_scalarmult_base -import org.libsodium.crypto_scalarmult_curve25519_BYTES -import org.libsodium.crypto_sign_BYTES -import org.libsodium.crypto_sign_PUBLICKEYBYTES -import org.libsodium.crypto_sign_SECRETKEYBYTES -import org.libsodium.crypto_sign_detached -import org.libsodium.crypto_sign_ed25519_pk_to_curve25519 -import org.libsodium.crypto_sign_seed_keypair -import org.libsodium.crypto_sign_verify_detached -import org.libsodium.randombytes - -internal actual object CryptoFactory { - internal actual fun getCrypto(): Crypto = CryptoNativeImpl -} - -@OptIn(ExperimentalUnsignedTypes::class) -internal object CryptoNativeImpl : CryptoImpl() { - - override fun sha256(input: ByteArray): ByteArray { - val output = ByteArray(crypto_hash_sha256_bytes().toInt()) - val cInput = if (input.isEmpty()) null else input.toCValuesRef() - crypto_hash_sha256(output.toCValuesRef(), cInput, input.size.toULong()) - return output - } - - override fun sha512(input: ByteArray): ByteArray { - val output = ByteArray(crypto_hash_sha512_bytes().toInt()) - val cInput = if (input.isEmpty()) null else input.toCValuesRef() - crypto_hash_sha512(output.toCValuesRef(), cInput, input.size.toULong()) - return output - } - - override fun getHashSha512State(): HashSha512State { - return NativeHashSha512State() - } - - override fun getRandomBytes(num: Int): ByteArray { - val bytes = ByteArray(num) - randombytes(bytes.toCValuesRef(), num.toULong()) - return bytes - } - - override fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray { - val publicKey = ByteArray(crypto_sign_PUBLICKEYBYTES.toInt()) - val privateKey = ByteArray(crypto_sign_SECRETKEYBYTES.toInt()) - crypto_sign_seed_keypair(publicKey.toCValuesRef(), privateKey.toCValuesRef(), eddsaPrivateKey.toCValuesRef()) - return publicKey - } - - override fun ecdheGetPublic(ecdhePrivateKey: ByteArray): ByteArray { - val publicKey = ByteArray(crypto_scalarmult_BYTES.toInt()) - crypto_scalarmult_base(publicKey.toCValuesRef(), ecdhePrivateKey.toCValuesRef()) - return publicKey - } - - override fun createEddsaKeyPair(): EddsaKeyPair { - val privateKey = ByteArray(crypto_sign_SECRETKEYBYTES.toInt()) - randombytes(privateKey.toCValuesRef(), crypto_sign_SECRETKEYBYTES.toULong()) - val publicKey = eddsaGetPublic(privateKey) - return EddsaKeyPair(privateKey, publicKey) - } - - override fun createEcdheKeyPair(): EcdheKeyPair { - val privateKey = ByteArray(crypto_scalarmult_BYTES.toInt()) - randombytes(privateKey.toCValuesRef(), crypto_scalarmult_BYTES.toULong()) - val publicKey = ecdheGetPublic(privateKey) - return EcdheKeyPair(privateKey, publicKey) - } - - override fun eddsaSign(msg: ByteArray, eddsaPrivateKey: ByteArray): ByteArray { - val publicKey = ByteArray(crypto_sign_PUBLICKEYBYTES.toInt()) - val privateKey = ByteArray(crypto_sign_SECRETKEYBYTES.toInt()) - crypto_sign_seed_keypair(publicKey.toCValuesRef(), privateKey.toCValuesRef(), eddsaPrivateKey.toCValuesRef()) - - val signatureBytes = ByteArray(crypto_sign_BYTES.toInt()) - crypto_sign_detached( - signatureBytes.toCValuesRef(), - null, - msg.toCValuesRef(), - msg.size.toULong(), - privateKey.toCValuesRef() - ) - return signatureBytes - } - - override fun eddsaVerify(msg: ByteArray, sig: ByteArray, eddsaPub: ByteArray): Boolean { - return crypto_sign_verify_detached( - sig.toCValuesRef(), - msg.toCValuesRef(), - msg.size.toULong(), - eddsaPub.toCValuesRef() - ) == 0 - } - - override fun keyExchangeEddsaEcdhe(eddsaPrivateKey: ByteArray, ecdhePublicKey: ByteArray): ByteArray { - val privateKey = sha512(eddsaPrivateKey).copyOfRange(0, 32) - val sharedKey = ByteArray(crypto_scalarmult_BYTES.toInt()) - crypto_scalarmult(sharedKey.toCValuesRef(), privateKey.toCValuesRef(), ecdhePublicKey.toCValuesRef()) - return sha512(sharedKey) - } - - override fun keyExchangeEcdheEddsa(ecdhePrivateKey: ByteArray, eddsaPublicKey: ByteArray): ByteArray { - val curve25519Pub = ByteArray(crypto_scalarmult_curve25519_BYTES.toInt()) - val cCurve25519Pub = curve25519Pub.toCValuesRef() - crypto_sign_ed25519_pk_to_curve25519(cCurve25519Pub, eddsaPublicKey.toCValuesRef()) - - val sharedKey = ByteArray(crypto_scalarmult_BYTES.toInt()) - crypto_scalarmult(sharedKey.toCValuesRef(), ecdhePrivateKey.toCValuesRef(), cCurve25519Pub) - return sha512(sharedKey) - } - - override fun rsaBlind(hm: ByteArray, bks: ByteArray, rsaPubEnc: ByteArray): ByteArray { - TODO("Not yet implemented") - } - - override fun rsaUnblind(sig: ByteArray, rsaPubEnc: ByteArray, bks: ByteArray): ByteArray { - TODO("Not yet implemented") - } - - override fun rsaVerify(hm: ByteArray, rsaSig: ByteArray, rsaPubEnc: ByteArray): Boolean { - TODO("Not yet implemented") - } - - private class NativeHashSha512State : HashSha512State { - private val state = nativeHeap.alloc<crypto_hash_sha512_state>() - private val statePointer = state.ptr - - init { - check(crypto_hash_sha512_init(statePointer) == 0) { "Error doing crypto_hash_sha512_init" } - } - - override fun update(data: ByteArray): HashSha512State { - val cInput = if (data.isEmpty()) null else data.toCValuesRef() - crypto_hash_sha512_update(statePointer, cInput, data.size.toULong()) - return this - } - - override fun final(): ByteArray { - val output = ByteArray(crypto_hash_sha512_bytes().toInt()) - crypto_hash_sha512_final(statePointer, output.toCValuesRef()) - nativeHeap.free(statePointer) - return output - } - - } - - private fun ByteArray.toCValuesRef(): CValuesRef<UByteVar> { - @Suppress("UNCHECKED_CAST") - return this.refTo(0) as CValuesRef<UByteVar> - } - -} diff --git a/src/linuxTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/src/linuxTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt deleted file mode 100644 index 162ce4e..0000000 --- a/src/linuxTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2020 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -package net.taler.wallet.kotlin - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.runBlocking - -actual fun runCoroutine(block: suspend (scope : CoroutineScope) -> Unit) = runBlocking { block(this) } - -actual fun getPlatformTarget(): PlatformTarget = PlatformTarget.NATIVE_LINUX diff --git a/src/iosMain/kotlin/net/taler/wallet/kotlin/Db.kt b/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt index 45cbfc3..45cbfc3 100644 --- a/src/iosMain/kotlin/net/taler/wallet/kotlin/Db.kt +++ b/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt diff --git a/src/iosMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt b/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt index 7860607..7860607 100644 --- a/src/iosMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt +++ b/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt diff --git a/src/iosTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt index fd053fa..c44a846 100644 --- a/src/iosTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt +++ b/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt @@ -21,4 +21,4 @@ import kotlinx.coroutines.runBlocking actual fun runCoroutine(block: suspend (scope : CoroutineScope) -> Unit) = runBlocking { block(this) } -actual fun getPlatformTarget(): PlatformTarget = PlatformTarget.NATIVE_IOS +actual fun getPlatformTarget(): PlatformTarget = PlatformTarget.NATIVE |