Skip to content
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
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ jobs:
- name: Run integration tests
uses: reactivecircus/android-emulator-runner@v2
env:
TEST_BASE_URL: ${{ vars.TEST_BASE_URL }}
TEST_CUV_PROJECT_ID: ${{ vars.TEST_CUV_PROJECT_ID }}
TEST_CUV_PROJECT_URL: ${{ vars.TEST_CUV_PROJECT_URL }}
TEST_CUV_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TEST_CUV_SERVICE_ACCOUNT_TOKEN }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.miracl.trust.utilities.UtilitiesKt.USER_ID;
import static com.miracl.trust.utilities.UtilitiesKt.USER_PIN_LENGTH;
import static com.miracl.trust.utilities.UtilitiesKt.getUnixTime;
import static com.miracl.trust.utilities.UtilitiesKt.randomHash;
import static com.miracl.trust.utilities.UtilitiesKt.randomNumericPin;
import static com.miracl.trust.utilities.UtilitiesKt.randomUuidString;

Expand Down Expand Up @@ -37,12 +38,14 @@
import com.miracl.trust.utilities.JwtHelper;
import com.miracl.trust.utilities.MIRACLService;
import com.miracl.trust.utilities.SigningSessionCreateResponse;
import com.miracl.trust.utilities.VerifySignatureResponse;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.HexFormat;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
Expand Down Expand Up @@ -173,7 +176,9 @@ public void testAuthentication() {
Assert.assertTrue(result instanceof MIRACLSuccess);

String token = ((MIRACLSuccess<String, AuthenticationException>) result).getValue();
Jws<Claims> claims = JwtHelper.INSTANCE.parseSignedClaims(token, projectUrl);

String jwks = MIRACLService.INSTANCE.getJwkSet(projectUrl);
Jws<Claims> claims = JwtHelper.INSTANCE.parseSignedClaims(token, jwks);
Assert.assertTrue(claims.getPayload().getAudience().contains(projectId));
}));
testCoroutineDispatcher.getScheduler().advanceUntilIdle();
Expand Down Expand Up @@ -231,14 +236,18 @@ public void testNotificationAuthentication() {

@Test
public void testSigning() {
createUser(user -> miraclTrust.sign("message".getBytes(), user, pinProvider, result -> {
byte[] hash = randomHash();
createUser(user -> miraclTrust.sign(hash, user, pinProvider, result -> {
Assert.assertTrue(result instanceof MIRACLSuccess);

SigningResult signingResult = ((MIRACLSuccess<SigningResult, SigningException>) result).getValue();
Signature signature = signingResult.getSignature();
int timestamp = (int) (signingResult.getTimestamp().getTime() / 1000);
boolean signatureVerified = MIRACLService.INSTANCE.verifySignature(projectId, projectUrl, serviceAccountToken, signature, timestamp);
Assert.assertTrue(signatureVerified);
VerifySignatureResponse verifySignatureResponse = MIRACLService.INSTANCE.verifySignature(projectId, projectUrl, serviceAccountToken, signature, timestamp);

String jwks = MIRACLService.INSTANCE.getDvsJwkSet(projectUrl);
Jws<Claims> claims = JwtHelper.INSTANCE.parseSignedClaims(verifySignatureResponse.getCertificate(), jwks);
Assert.assertEquals(HexFormat.of().formatHex(hash), claims.getPayload().get("hash"));
}));
testCoroutineDispatcher.getScheduler().advanceUntilIdle();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ class AuthenticationTest {
Assert.assertTrue(result is MIRACLSuccess)
val token = (result as MIRACLSuccess).value

val claims = JwtHelper.parseSignedClaims(token, projectUrl)
val jwks = MIRACLService.getJwkSet(projectUrl)
val claims = JwtHelper.parseSignedClaims(token, jwks)
Assert.assertTrue(claims.payload.audience.contains(projectId))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ import com.miracl.trust.util.json.KotlinxSerializationJsonUtil
import com.miracl.trust.util.secondsSince1970
import com.miracl.trust.util.toHexString
import com.miracl.trust.util.toUser
import com.miracl.trust.utilities.JwtHelper
import com.miracl.trust.utilities.MIRACLService
import com.miracl.trust.utilities.USER_ID
import com.miracl.trust.utilities.USER_PIN_LENGTH
import com.miracl.trust.utilities.WRONG_FORMAT_PIN
import com.miracl.trust.utilities.generateWrongPin
import com.miracl.trust.utilities.randomHash
import com.miracl.trust.utilities.randomNumericPin
import com.miracl.trust.utilities.randomPinLength
import com.miracl.trust.utilities.randomUuidString
Expand All @@ -49,10 +51,6 @@ import org.junit.Test
import kotlin.random.Random

class DocumentSigningTest {
companion object {
private val HASH_RANGE = 1..10
}

private val projectId = BuildConfig.CUV_PROJECT_ID
private val projectUrl = BuildConfig.CUV_PROJECT_URL
private val serviceAccountToken = BuildConfig.CUV_SERVICE_ACCOUNT_TOKEN
Expand Down Expand Up @@ -129,8 +127,9 @@ class DocumentSigningTest {
@Test
fun testSuccessfulDocumentSigning() = runBlocking {
// Sign
val message = randomHash()
val result = documentSigner.sign(
message = randomHash(),
message = message,
user = user,
pinProvider = pinProvider,
deviceName = Build.MODEL
Expand All @@ -139,14 +138,17 @@ class DocumentSigningTest {

// Verify the signature
val signingResult = (result as MIRACLSuccess).value
val signatureVerified = MIRACLService.verifySignature(
val verifySignatureResponse = MIRACLService.verifySignature(
projectId = projectId,
projectUrl = projectUrl,
serviceAccountToken = serviceAccountToken,
signature = signingResult.signature,
timestamp = signingResult.timestamp.secondsSince1970()
)
Assert.assertTrue(signatureVerified)

val jwks = MIRACLService.getDvsJwkSet(projectUrl)
val claims = JwtHelper.parseSignedClaims(verifySignatureResponse.certificate, jwks)
Assert.assertEquals(message.toHexString(), claims.payload["hash"])
}

@Test
Expand All @@ -166,14 +168,17 @@ class DocumentSigningTest {
val signingResult = (result as MIRACLSuccess).value
Assert.assertEquals(signingSessionDetails.signingHash, signingResult.signature.hash)

val signatureVerified = MIRACLService.verifySignature(
val verifySignatureResponse = MIRACLService.verifySignature(
projectId = projectId,
projectUrl = projectUrl,
serviceAccountToken = serviceAccountToken,
signature = signingResult.signature,
timestamp = signingResult.timestamp.secondsSince1970()
)
Assert.assertTrue(signatureVerified)

val jwks = MIRACLService.getDvsJwkSet(projectUrl)
val claims = JwtHelper.parseSignedClaims(verifySignatureResponse.certificate, jwks)
Assert.assertEquals(signingSessionDetails.signingHash, claims.payload["hash"])
}

@Test
Expand Down Expand Up @@ -211,14 +216,17 @@ class DocumentSigningTest {
val signature = KotlinxSerializationJsonUtil.fromJsonString<Signature>(signatureJson)
Assert.assertEquals(crossDeviceSession.signingHash, signature.hash)

val verified = MIRACLService.verifySignature(
val verifySignatureResponse = MIRACLService.verifySignature(
projectId = projectId,
projectUrl = projectUrl,
serviceAccountToken = serviceAccountToken,
signature = signature,
timestamp = signature.timestamp
)
Assert.assertTrue(verified)

val jwks = MIRACLService.getDvsJwkSet(projectUrl)
val claims = JwtHelper.parseSignedClaims(verifySignatureResponse.certificate, jwks)
Assert.assertEquals(crossDeviceSession.signingHash, claims.payload["hash"])
}

@Test
Expand Down Expand Up @@ -453,9 +461,4 @@ class DocumentSigningTest {

return (getSigningSessionDetailsResult as MIRACLSuccess).value
}

private fun randomHash(): ByteArray =
(HASH_RANGE)
.map { Random.nextBytes(it) }
.reduce { acc, bytes -> acc + bytes }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.miracl.trust.utilities

import com.miracl.trust.MIRACLSuccess
import io.jsonwebtoken.Claims
import io.jsonwebtoken.Jws
import io.jsonwebtoken.JwtException
Expand All @@ -10,26 +9,21 @@ import io.jsonwebtoken.LocatorAdapter
import io.jsonwebtoken.ProtectedHeader
import io.jsonwebtoken.security.JwkSet
import io.jsonwebtoken.security.Jwks
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import java.security.Key

object JwtHelper {
fun parseSignedClaims(token: String, projectUrl: String): Jws<Claims> = runBlocking {
Jwts.parser()
.keyLocator(getKeyLocator(projectUrl))
fun parseSignedClaims(token: String, jwks: String): Jws<Claims> {
return Jwts.parser()
.keyLocator(getKeyLocator(jwks))
.build()
.parseSignedClaims(token)
}

private suspend fun getKeyLocator(projectUrl: String): Locator<Key> {
val result = MIRACLService.getJwkSet(projectUrl)
Assert.assertTrue(result is MIRACLSuccess)

val json = (result as MIRACLSuccess).value
private fun getKeyLocator(jwks: String): Locator<Key> {
val jwkSet: JwkSet = Jwks.setParser()
.build()
.parse(json)
.parse(jwks)

val keyLocator = object : LocatorAdapter<Key>() {
override fun locate(header: ProtectedHeader?): Key {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.miracl.trust.utilities

import android.net.Uri
import com.miracl.trust.MIRACLResult
import com.miracl.trust.MIRACLSuccess
import com.miracl.trust.network.ApiRequest
import com.miracl.trust.network.HttpMethod
import com.miracl.trust.network.HttpRequestExecutorException
import com.miracl.trust.network.HttpsURLConnectionRequestExecutor
import com.miracl.trust.signing.Signature
import com.miracl.trust.test.BuildConfig
Expand Down Expand Up @@ -74,6 +72,11 @@ data class VerifySignatureRequestBody(
val timestamp: Int
)

@Serializable
data class VerifySignatureResponse(
val certificate: String
)

object MIRACLService {
private val requestExecutor = HttpsURLConnectionRequestExecutor(10, 10)
private val json = Json {
Expand Down Expand Up @@ -168,7 +171,7 @@ object MIRACLService {
activateInitiateResponse.actToken
}

suspend fun getJwkSet(projectUrl: String): MIRACLResult<String, HttpRequestExecutorException> {
fun getJwkSet(projectUrl: String): String = runBlocking {
val apiRequest = ApiRequest(
method = HttpMethod.GET,
headers = null,
Expand All @@ -177,7 +180,19 @@ object MIRACLService {
url = "$projectUrl/.well-known/jwks"
)

return requestExecutor.execute(apiRequest)
(requestExecutor.execute(apiRequest) as MIRACLSuccess).value
}

fun getDvsJwkSet(projectUrl: String): String = runBlocking {
val apiRequest = ApiRequest(
method = HttpMethod.GET,
headers = null,
body = null,
params = null,
url = "$projectUrl/dvs/jwks"
)

(requestExecutor.execute(apiRequest) as MIRACLSuccess).value
}

fun createSigningSession(
Expand Down Expand Up @@ -212,7 +227,7 @@ object MIRACLService {
serviceAccountToken: String,
signature: Signature,
timestamp: Int
): Boolean = runBlocking {
): VerifySignatureResponse = runBlocking {
val apiRequest = ApiRequest(
method = HttpMethod.POST,
headers = mapOf("Authorization" to "Bearer $serviceAccountToken"),
Expand All @@ -222,6 +237,6 @@ object MIRACLService {
)

val result = requestExecutor.execute(apiRequest)
result is MIRACLSuccess
json.decodeFromString<VerifySignatureResponse>((result as MIRACLSuccess).value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ fun randomUuidString() = UUID.randomUUID().toString()

fun randomByteArray(size: Int = 20) = Random.nextBytes(size)

fun randomPinLength() = Random.nextInt(4..6)
fun randomPinLength() = Random.nextInt(4..6)

fun randomHash(): ByteArray =
(1..10)
.map { Random.nextBytes(it) }
.reduce { acc, bytes -> acc + bytes }
1 change: 0 additions & 1 deletion run-instrumentation-tests.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ echo $GMAIL_TOKEN > "${TEST_CREDENTIALS_DIR}/token.json"

#Instrumentation tests
./gradlew connectedAndroidTest \
-Pmiracltrust.baseUrl="$TEST_BASE_URL" \
-Pmiracltrust.cuvProjectId="$TEST_CUV_PROJECT_ID" \
-Pmiracltrust.cuvProjectUrl="$TEST_CUV_PROJECT_URL" \
-Pmiracltrust.cuvServiceAccountToken="$TEST_CUV_SERVICE_ACCOUNT_TOKEN" \
Expand Down