summaryrefslogtreecommitdiff
path: root/wallet/src/commonMain/kotlin/net/taler/lib/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'wallet/src/commonMain/kotlin/net/taler/lib/wallet')
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/Amount.kt2
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/Base32Crockford.kt129
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/Time.kt2
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Exchanges.kt55
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Version.kt (renamed from wallet/src/commonMain/kotlin/net/taler/lib/wallet/Version.kt)2
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletApi.kt29
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletFactory.kt (renamed from wallet/src/commonMain/kotlin/net/taler/lib/wallet/WalletApi.kt)34
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Withdrawal.kt53
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Crypto.kt78
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/CryptoImpl.kt53
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Deposit.kt112
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Kdf.kt90
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Planchet.kt7
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Recoup.kt6
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Refresh.kt4
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Signature.kt5
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Denomination.kt2
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Exchange.kt43
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/lib/wallet/operations/Withdraw.kt44
19 files changed, 183 insertions, 567 deletions
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Amount.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Amount.kt
index 7273dba..e7ee929 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Amount.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Amount.kt
@@ -17,7 +17,7 @@
package net.taler.lib.wallet
import net.taler.lib.common.Amount
-import net.taler.lib.wallet.crypto.CryptoImpl.Companion.toByteArray
+import net.taler.lib.crypto.CryptoImpl.Companion.toByteArray
fun Amount.toByteArray() = ByteArray(8 + 4 + 12).apply {
value.toByteArray().copyInto(this, 0, 0, 8)
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Base32Crockford.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Base32Crockford.kt
deleted file mode 100644
index 2517e85..0000000
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Base32Crockford.kt
+++ /dev/null
@@ -1,129 +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.lib.wallet
-
-
-class EncodingException : Exception("Invalid encoding")
-
-
-object Base32Crockford {
-
- private fun ByteArray.getIntAt(index: Int): Int {
- val x = this[index].toInt()
- return if (x >= 0) x else (x + 256)
- }
-
- private var encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
-
- fun encode(data: ByteArray): String {
- val sb = StringBuilder()
- val size = data.size
- var bitBuf = 0
- var numBits = 0
- var pos = 0
- while (pos < size || numBits > 0) {
- if (pos < size && numBits < 5) {
- val d = data.getIntAt(pos++)
- bitBuf = (bitBuf shl 8) or d
- numBits += 8
- }
- if (numBits < 5) {
- // zero-padding
- bitBuf = bitBuf shl (5 - numBits)
- numBits = 5
- }
- val v = bitBuf.ushr(numBits - 5) and 31
- sb.append(encTable[v])
- numBits -= 5
- }
- return sb.toString()
- }
-
- fun decode(encoded: String): ByteArray {
- val size = encoded.length
- var bitpos = 0
- var bitbuf = 0
- var readPosition = 0
- var writePosition = 0
- val out = ByteArray(calculateDecodedDataLength(size))
-
- while (readPosition < size || bitpos > 0) {
- //println("at position $readPosition with bitpos $bitpos")
- if (readPosition < size) {
- val v = getValue(encoded[readPosition++])
- bitbuf = (bitbuf shl 5) or v
- bitpos += 5
- }
- while (bitpos >= 8) {
- val d = (bitbuf ushr (bitpos - 8)) and 0xFF
- out[writePosition] = d.toByte()
- writePosition++
- bitpos -= 8
- }
- if (readPosition == size && bitpos > 0) {
- bitbuf = (bitbuf shl (8 - bitpos)) and 0xFF
- bitpos = if (bitbuf == 0) 0 else 8
- }
- }
- return out
- }
-
- private fun getValue(chr: Char): Int {
- var a = chr
- when (a) {
- 'O', 'o' -> a = '0'
- 'i', 'I', 'l', 'L' -> a = '1'
- 'u', 'U' -> a = 'V'
- }
- if (a in '0'..'9')
- return a - '0'
- if (a in 'a'..'z')
- a = a.toUpperCase()
- var dec = 0
- if (a in 'A'..'Z') {
- if ('I' < a) dec++
- if ('L' < a) dec++
- if ('O' < a) dec++
- if ('U' < a) dec++
- return a - 'A' + 10 - dec
- }
- throw EncodingException()
- }
-
- /**
- * Compute the length of the resulting string when encoding data of the given size
- * in bytes.
- *
- * @param dataSize size of the data to encode in bytes
- * @return size of the string that would result from encoding
- */
- private fun calculateEncodedStringLength(dataSize: Int): Int {
- return (dataSize * 8 + 4) / 5
- }
-
- /**
- * Compute the length of the resulting data in bytes when decoding a (valid) string of the
- * given size.
- *
- * @param stringSize size of the string to decode
- * @return size of the resulting data in bytes
- */
- fun calculateDecodedDataLength(stringSize: Int): Int {
- return stringSize * 5 / 8
- }
-
-}
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Time.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Time.kt
index e67474b..6cb5a5c 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Time.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Time.kt
@@ -17,7 +17,7 @@
package net.taler.lib.wallet
import net.taler.lib.common.Timestamp
-import net.taler.lib.wallet.crypto.CryptoImpl.Companion.toByteArray
+import net.taler.lib.crypto.CryptoImpl.Companion.toByteArray
fun Timestamp.roundedToByteArray(): ByteArray = ByteArray(8).apply {
(truncateSeconds().ms * 1000L).toByteArray().copyInto(this)
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Exchanges.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Exchanges.kt
new file mode 100644
index 0000000..2542dd6
--- /dev/null
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Exchanges.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.lib.wallet.api
+
+import net.taler.lib.wallet.exchange.ExchangeRecord
+
+data class ExchangeListItem(
+ val exchangeBaseUrl: String,
+ val currency: String,
+ val paytoUris: List<String>
+) {
+ companion object {
+ fun fromExchangeRecord(exchange: ExchangeRecord): ExchangeListItem? {
+ return if (exchange.details == null || exchange.wireInfo == null) null
+ else ExchangeListItem(
+ exchangeBaseUrl = exchange.baseUrl,
+ currency = exchange.details.currency,
+ paytoUris = exchange.wireInfo.accounts.map {
+ it.paytoUri
+ }
+ )
+ }
+ }
+}
+
+data class GetExchangeTosResult(
+ /**
+ * Markdown version of the current ToS.
+ */
+ val tos: String,
+
+ /**
+ * Version tag of the current ToS.
+ */
+ val currentEtag: String,
+
+ /**
+ * Version tag of the last ToS that the user has accepted, if any.
+ */
+ val acceptedEtag: String? = null
+)
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Version.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Version.kt
index ba9be3c..12916d3 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/Version.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Version.kt
@@ -14,7 +14,7 @@
* GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-package net.taler.lib.wallet
+package net.taler.lib.wallet.api
import net.taler.lib.common.Version
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletApi.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletApi.kt
new file mode 100644
index 0000000..026c682
--- /dev/null
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletApi.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.lib.wallet.api
+
+import net.taler.lib.common.Amount
+
+public interface WalletApi {
+ fun getVersions(): SupportedVersions
+ fun getWithdrawalDetailsForUri(talerWithdrawUri: String): WithdrawalDetailsForUri
+ fun getWithdrawalDetailsForAmount(exchangeBaseUrl: String, amount: Amount): WithdrawalDetails
+ fun listExchanges(): List<ExchangeListItem>
+ fun addExchange(exchangeBaseUrl: String): ExchangeListItem
+ fun getExchangeTos(exchangeBaseUrl: String): GetExchangeTosResult
+ fun setExchangeTosAccepted(exchangeBaseUrl: String, acceptedEtag: String)
+}
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/WalletApi.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletFactory.kt
index bfe2825..d56f80c 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/WalletApi.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/WalletFactory.kt
@@ -14,23 +14,27 @@
* GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-package net.taler.lib.wallet
+package net.taler.lib.wallet.api
import io.ktor.client.HttpClient
import net.taler.lib.common.Amount
import net.taler.lib.common.Timestamp
import net.taler.lib.common.Version
-import net.taler.lib.wallet.crypto.Crypto
-import net.taler.lib.wallet.crypto.CryptoFactory
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.CryptoFactory
+import net.taler.lib.wallet.Db
+import net.taler.lib.wallet.DbFactory
import net.taler.lib.wallet.crypto.Signature
import net.taler.lib.wallet.exchange.Exchange
-import net.taler.lib.wallet.exchange.ExchangeListItem
-import net.taler.lib.wallet.exchange.GetExchangeTosResult
+import net.taler.lib.wallet.getDefaultHttpClient
import net.taler.lib.wallet.operations.Withdraw
-import net.taler.lib.wallet.operations.WithdrawalDetails
-import net.taler.lib.wallet.operations.WithdrawalDetailsForUri
-public class WalletApi {
+
+public expect class WalletFactory {
+ fun createWalletApi(): WalletApi
+}
+
+internal class WalletApiImpl {
private val httpClient: HttpClient = getDefaultHttpClient()
private val db: Db = DbFactory().openDb()
@@ -39,7 +43,7 @@ public class WalletApi {
private val exchangeManager: Exchange = Exchange(crypto, signature, httpClient, db = db)
private val withdrawManager = Withdraw(httpClient, db, crypto, signature, exchangeManager)
- public fun getVersions(): SupportedVersions {
+ fun getVersions(): SupportedVersions {
return SupportedVersions(
walletVersion = Version(8, 0, 0),
exchangeVersion = Version(8, 0, 0),
@@ -48,7 +52,7 @@ public class WalletApi {
)
}
- public suspend fun getWithdrawalDetailsForUri(talerWithdrawUri: String): WithdrawalDetailsForUri {
+ suspend fun getWithdrawalDetailsForUri(talerWithdrawUri: String): WithdrawalDetailsForUri {
val bankInfo = withdrawManager.getBankInfo(talerWithdrawUri)
return WithdrawalDetailsForUri(
amount = bankInfo.amount,
@@ -57,7 +61,7 @@ public class WalletApi {
)
}
- public suspend fun getWithdrawalDetailsForAmount(
+ suspend fun getWithdrawalDetailsForAmount(
exchangeBaseUrl: String,
amount: Amount
): WithdrawalDetails {
@@ -69,19 +73,19 @@ public class WalletApi {
)
}
- public suspend fun listExchanges(): List<ExchangeListItem> {
+ suspend fun listExchanges(): List<ExchangeListItem> {
return db.listExchanges().mapNotNull { exchange ->
ExchangeListItem.fromExchangeRecord(exchange)
}
}
- public suspend fun addExchange(exchangeBaseUrl: String): ExchangeListItem {
+ suspend fun addExchange(exchangeBaseUrl: String): ExchangeListItem {
val exchange = exchangeManager.updateFromUrl(exchangeBaseUrl)
db.put(exchange)
return ExchangeListItem.fromExchangeRecord(exchange) ?: TODO("error handling")
}
- public suspend fun getExchangeTos(exchangeBaseUrl: String): GetExchangeTosResult {
+ suspend fun getExchangeTos(exchangeBaseUrl: String): GetExchangeTosResult {
val record = db.getExchangeByBaseUrl(exchangeBaseUrl) ?: TODO("error handling")
return GetExchangeTosResult(
tos = record.termsOfServiceText ?: TODO("error handling"),
@@ -90,7 +94,7 @@ public class WalletApi {
)
}
- public suspend fun setExchangeTosAccepted(exchangeBaseUrl: String, acceptedEtag: String) {
+ suspend fun setExchangeTosAccepted(exchangeBaseUrl: String, acceptedEtag: String) {
db.transaction {
val record = getExchangeByBaseUrl(exchangeBaseUrl) ?: TODO("error handling")
val updatedRecord = record.copy(
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Withdrawal.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Withdrawal.kt
new file mode 100644
index 0000000..88c96a4
--- /dev/null
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/api/Withdrawal.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.lib.wallet.api
+
+import net.taler.lib.common.Amount
+
+public data class WithdrawalDetailsForUri(
+ /**
+ * The amount that the user wants to withdraw
+ */
+ val amount: Amount,
+
+ /**
+ * Exchange suggested by the wallet
+ */
+ val defaultExchangeBaseUrl: String?,
+
+ /**
+ * A list of exchanges that can be used for this withdrawal
+ */
+ val possibleExchanges: List<ExchangeListItem>
+)
+
+public data class WithdrawalDetails(
+ /**
+ * Did the user accept the current version of the exchange's terms of service?
+ */
+ val tosAccepted: Boolean,
+
+ /**
+ * Amount that will be transferred to the exchange.
+ */
+ val amountRaw: Amount,
+
+ /**
+ * Amount that will be added to the user's wallet balance.
+ */
+ val amountEffective: Amount
+)
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Crypto.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Crypto.kt
deleted file mode 100644
index cbb486a..0000000
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Crypto.kt
+++ /dev/null
@@ -1,78 +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.lib.wallet.crypto
-
-internal interface Crypto {
- fun sha256(input: ByteArray): ByteArray
- fun sha512(input: ByteArray): ByteArray
- fun getHashSha512State(): HashSha512State
- fun getRandomBytes(num: Int): ByteArray
- fun eddsaGetPublic(eddsaPrivateKey: ByteArray): ByteArray
- fun ecdheGetPublic(ecdhePrivateKey: ByteArray): ByteArray
- fun createEddsaKeyPair(): EddsaKeyPair
- fun createEcdheKeyPair(): EcdheKeyPair
- fun eddsaSign(msg: ByteArray, eddsaPrivateKey: ByteArray): ByteArray
- fun eddsaVerify(msg: ByteArray, sig: ByteArray, eddsaPub: ByteArray): Boolean
- fun keyExchangeEddsaEcdhe(eddsaPrivateKey: ByteArray, ecdhePublicKey: ByteArray): ByteArray
- fun keyExchangeEcdheEddsa(ecdhePrivateKey: ByteArray, eddsaPublicKey: ByteArray): ByteArray
- fun kdf(outputLength: Int, ikm: ByteArray, salt: ByteArray, info: ByteArray): ByteArray
- fun rsaBlind(hm: ByteArray, bks: ByteArray, rsaPubEnc: ByteArray): ByteArray
- fun rsaUnblind(sig: ByteArray, rsaPubEnc: ByteArray, bks: ByteArray): ByteArray
- fun rsaVerify(hm: ByteArray, rsaSig: ByteArray, rsaPubEnc: ByteArray): Boolean
- fun setupRefreshPlanchet(secretSeed: ByteArray, coinNumber: Int): FreshCoin
-}
-
-interface HashSha512State {
- fun update(data: ByteArray): HashSha512State
- fun final(): ByteArray
-}
-class EddsaKeyPair(val privateKey: ByteArray, val publicKey: ByteArray)
-class EcdheKeyPair(val privateKey: ByteArray, val publicKey: ByteArray)
-data class FreshCoin(val coinPublicKey: ByteArray, val coinPrivateKey: ByteArray, val bks: ByteArray) {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class != other::class) return false
- other as FreshCoin
- if (!coinPublicKey.contentEquals(other.coinPublicKey)) return false
- if (!coinPrivateKey.contentEquals(other.coinPrivateKey)) return false
- if (!bks.contentEquals(other.bks)) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = coinPublicKey.contentHashCode()
- result = 31 * result + coinPrivateKey.contentHashCode()
- result = 31 * result + bks.contentHashCode()
- return result
- }
-}
-
-internal expect object CryptoFactory {
- internal fun getCrypto(): Crypto
-}
-
-private val hexArray = arrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')
-
-fun ByteArray.toHexString(): String {
- val hexChars = CharArray(this.size * 2)
- for (j in this.indices) {
- val v = (this[j].toInt() and 0xFF)
- hexChars[j * 2] = hexArray[v ushr 4]
- hexChars[j * 2 + 1] = hexArray[v and 0x0F]
- }
- return String(hexChars)
-}
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/CryptoImpl.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/CryptoImpl.kt
deleted file mode 100644
index 6b7cb8e..0000000
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/CryptoImpl.kt
+++ /dev/null
@@ -1,53 +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.lib.wallet.crypto
-
-abstract class CryptoImpl : Crypto {
-
- companion object {
- fun Int.toByteArray(): ByteArray {
- val bytes = ByteArray(4)
- bytes[3] = (this and 0xFFFF).toByte()
- bytes[2] = ((this ushr 8) and 0xFFFF).toByte()
- bytes[1] = ((this ushr 16) and 0xFFFF).toByte()
- bytes[0] = ((this ushr 24) and 0xFFFF).toByte()
- return bytes
- }
-
- fun Long.toByteArray() = ByteArray(8).apply {
- var l = this@toByteArray
- for (i in 7 downTo 0) {
- this[i] = (l and 0xFF).toByte()
- l = l shr 8
- }
- }
- }
-
- override fun kdf(outputLength: Int, ikm: ByteArray, salt: ByteArray, info: ByteArray): ByteArray {
- return Kdf.kdf(outputLength, ikm, salt, info, { sha256(it) }, { sha512(it) })
- }
-
- override fun setupRefreshPlanchet(secretSeed: ByteArray, coinNumber: Int): FreshCoin {
- val info = "taler-coin-derivation".encodeToByteArray()
- val salt = coinNumber.toByteArray()
- val out = kdf(64, secretSeed, salt, info)
- val coinPrivateKey = out.copyOfRange(0, 32)
- val bks = out.copyOfRange(32, 64)
- return FreshCoin(eddsaGetPublic(coinPrivateKey), coinPrivateKey, bks)
- }
-
-}
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Deposit.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Deposit.kt
deleted file mode 100644
index 66255d8..0000000
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Deposit.kt
+++ /dev/null
@@ -1,112 +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.lib.wallet.crypto
-
-import net.taler.lib.common.Amount
-import net.taler.lib.common.Timestamp
-import net.taler.lib.wallet.Base32Crockford
-import net.taler.lib.wallet.crypto.Signature.Companion.WALLET_COIN_DEPOSIT
-import net.taler.lib.wallet.roundedToByteArray
-import net.taler.lib.wallet.toByteArray
-
-/**
- * Deposit operations are requested by a merchant during a transaction.
- * For the deposit operation, the merchant has to obtain the deposit permission for a coin
- * from their customer who owns the coin.
- *
- * When depositing a coin, the merchant is credited an amount specified in the deposit permission,
- * possibly a fraction of the total coin’s value,
- * minus the deposit fee as specified by the coin’s denomination.
- */
-internal class Deposit(private val crypto: Crypto) {
-
- /**
- * Private data required to make a deposit permission.
- */
- data class DepositInfo(
- val exchangeBaseUrl: String,
- val contractTermsHash: String,
- val coinPublicKey: String,
- val coinPrivateKey: String,
- val spendAmount: Amount,
- val timestamp: Timestamp,
- val refundDeadline: Timestamp,
- val merchantPublicKey: String,
- val feeDeposit: Amount,
- val wireInfoHash: String,
- val denomPublicKey: String,
- val denomSignature: String
- )
-
- /**
- * Deposit permission for a single coin.
- */
- // TODO rename _
- data class CoinDepositPermission(
- /**
- * Signature by the coin.
- */
- val coinSignature: String,
- /**
- * Public key of the coin being spend.
- */
- val coinPublicKey: String,
- /**
- * Signature made by the denomination public key.
- */
- val denomSignature: String,
- /**
- * The denomination public key associated with this coin.
- */
- val denomPublicKey: String,
- /**
- * The amount that is subtracted from this coin with this payment.
- */
- val contribution: String,
- /**
- * URL of the exchange this coin was withdrawn from.
- */
- val exchangeBaseUrl: String
- )
-
- /**
- * Generate updated coins (to store in the database) and deposit permissions for each given coin.
- */
- fun signDepositPermission(depositInfo: DepositInfo): CoinDepositPermission {
- val d = Signature.PurposeBuilder(WALLET_COIN_DEPOSIT)
- .put(Base32Crockford.decode(depositInfo.contractTermsHash))
- .put(Base32Crockford.decode(depositInfo.wireInfoHash))
- .put(depositInfo.timestamp.roundedToByteArray())
- .put(depositInfo.refundDeadline.roundedToByteArray())
- .put(depositInfo.spendAmount.toByteArray())
- .put(depositInfo.feeDeposit.toByteArray())
- .put(Base32Crockford.decode(depositInfo.merchantPublicKey))
- .put(Base32Crockford.decode(depositInfo.coinPublicKey))
- .build()
- val coinPriv = Base32Crockford.decode(depositInfo.coinPrivateKey);
- val coinSig = crypto.eddsaSign(d, coinPriv)
- return CoinDepositPermission(
- coinPublicKey = depositInfo.coinPublicKey,
- coinSignature = Base32Crockford.encode(coinSig),
- contribution = depositInfo.spendAmount.toJSONString(),
- denomPublicKey = depositInfo.denomPublicKey,
- exchangeBaseUrl = depositInfo.exchangeBaseUrl,
- denomSignature = depositInfo.denomSignature
- )
- }
-
-}
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Kdf.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Kdf.kt
deleted file mode 100644
index 2d714f8..0000000
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Kdf.kt
+++ /dev/null
@@ -1,90 +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.lib.wallet.crypto
-
-import kotlin.experimental.xor
-import kotlin.math.ceil
-
-internal object Kdf {
-
- const val HMAC_SHA256_BLOCK_SIZE = 64
- const val HMAC_SHA512_BLOCK_SIZE = 128
-
- fun kdf(
- outputLength: Int,
- ikm: ByteArray,
- salt: ByteArray,
- info: ByteArray,
- sha256: (ByteArray) -> ByteArray,
- sha512: (ByteArray) -> ByteArray
- ): ByteArray {
- //extract
- val prk = hmacSha512(salt, ikm, sha512)
-
- // expand
- val n = ceil(outputLength.toDouble() / 32).toInt()
- val output = ByteArray(n * 32)
- for (i in 0 until n) {
- val buf: ByteArray
- if (i == 0) {
- buf = ByteArray(info.size + 1)
- info.copyInto(buf)
- } else {
- buf = ByteArray(info.size + 1 + 32)
- for (j in 0 until 32) {
- buf[j] = output[(i - 1) * 32 + j]
- }
- info.copyInto(buf, destinationOffset = 32)
- }
- buf[buf.size - 1] = (i + 1).toByte()
- val chunk = hmacSha256(prk, buf, sha256)
- chunk.copyInto(output, destinationOffset = i * 32)
- }
- return output.copyOfRange(0, outputLength)
- }
-
- fun hmacSha256(key: ByteArray, message: ByteArray, sha256: (ByteArray) -> ByteArray): ByteArray {
- return hmac(HMAC_SHA256_BLOCK_SIZE, key, message) { sha256(it) }
- }
-
- fun hmacSha512(key: ByteArray, message: ByteArray, sha512: (ByteArray) -> ByteArray): ByteArray {
- return hmac(HMAC_SHA512_BLOCK_SIZE, key, message) { sha512(it) }
- }
-
- private fun hmac(blockSize: Int, key: ByteArray, message: ByteArray, hash: (ByteArray) -> ByteArray): ByteArray {
- var newKey = key
- if (newKey.size > blockSize) newKey = hash(newKey)
- if (newKey.size < blockSize) newKey = ByteArray(blockSize).apply {
- newKey.copyInto(this)
- }
- val okp = ByteArray(blockSize)
- val ikp = ByteArray(blockSize)
- for (i in 0 until blockSize) {
- ikp[i] = newKey[i] xor 0x36
- okp[i] = newKey[i] xor 0x5c
- }
- val b1 = ByteArray(blockSize + message.size)
- ikp.copyInto(b1)
- message.copyInto(b1, destinationOffset = blockSize)
- val h0 = hash(b1)
- val b2 = ByteArray(blockSize + h0.size)
- okp.copyInto(b2)
- h0.copyInto(b2, destinationOffset = blockSize)
- return hash(b2)
- }
-
-}
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Planchet.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Planchet.kt
index 22aa786..fa87348 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Planchet.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Planchet.kt
@@ -17,7 +17,10 @@
package net.taler.lib.wallet.crypto
import net.taler.lib.common.Amount
-import net.taler.lib.wallet.Base32Crockford
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.EddsaKeyPair
+import net.taler.lib.wallet.crypto.Signature.PurposeBuilder
+import net.taler.lib.crypto.Base32Crockford
import net.taler.lib.wallet.toByteArray
internal class Planchet(private val crypto: Crypto) {
@@ -53,7 +56,7 @@ internal class Planchet(private val crypto: Crypto) {
val denomPubHash = crypto.sha512(denomPub)
val evHash = crypto.sha512(ev)
- val withdrawRequest = Signature.PurposeBuilder(Signature.RESERVE_WITHDRAW)
+ val withdrawRequest = PurposeBuilder(Signature.RESERVE_WITHDRAW)
.put(reservePub)
.put(amountWithFee.toByteArray())
.put(req.feeWithdraw.toByteArray())
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Recoup.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Recoup.kt
index c7678e4..b87eff2 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Recoup.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Recoup.kt
@@ -16,10 +16,12 @@
package net.taler.lib.wallet.crypto
-import net.taler.lib.wallet.Base32Crockford
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.Base32Crockford
import net.taler.lib.wallet.CoinRecord
import net.taler.lib.wallet.CoinSourceType.REFRESH
import net.taler.lib.wallet.crypto.Signature.Companion.WALLET_COIN_RECOUP
+import net.taler.lib.wallet.crypto.Signature.PurposeBuilder
internal class Recoup(private val crypto: Crypto) {
@@ -64,7 +66,7 @@ internal class Recoup(private val crypto: Crypto) {
* Create and sign a message to recoup a coin.
*/
fun createRequest(coin: CoinRecord): Request {
- val p = Signature.PurposeBuilder(WALLET_COIN_RECOUP)
+ val p = PurposeBuilder(WALLET_COIN_RECOUP)
.put(Base32Crockford.decode(coin.coinPub))
.put(Base32Crockford.decode(coin.denomPubHash))
.put(Base32Crockford.decode(coin.blindingKey))
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Refresh.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Refresh.kt
index 90478ef..8098437 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Refresh.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Refresh.kt
@@ -17,9 +17,11 @@
package net.taler.lib.wallet.crypto
import net.taler.lib.common.Amount
-import net.taler.lib.wallet.Base32Crockford
+import net.taler.lib.crypto.Base32Crockford
import net.taler.lib.wallet.CoinRecord
import net.taler.lib.common.Timestamp
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.EcdheKeyPair
import net.taler.lib.wallet.crypto.Signature.Companion.WALLET_COIN_LINK
import net.taler.lib.wallet.crypto.Signature.Companion.WALLET_COIN_MELT
import net.taler.lib.wallet.crypto.Signature.PurposeBuilder
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Signature.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Signature.kt
index 006c004..8828509 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Signature.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/crypto/Signature.kt
@@ -16,8 +16,9 @@
package net.taler.lib.wallet.crypto
-import net.taler.lib.wallet.Base32Crockford
-import net.taler.lib.wallet.crypto.CryptoImpl.Companion.toByteArray
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.Base32Crockford
+import net.taler.lib.crypto.CryptoImpl.Companion.toByteArray
import net.taler.lib.wallet.exchange.DenominationRecord
import net.taler.lib.wallet.exchange.WireFee
import net.taler.lib.wallet.roundedToByteArray
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Denomination.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Denomination.kt
index fca9e3f..a515d96 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Denomination.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Denomination.kt
@@ -20,7 +20,7 @@ import kotlinx.serialization.Serializable
import net.taler.lib.common.Amount
import net.taler.lib.common.Duration
import net.taler.lib.common.Timestamp
-import net.taler.lib.wallet.Base32Crockford
+import net.taler.lib.crypto.Base32Crockford
import net.taler.lib.wallet.exchange.DenominationStatus.Unverified
import net.taler.lib.wallet.exchange.DenominationStatus.VerifiedGood
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Exchange.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Exchange.kt
index 4d89cd6..e685040 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Exchange.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/exchange/Exchange.kt
@@ -27,11 +27,11 @@ import io.ktor.http.HttpStatusCode
import net.taler.lib.common.Amount
import net.taler.lib.common.Timestamp
import net.taler.lib.common.Version
-import net.taler.lib.wallet.Base32Crockford
+import net.taler.lib.crypto.Base32Crockford
import net.taler.lib.wallet.Db
import net.taler.lib.wallet.DbFactory
-import net.taler.lib.wallet.crypto.Crypto
-import net.taler.lib.wallet.crypto.CryptoFactory
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.CryptoFactory
import net.taler.lib.wallet.crypto.Signature
import net.taler.lib.wallet.exchange.DenominationStatus.Unverified
import net.taler.lib.wallet.exchange.ExchangeUpdateReason.Initial
@@ -223,40 +223,3 @@ internal class Exchange(
}
}
-
-
-data class ExchangeListItem(
- val exchangeBaseUrl: String,
- val currency: String,
- val paytoUris: List<String>
-) {
- companion object {
- fun fromExchangeRecord(exchange: ExchangeRecord): ExchangeListItem? {
- return if (exchange.details == null || exchange.wireInfo == null) null
- else ExchangeListItem(
- exchangeBaseUrl = exchange.baseUrl,
- currency = exchange.details.currency,
- paytoUris = exchange.wireInfo.accounts.map {
- it.paytoUri
- }
- )
- }
- }
-}
-
-data class GetExchangeTosResult(
- /**
- * Markdown version of the current ToS.
- */
- val tos: String,
-
- /**
- * Version tag of the current ToS.
- */
- val currentEtag: String,
-
- /**
- * Version tag of the last ToS that the user has accepted, if any.
- */
- val acceptedEtag: String? = null
-)
diff --git a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/operations/Withdraw.kt b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/operations/Withdraw.kt
index 69c68d1..84851ba 100644
--- a/wallet/src/commonMain/kotlin/net/taler/lib/wallet/operations/Withdraw.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/lib/wallet/operations/Withdraw.kt
@@ -23,12 +23,11 @@ import kotlinx.serialization.Serializable
import net.taler.lib.common.Amount
import net.taler.lib.common.TalerUri.parseWithdrawUri
import net.taler.lib.common.Timestamp
-import net.taler.lib.common.Version
import net.taler.lib.common.Version.VersionMatchResult
+import net.taler.lib.crypto.Crypto
+import net.taler.lib.crypto.CryptoFactory
import net.taler.lib.wallet.Db
import net.taler.lib.wallet.DbFactory
-import net.taler.lib.wallet.crypto.Crypto
-import net.taler.lib.wallet.crypto.CryptoFactory
import net.taler.lib.wallet.crypto.Signature
import net.taler.lib.wallet.exchange.DenominationRecord
import net.taler.lib.wallet.exchange.DenominationSelectionInfo
@@ -36,7 +35,6 @@ import net.taler.lib.wallet.exchange.DenominationStatus.Unverified
import net.taler.lib.wallet.exchange.DenominationStatus.VerifiedBad
import net.taler.lib.wallet.exchange.DenominationStatus.VerifiedGood
import net.taler.lib.wallet.exchange.Exchange
-import net.taler.lib.wallet.exchange.ExchangeListItem
import net.taler.lib.wallet.exchange.ExchangeRecord
import net.taler.lib.wallet.exchange.ExchangeWireInfo
import net.taler.lib.wallet.exchange.SelectedDenomination
@@ -46,7 +44,9 @@ internal class Withdraw(
private val httpClient: HttpClient = getDefaultHttpClient(),
private val db: Db = DbFactory().openDb(),
private val crypto: Crypto = CryptoFactory.getCrypto(),
- private val signature: Signature = Signature(crypto),
+ private val signature: Signature = Signature(
+ crypto
+ ),
private val exchange: Exchange = Exchange(crypto, signature, httpClient, db = db)
) {
@@ -270,37 +270,3 @@ internal class Withdraw(
}
}
-
-data class WithdrawalDetailsForUri(
- /**
- * The amount that the user wants to withdraw
- */
- val amount: Amount,
-
- /**
- * Exchange suggested by the wallet
- */
- val defaultExchangeBaseUrl: String?,
-
- /**
- * A list of exchanges that can be used for this withdrawal
- */
- val possibleExchanges: List<ExchangeListItem>
-)
-
-data class WithdrawalDetails(
- /**
- * Did the user accept the current version of the exchange's terms of service?
- */
- val tosAccepted: Boolean,
-
- /**
- * Amount that will be transferred to the exchange.
- */
- val amountRaw: Amount,
-
- /**
- * Amount that will be added to the user's wallet balance.
- */
- val amountEffective: Amount
-)