Skip to content

Commit

Permalink
Merge branch 'develop' into 'master'
Browse files Browse the repository at this point in the history
Develop

See merge request papers/airgap/airgap-vault!253
  • Loading branch information
godenzim committed Apr 23, 2021
2 parents d6a4c99 + cfe3ba1 commit 2c029f8
Show file tree
Hide file tree
Showing 114 changed files with 5,501 additions and 924 deletions.
40 changes: 34 additions & 6 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
image: docker:latest

variables:
SHARED_PATH: /builds/shared/$CI_PROJECT_PATH
GOOGLE_TAG: eu.gcr.io/papers-kubernetes/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:$CI_COMMIT_SHA
GOOGLE_TAG_ANDROID_CURRENT: eu.gcr.io/papers-kubernetes/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:android-$CI_COMMIT_SHA
GOOGLE_TAG_ELECTRON_LINUX_CURRENT: eu.gcr.io/papers-kubernetes/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME:electron-linux-$CI_COMMIT_SHA
Expand All @@ -11,6 +12,8 @@ stages:
- test
- qa
- native_build
- native_test
- publish

build_ionic:
stage: build
Expand Down Expand Up @@ -49,12 +52,29 @@ build_android:
- docker run --name $LOCAL_ANDROID $GOOGLE_TAG_ANDROID_CURRENT echo "container ran."
- docker cp $LOCAL_ANDROID:/app/android-release-unsigned.apk airgap-vault-release-unsigned-$CI_PIPELINE_ID.apk
- docker cp $LOCAL_ANDROID:/app/android-debug.apk airgap-vault-debug-$CI_PIPELINE_ID.apk
- docker cp $LOCAL_ANDROID:/app/android-appium.apk airgap-vault-appium-$CI_PIPELINE_ID.apk
after_script:
- docker rm -f $LOCAL_ANDROID || true
artifacts:
paths:
- airgap-vault-release-unsigned-$CI_PIPELINE_ID.apk
- airgap-vault-debug-$CI_PIPELINE_ID.apk
- airgap-vault-appium-$CI_PIPELINE_ID.apk

test_android:
stage: native_test
when: manual
tags:
- android-ui
before_script:
- echo "$APPIUM_CONFIG_JSON" > ./uitest/config.json
script:
- docker cp airgap-vault-appium-$CI_PIPELINE_ID.apk appium:/home/airgap-signed.apk
- docker create --network="host" -w /usr/src/uitest --name maven-runner-$CI_PIPELINE_ID maven:3.3-jdk-8 mvn test
- docker cp uitest maven-runner-$CI_PIPELINE_ID:/usr/src/
- docker start -a maven-runner-$CI_PIPELINE_ID
after_script:
- docker rm -f maven-runner-$CI_PIPELINE_ID || true

qa:
stage: qa
Expand Down Expand Up @@ -85,7 +105,6 @@ build_ios:
when: manual
before_script:
- echo "$IOS_BUILD_JSON" > build.json
- echo "$IOS_EXPORT_OPTIONS" > exportOptions.plist
script:
- export DEVELOPER_DIR=$XCODE_PATH
- nvm use 14
Expand All @@ -96,12 +115,21 @@ build_ios:
- npx ionic info
- npx ionic build --prod
- npx cap sync ios
- xcodebuild -workspace ios/App/App.xcworkspace -scheme "App" -destination generic/platform=iOS -configuration Release archive -archivePath ios/App.xcarchive MARKETING_VERSION=$VERSION CURRENT_PROJECT_VERSION=$CI_PIPELINE_ID -allowProvisioningUpdates
- xcodebuild -exportArchive -archivePath ios/App.xcarchive -exportOptionsPlist exportOptions.plist -exportPath ios/ -allowProvisioningUpdates
- xcrun altool --upload-app -f ios/App.ipa -u $IOS_USERNAME -p $IOS_PASSWORD
- xcodebuild -workspace ios/App/App.xcworkspace -scheme "App" -destination generic/platform=iOS -configuration Release archive -archivePath ios/airgap-vault-$VERSION-$CI_PIPELINE_ID.xcarchive MARKETING_VERSION=$VERSION CURRENT_PROJECT_VERSION=$CI_PIPELINE_ID -allowProvisioningUpdates
artifacts:
paths:
- ios/App.ipa
- ios/App.xcarchive
- ios/airgap-vault-$VERSION-$CI_PIPELINE_ID.xcarchive
tags:
- ios

publish_ios:
stage: publish
when: manual
before_script:
- echo "$IOS_EXPORT_OPTIONS" > exportOptions.plist
script:
- export DEVELOPER_DIR=$XCODE_PATH
- xcodebuild -exportArchive -archivePath ios/airgap-vault-$VERSION-$CI_PIPELINE_ID.xcarchive -exportOptionsPlist exportOptions.plist -exportPath ios/ -allowProvisioningUpdates
- xcrun altool --upload-app -f ios/App.ipa -u $IOS_USERNAME -p $IOS_PASSWORD
tags:
- ios
2 changes: 2 additions & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,5 @@ capacitor-cordova-android-plugins

# Copied web assets
app/src/main/assets/public

.cxx
20 changes: 20 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,28 @@ android {
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
debug {
buildConfigField "boolean", "APPIUM", "false"
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "APPIUM", "false"
}
appium {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "APPIUM", "true"
matchingFallbacks = ['release']
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
lintOptions {
abortOnError false
}
Expand Down Expand Up @@ -48,6 +65,9 @@ dependencies {

implementation 'com.google.android.material:material:1.2.0'
implementation 'com.scottyab:rootbeer-lib:0.0.7'

def saplingVersion = "0.0.6"
implementation "com.github.airgap-it:airgap-sapling:$saplingVersion"
}


Expand Down
2 changes: 2 additions & 0 deletions android/app/src/main/java/it/airgap/vault/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import it.airgap.vault.plugin.appinfo.AppInfo;
import it.airgap.vault.plugin.camerapreview.CameraPreview;
import it.airgap.vault.plugin.saplingnative.SaplingNative;
import it.airgap.vault.plugin.securityutils.SecurityUtils;

public class MainActivity extends BridgeActivity {
Expand All @@ -23,6 +24,7 @@ public void onCreate(Bundle savedInstanceState) {
add(CameraPreview.class);
add(AppInfo.class);
add(SecurityUtils.class);
add(SaplingNative.class);
}});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package it.airgap.vault.plugin.saplingnative

import com.getcapacitor.NativePlugin
import com.getcapacitor.Plugin
import com.getcapacitor.PluginCall
import com.getcapacitor.PluginMethod
import it.airgap.sapling.Sapling
import it.airgap.vault.util.*
import kotlin.concurrent.thread

@NativePlugin
class SaplingNative : Plugin() {
private val sapling: Sapling by lazy { Sapling() }

@PluginMethod
fun isSupported(call: PluginCall) {
call.resolveWithData(Key.IS_SUPPORTED to true)
}

@PluginMethod
fun initParameters(call: PluginCall) {
with(call) {
thread {
tryResolveCatchReject {
val spendParameters = readFromAssets("public/assets/sapling/sapling-spend.params")
val outputParameters = readFromAssets("public/assets/sapling/sapling-output.params")

sapling.initParameters(spendParameters, outputParameters)
}
}
}
}

@PluginMethod
fun initProvingContext(call: PluginCall) {
call.resolveWithData(Key.CONTEXT to sapling.initProvingContext().toString())
}

@PluginMethod
fun dropProvingContext(call: PluginCall) {
with(call) {
assertReceived(Param.CONTEXT)
sapling.dropProvingContext(context)
resolve()
}
}

@PluginMethod
fun prepareSpendDescription(call: PluginCall) {
with(call) {
assertReceived(
Param.CONTEXT,
Param.SPENDING_KEY,
Param.ADDRESS,
Param.RCM,
Param.AR,
Param.VALUE,
Param.ROOT,
Param.MERKLE_PATH
)

tryResolveWithDataCatchReject {
val spendDescription = sapling.prepareSpendDescription(
context,
spendingKey,
address,
rcm,
ar,
value,
root,
merklePath
)

listOf(Key.SPEND_DESCRIPTION to spendDescription.asHexString())
}
}
}

@PluginMethod
fun preparePartialOutputDescription(call: PluginCall) {
with(call) {
assertReceived(
Param.CONTEXT,
Param.ADDRESS,
Param.RCM,
Param.ESK,
Param.VALUE
)

tryResolveWithDataCatchReject {
val outputDescription = sapling.preparePartialOutputDescription(
context,
address,
rcm,
esk,
value
)

listOf(Key.OUTPUT_DESCRIPTION to outputDescription.asHexString())
}
}
}

@PluginMethod
fun createBindingSignature(call: PluginCall) {
with(call) {
assertReceived(Param.CONTEXT, Param.BALANCE, Param.SIGHASH)

tryResolveWithDataCatchReject {
val bindingSignature = sapling.createBindingSignature(context, balance, sighash)

listOf(Key.BINDING_SIGNATURE to bindingSignature.asHexString())
}
}
}

private val PluginCall.context: Long
get() = getString(Param.CONTEXT).toLong()

private val PluginCall.spendingKey: ByteArray
get() = getString(Param.SPENDING_KEY).asByteArray()

private val PluginCall.address: ByteArray
get() = getString(Param.ADDRESS).asByteArray()

private val PluginCall.rcm: ByteArray
get() = getString(Param.RCM).asByteArray()

private val PluginCall.ar: ByteArray
get() = getString(Param.AR).asByteArray()

private val PluginCall.esk: ByteArray
get() = getString(Param.ESK).asByteArray()

private val PluginCall.value: Long
get() = getString(Param.VALUE).toLong()

private val PluginCall.root: ByteArray
get() = getString(Param.ROOT).asByteArray()

private val PluginCall.merklePath: ByteArray
get() = getString(Param.MERKLE_PATH).asByteArray()

private val PluginCall.balance: Long
get() = getString(Param.BALANCE).toLong()

private val PluginCall.sighash: ByteArray
get() = getString(Param.SIGHASH).asByteArray()

private object Param {
const val CONTEXT = "context"

const val SPENDING_KEY = "spendingKey"
const val ADDRESS = "address"
const val RCM = "rcm"
const val AR = "ar"
const val ESK = "esk"
const val VALUE = "value"
const val ROOT = "root"
const val MERKLE_PATH = "merklePath"

const val BALANCE = "balance"
const val SIGHASH = "sighash"
}

private object Key {
const val IS_SUPPORTED = "isSupported"

const val CONTEXT = "context"
const val SPEND_DESCRIPTION = "spendDescription"
const val OUTPUT_DESCRIPTION = "outputDescription"
const val BINDING_SIGNATURE = "bindingSignature"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ class SecurityUtils : Plugin() {
@Synchronized get
@Synchronized set

private val integrityAssessment: Boolean
private val isDebuggable: Boolean
get() {
val isRooted = RootBeer(context).isRootedWithoutBusyBoxCheck
val nonDebuggable = BuildConfig.DEBUG || (context.applicationContext.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) == 0
return BuildConfig.DEBUG || (context.applicationContext.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0
}

return !isRooted && nonDebuggable
private val integrityAssessment: Boolean
get() {
return !RootBeer(context).isRootedWithoutBusyBoxCheck || isDebuggable || BuildConfig.APPIUM
}

/*
Expand Down Expand Up @@ -321,16 +323,20 @@ class SecurityUtils : Plugin() {

@PluginMethod
fun setWindowSecureFlag(call: PluginCall) {
with (activity) {
runOnUiThread { window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) }
if(!BuildConfig.APPIUM){
with (activity) {
runOnUiThread { window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) }
}
}
call.resolve()
}

@PluginMethod
fun clearWindowSecureFlag(call: PluginCall) {
with (activity) {
runOnUiThread { window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) }
if(!BuildConfig.APPIUM){
with (activity) {
runOnUiThread { window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) }
}
}
call.resolve()
}
Expand Down Expand Up @@ -466,4 +472,4 @@ class SecurityUtils : Plugin() {
private const val PREFERENCES_KEY_AUTOMATIC_AUTHENTICATION = "autoauth"
private const val MAX_AUTH_TRIES = 3
}
}
}
8 changes: 8 additions & 0 deletions android/app/src/main/java/it/airgap/vault/util/Hex.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package it.airgap.vault.util

fun String.isHex(): Boolean = matches(Regex("^(0x)?([0-9a-fA-F]{2})+$"))

fun String.asByteArray(): ByteArray =
if (isHex()) chunked(2).map { it.toInt(16).toByte() }.toByteArray() else toByteArray()

fun ByteArray.asHexString(): String = joinToString(separator = "") { "%02x".format(it) }
Loading

0 comments on commit 2c029f8

Please sign in to comment.