Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EthSigner for signing byte strings and structured data (EIP712) #175

Merged
merged 1 commit into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add EthSigner for signing byte strings and structured data (EIP712)
  • Loading branch information
omurovch committed May 17, 2021
commit cb2f8221c365971e0e85a3a7f14cafc84d2a1309
4 changes: 4 additions & 0 deletions ethereumkit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ dependencies {
implementation 'androidx.room:room-rxjava2:2.2.5'
kapt 'androidx.room:room-compiler:2.2.5'

//Eip712
def kethereum_version = "0.83.6"
implementation "com.github.komputing.kethereum:erc712:$kethereum_version"

// Test helpers
testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:3.3.3'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import io.horizontalsystems.ethereumkit.api.models.AccountState
import io.horizontalsystems.ethereumkit.api.models.EthereumKitState
import io.horizontalsystems.ethereumkit.api.storage.ApiStorage
import io.horizontalsystems.ethereumkit.crypto.CryptoUtils
import io.horizontalsystems.ethereumkit.crypto.EIP712Encoder
import io.horizontalsystems.ethereumkit.crypto.EthSigner
import io.horizontalsystems.ethereumkit.crypto.InternalBouncyCastleProvider
import io.horizontalsystems.ethereumkit.models.*
import io.horizontalsystems.ethereumkit.network.*
Expand Down Expand Up @@ -43,6 +45,7 @@ class EthereumKit(
val walletId: String,
val etherscanService: EtherscanService,
private val decorationManager: DecorationManager,
private val ethSigner: EthSigner,
private val state: EthereumKitState = EthereumKitState()
) : IBlockchainListener {

Expand Down Expand Up @@ -194,6 +197,14 @@ class EthereumKit(
return transactionBuilder.encode(rawTransaction, signature)
}

fun signByteArray(message: ByteArray): ByteArray {
return ethSigner.signByteArray(message)
}

fun signTypedData(rawJsonMessage: String): ByteArray {
return ethSigner.signTypedData(rawJsonMessage)
}

fun getLogs(address: Address?, topics: List<ByteArray?>, fromBlock: Long, toBlock: Long, pullTimestamps: Boolean): Single<List<TransactionLog>> {
return blockchain.getLogs(address, topics, fromBlock, toBlock, pullTimestamps)
}
Expand Down Expand Up @@ -390,8 +401,9 @@ class EthereumKit(

val transactionManager = TransactionManager(address, transactionSyncManager, transactionStorage)
val decorationManager = DecorationManager(address)
val ethSigner = EthSigner(privateKey, CryptoUtils, EIP712Encoder())

val ethereumKit = EthereumKit(blockchain, transactionManager, transactionSyncManager, transactionBuilder, transactionSigner, connectionManager, address, networkType, walletId, etherscanService, decorationManager)
val ethereumKit = EthereumKit(blockchain, transactionManager, transactionSyncManager, transactionBuilder, transactionSigner, connectionManager, address, networkType, walletId, etherscanService, decorationManager, ethSigner)

blockchain.listener = ethereumKit
transactionSyncManager.set(ethereumKit)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.horizontalsystems.ethereumkit.crypto

import com.google.gson.Gson
import pm.gnosis.eip712.EIP712JsonAdapter
import pm.gnosis.eip712.EIP712JsonParser
import pm.gnosis.eip712.typedDataHash
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader

class EIP712Encoder {

private val eip712JsonAdapter = EIP712GsonAdapter()

fun encodeTypedDataHash(rawJsonMessage: String): ByteArray {
val domainWithMessage = EIP712JsonParser(eip712JsonAdapter).parseMessage(rawJsonMessage)
return typedDataHash(domainWithMessage.message, domainWithMessage.domain)
}

private class EIP712GsonAdapter : EIP712JsonAdapter {
private val gson = Gson()

override fun parse(inputStream: InputStream): EIP712JsonAdapter.Result {
val typedData = gson.fromJson(BufferedReader(InputStreamReader(inputStream)), TypedData::class.java)
return parse(typedData)
}

override fun parse(typedDataJson: String): EIP712JsonAdapter.Result {
val typedData = gson.fromJson(typedDataJson, TypedData::class.java)
return parse(typedData)
}

private fun parse(typedData: TypedData): EIP712JsonAdapter.Result {
return EIP712JsonAdapter.Result(
primaryType = typedData.primaryType,
domain = typedData.domain,
message = typedData.message,
types = typedData.types.mapValues { (_, types) -> types.map { EIP712JsonAdapter.Parameter(it.name, it.type) } }
)
}

data class TypedData(
val types: Map<String, List<TypeParam>>,
val primaryType: String,
val domain: Map<String, Any>,
val message: Map<String, Any>
)

data class TypeParam(
val name: String,
val type: String
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.horizontalsystems.ethereumkit.crypto

import java.math.BigInteger

class EthSigner(
private val privateKey: BigInteger,
private val cryptoUtils: CryptoUtils,
private val eip712Encoder: EIP712Encoder
) {

fun signByteArray(message: ByteArray): ByteArray {
val prefix = "\u0019Ethereum Signed Message:\n" + message.size
val hashedMessage = cryptoUtils.sha3(prefix.toByteArray() + message)
return sign(hashedMessage)
}

fun signTypedData(rawJsonMessage: String): ByteArray {
val encodedMessage = eip712Encoder.encodeTypedDataHash(rawJsonMessage)
return sign(encodedMessage)
}

private fun sign(message: ByteArray): ByteArray = cryptoUtils.ellipticSign(message, privateKey)

}