Skip to content

Commit

Permalink
Merge pull request #12 from ProtonProtocol/develop
Browse files Browse the repository at this point in the history
Fixed decode and authorize ESR
  • Loading branch information
Joey Harward authored Dec 4, 2020
2 parents 8d13433 + 0390d33 commit a477504
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 32 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Then add the following dependency to your module's build.gradle
```gradle
dependencies {
...
implementation "com.metallicus:protonsdk:0.7.0"
implementation "com.metallicus:protonsdk:0.7.1"
}
```

Expand Down
10 changes: 5 additions & 5 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
const val kotlinVersion = "1.4.10"
const val kotlinVersion = "1.4.10" // TODO: 1.4.20
const val orchidVersion = "0.21.1"

object ProtonSdk {
const val versionCode = 23
const val versionName = "0.7.0"
const val versionCode = 24
const val versionName = "0.7.1"
}

object BuildPlugins {
Expand Down Expand Up @@ -66,13 +66,13 @@ object Libraries {
const val workManager = "2.4.0"
const val okhttp3 = "4.9.0"
const val retrofit = "2.9.0"
const val dagger = "2.29.1"
const val dagger = "2.30.1"
const val daggerAssistedInject = "0.6.0"
const val coroutines = "1.4.0-M1"
const val timber = "4.7.1"
const val gson = "2.8.6"
const val guava = "29.0-jre"
const val esr = "1.0.2"
const val esr = "1.0.4"
}

const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
Expand Down
89 changes: 75 additions & 14 deletions protonsdk/src/main/java/com/metallicus/protonsdk/AccountModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,27 @@
package com.metallicus.protonsdk

import android.content.Context
import android.net.Uri
import android.util.Base64
import com.google.gson.*
import com.greymass.esr.ESR
import com.greymass.esr.SigningRequest
import com.greymass.esr.models.PermissionLevel
import com.greymass.esr.models.TransactionContext
import com.metallicus.protonsdk.common.SecureKeys
import com.metallicus.protonsdk.common.Prefs
import com.metallicus.protonsdk.common.Resource
import com.metallicus.protonsdk.di.DaggerInjector
import com.metallicus.protonsdk.eosio.commander.digest.Sha256
import com.metallicus.protonsdk.eosio.commander.ec.EosPrivateKey
import com.metallicus.protonsdk.eosio.commander.model.types.TypeChainId
import com.metallicus.protonsdk.model.*
import com.metallicus.protonsdk.repository.AccountContactRepository
import com.metallicus.protonsdk.repository.AccountRepository
import com.metallicus.protonsdk.repository.ChainProviderRepository
import com.metallicus.protonsdk.repository.ESRRepository
import timber.log.Timber
import java.util.*
import javax.inject.Inject

/**
Expand Down Expand Up @@ -328,19 +333,25 @@ class AccountModule {
return secureKeys.getPrivateKey(publicKey, pin).orEmpty()
}

private fun getActiveAccountSignature(pin: String): String {
private fun signActiveAccountName(pin: String): String {
val accountName = prefs.getActiveAccountName()
val publicKey = prefs.getActivePublicKey()
return signWithActiveKey(pin, accountName)
}

private fun signWithActiveKey(pin: String, data: String): String {
return signWithActiveKey(pin, data.toByteArray())
}

private fun signWithActiveKey(pin: String, data: ByteArray): String {
val publicKey = prefs.getActivePublicKey()
val privateKeyStr = secureKeys.getPrivateKey(publicKey, pin)
val privateKey = EosPrivateKey(privateKeyStr)
val sha256 = Sha256.from(accountName.toByteArray())
val signature = privateKey.sign(sha256).toString()
return signature
val sha256 = Sha256.from(data)
return privateKey.sign(sha256).toString()
}

suspend fun updateAccountName(chainAccount: ChainAccount, pin: String, name: String): Resource<ChainAccount> {
val signature = getActiveAccountSignature(pin)
val signature = signActiveAccountName(pin)

val accountName = chainAccount.account.accountName

Expand Down Expand Up @@ -371,7 +382,7 @@ class AccountModule {
}

suspend fun updateAccountAvatar(chainAccount: ChainAccount, pin: String, imageByteArray: ByteArray): Resource<ChainAccount> {
val signature = getActiveAccountSignature(pin)
val signature = signActiveAccountName(pin)

val accountName = chainAccount.account.accountName

Expand Down Expand Up @@ -426,11 +437,14 @@ class AccountModule {

val requestAccountName = signingRequest.info["req_account"].orEmpty()

val requestKey = ""
var requestKey = ""
if (signingRequest.isIdentity) {
val linkStr = signingRequest.info["link"]
val linkHexValue = signingRequest.infoPairs.find {
it.key == "link"
}?.hexValue.orEmpty()

// TODO: deserialize link as LinkCreate obj
val linkCreate = signingRequest.decodeLinkCreate(linkHexValue)
requestKey = linkCreate.requestKey
}

val returnPath = signingRequest.info["return_path"].orEmpty()
Expand Down Expand Up @@ -474,12 +488,59 @@ class AccountModule {
}
}

suspend fun authorizeESR(protonESR: ProtonESR): Resource<JsonObject> {
fun getAppName(): String {
val applicationInfo = context.applicationInfo
val stringId = applicationInfo.labelRes
return if (stringId == 0) {
applicationInfo.nonLocalizedLabel.toString()
} else {
context.getString(stringId)
}
}

suspend fun authorizeESR(pin: String, protonESR: ProtonESR): Resource<String> {
return try {
val callback = protonESR.signingRequest.callback
val resolvedSigningRequest =
protonESR.signingRequest.resolve(
PermissionLevel(protonESR.signingAccount.account.accountName, "active"), TransactionContext())

val response =
esrRepository.authorizeESR(callback, "")
protonESR.resolvedSigningRequest = resolvedSigningRequest

val chainIdStr = protonESR.signingAccount.chainProvider.chainId
val chainIdByteArray = TypeChainId(chainIdStr).bytes

val transactionByteArray = resolvedSigningRequest.serializedTransaction

val trailingByteArray = ByteArray(32)

val unsignedTransactionDigest = chainIdByteArray + transactionByteArray + trailingByteArray

val signature = signWithActiveKey(pin, unsignedTransactionDigest)

val callback = resolvedSigningRequest.getCallback(listOf(signature))

val sessionKey = EosPrivateKey()

val sessionChannel = Uri.Builder()
.scheme("https")
.authority("cb.anchor.link")
.appendPath(UUID.randomUUID().toString())
.build()

val linkName = getAppName()

val authParams = callback.payload
authParams["link_key"] = sessionKey.publicKey.toString()
authParams["link_ch"] = sessionChannel.toString()
authParams["link_name"] = linkName
//authParams.remove("SIG")
authParams["sig"] = signature

val originalESRUrlScheme = protonESR.originESRUrlScheme + ":"
val req = authParams["req"]?.replace("esr:", originalESRUrlScheme)
authParams["req"] = req

val response = esrRepository.authorizeESR(callback.url, authParams)
if (response.isSuccessful) {
Resource.success(response.body())
} else {
Expand Down
8 changes: 4 additions & 4 deletions protonsdk/src/main/java/com/metallicus/protonsdk/Proton.kt
Original file line number Diff line number Diff line change
Expand Up @@ -519,16 +519,16 @@ class Proton private constructor(context: Context) {
}
}

fun authorizeESR(protonESR: ProtonESR): LiveData<Resource<JsonObject>> = liveData {
fun authorizeESR(pin: String, protonESR: ProtonESR): LiveData<Resource<String>> = liveData {
emit(Resource.loading())

try {
emit(accountModule.authorizeESR(protonESR))
emit(accountModule.authorizeESR(pin, protonESR))
} catch (e: ProtonException) {
val error: Resource<JsonObject> = Resource.error(e)
val error: Resource<String> = Resource.error(e)
emit(error)
} catch (e: Exception) {
val error: Resource<JsonObject> = Resource.error(e.localizedMessage.orEmpty())
val error: Resource<String> = Resource.error(e.localizedMessage.orEmpty())
emit(error)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@
*/
package com.metallicus.protonsdk.api

import com.google.gson.JsonObject
import retrofit2.Response
import retrofit2.http.*

data class CancelAuthorizeESRBody(val error: String)
data class AuthorizeESRBody(val error: String)
data class CancelAuthorizeESRBody(val rejected: String)

interface ESRCallbackService {
@POST
Expand All @@ -37,5 +35,5 @@ interface ESRCallbackService {
@POST
suspend fun authorizeESR(
@Url url: String,
@Body body: AuthorizeESRBody): Response<JsonObject>
@Body body: Map<String, String>): Response<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ProtonESR(
val originESRUrlScheme: String,
val requestAccount: Account? = null,
val returnPath: String? = "",
val resolvedSigningRequest: ResolvedSigningRequest? = null//,
var resolvedSigningRequest: ResolvedSigningRequest? = null//,
//val actions: List<ProtonESRAction>
) {
fun getRequestAccountDisplayName(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
*/
package com.metallicus.protonsdk.repository

import com.google.gson.JsonObject
import com.metallicus.protonsdk.api.*
import retrofit2.Response
import javax.inject.Inject
Expand All @@ -35,7 +34,7 @@ class ESRRepository @Inject constructor(
return esrCallbackService.cancelAuthorizeESR(url, CancelAuthorizeESRBody(error))
}

suspend fun authorizeESR(url: String, error: String): Response<JsonObject> {
return esrCallbackService.authorizeESR(url, AuthorizeESRBody(error))
suspend fun authorizeESR(url: String, params: Map<String, String>): Response<String> {
return esrCallbackService.authorizeESR(url, params)
}
}

0 comments on commit a477504

Please sign in to comment.