Skip to content

Commit

Permalink
B
Browse files Browse the repository at this point in the history
Merge branch 'develop' of https://github.com/mosip/digital-credential-plugins into develop
the commit.
Merged from upstream
  • Loading branch information
Piyush7034 committed Nov 11, 2024
2 parents 4cac364 + e1a182f commit d963dd6
Show file tree
Hide file tree
Showing 16 changed files with 886 additions and 49 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/push-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,44 @@ jobs:
OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }}
GPG_SECRET: ${{ secrets.GPG_SECRET }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

build-maven-mock-csv-dataprovider-plugin:
uses: mosip/kattu/.github/workflows/maven-build.yml@master-java21
with:
SERVICE_LOCATION: mock-csv-dataprovider-plugin
BUILD_ARTIFACT: mock-csv-dataprovider-plugin
secrets:
OSSRH_USER: ${{ secrets.OSSRH_USER }}
OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }}
OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }}
GPG_SECRET: ${{ secrets.GPG_SECRET }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

publish_to_nexus_mock-csv-dataprovider-plugin:
if: "${{ !contains(github.ref, 'master') && github.event_name != 'pull_request' && github.event_name != 'release' && github.event_name != 'prerelease' && github.event_name != 'publish' }}"
needs: build-maven-mock-csv-dataprovider-plugin
uses: mosip/kattu/.github/workflows/maven-publish-to-nexus.yml@master-java21
with:
SERVICE_LOCATION: ./mock-csv-dataprovider-plugin
secrets:
OSSRH_USER: ${{ secrets.OSSRH_USER }}
OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }}
OSSRH_URL: ${{ secrets.OSSRH_SNAPSHOT_URL }}
OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }}
GPG_SECRET: ${{ secrets.GPG_SECRET }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

sonar_analysis_mock-csv-dataprovider-plugin:
needs: build-maven-mock-csv-dataprovider-plugin
if: "${{ github.event_name != 'pull_request' }}"
uses: mosip/kattu/.github/workflows/maven-sonar-analysis.yml@master-java21
with:
SERVICE_LOCATION: ./mock-csv-dataprovider-plugin
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
ORG_KEY: ${{ secrets.ORG_KEY }}
OSSRH_USER: ${{ secrets.OSSRH_USER }}
OSSRH_SECRET: ${{ secrets.OSSRH_SECRET }}
OSSRH_TOKEN: ${{ secrets.OSSRH_TOKEN }}
GPG_SECRET: ${{ secrets.GPG_SECRET }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.mosip.certify.api.spi.VCIssuancePlugin;
import io.mosip.certify.api.util.ErrorConstants;
import io.mosip.certify.core.exception.CertifyException;
import io.mosip.certify.util.UUIDGenerator;
import io.mosip.esignet.core.dto.OIDCTransaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -95,9 +96,6 @@ public class MockVCIssuancePlugin implements VCIssuancePlugin {
@Value("${mosip.certify.mock.vciplugin.issuer.key-cert:empty}")
private String issuerKeyAndCertificate = null;

@Value("${mosip.certify.mock.vciplugin.ca.key-cert:empty}")
private String caKeyAndCertificate = null;

private static final String ACCESS_TOKEN_HASH = "accessTokenHash";

public static final String UTC_DATETIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
Expand Down Expand Up @@ -130,10 +128,12 @@ private JsonLDObject buildJsonLDWithLDProof(String accessTokenHash)
log.error("Unable to get KYC exchange data from MOCK", e);
}

String uuid = new UUIDGenerator().generate();

Map<String, Object> verCredJsonObject = new HashMap<>();
verCredJsonObject.put("@context", vcCredentialContexts);
verCredJsonObject.put("type", Arrays.asList("VerifiableCredential", "MockVerifiableCredential"));
verCredJsonObject.put("id", "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5");
verCredJsonObject.put("id", uuid);
verCredJsonObject.put("issuer", "did:example:123456789");
verCredJsonObject.put("issuanceDate", getUTCDateTime());
verCredJsonObject.put("credentialSubject", formattedMap);
Expand Down Expand Up @@ -252,7 +252,7 @@ public VCResult<String> getVerifiableCredential(VCRequestDto vcRequestDto, Strin
VCResult<String> vcResult = new VCResult<>();
String mdocVc = null;
try {
mdocVc = new io.mosip.certify.mock.integration.mocks.MdocGenerator().generate(mockDataForMsoMdoc(documentNumber),holderId, caKeyAndCertificate,issuerKeyAndCertificate);
mdocVc = new io.mosip.certify.mock.integration.mocks.MdocGenerator().generate(mockDataForMsoMdoc(documentNumber),holderId, issuerKeyAndCertificate);
} catch (Exception e) {
log.error("Exception on mdoc creation", e);
throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED);
Expand All @@ -268,18 +268,13 @@ public VCResult<String> getVerifiableCredential(VCRequestDto vcRequestDto, Strin
private Map<String, Object> mockDataForMsoMdoc(String documentNumber) {
Map<String, Object> data = new HashMap<>();
log.info("Setting up the data for mDoc");
//TODO: Populate datetime in real time
data.put("issue_date", "2024-01-12");
data.put("expiry_date", "2025-01-12");
data.put("family_name","Agatha");
data.put("given_name","Joseph");
data.put("birth_date", "1994-11-06");
data.put("issuing_country", "Island");
data.put("issuing_country", "IN");
data.put("document_number", documentNumber);
data.put("driving_privileges",new HashMap<>(){{
put("vehicle_category_code","A");
put("issue_date","2023-01-01");
put("expiry_date","2043-01-01");
}});
return data;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ import com.android.identity.internal.Util
import com.android.identity.mdoc.mso.MobileSecurityObjectGenerator
import com.android.identity.mdoc.util.MdocUtil
import com.android.identity.util.Timestamp
import io.mosip.certify.util.*
import io.mosip.certify.util.CBORConverter
import io.mosip.certify.util.JwkToKeyConverter
import io.mosip.certify.util.KeyPairAndCertificate
import io.mosip.certify.util.PKCS12Reader
import io.mosip.certify.util.UUIDGenerator
import java.io.ByteArrayOutputStream
import io.mosip.certify.util.IssuerKeyPairAndCertificate
import java.time.Instant
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.*


Expand All @@ -21,27 +28,38 @@ class MdocGenerator {
const val DIGEST_ALGORITHM = "SHA-256"
const val ECDSA_ALGORITHM = "SHA256withECDSA"
const val SEED = 42L
val FULL_DATE_FORMATTER: DateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE
}

fun generate(
data: MutableMap<String, out Any>,
holderId: String,
caKeyAndCertificate: String,
issuerKeyAndCertificate: String
): String? {
val issuerKeyPairAndCertificate: IssuerKeyPairAndCertificate? = readKeypairAndCertificates(
caKeyAndCertificate,issuerKeyAndCertificate
)
if(issuerKeyPairAndCertificate == null) {
val issuerDetails: KeyPairAndCertificate = PKCS12Reader().extract(issuerKeyAndCertificate)

if (issuerDetails.keyPair == null) {
throw RuntimeException("Unable to load Crypto details")
}
val devicePublicKey = JwkToKeyConverter().convertToPublicKey(holderId.replace("did:jwk:", ""))
val issuerKeypair = issuerKeyPairAndCertificate.issuerKeypair()
val issuerKeypair = issuerDetails.keyPair


val issueDate: LocalDate = LocalDate.now()
val formattedIssueDate: String = issueDate.format(FULL_DATE_FORMATTER)
val expiryDate = issueDate.plusYears(5)
val formattedExpiryDate = expiryDate.format(FULL_DATE_FORMATTER)
val nameSpacedDataBuilder: NameSpacedData.Builder = NameSpacedData.Builder()
//Validity of document is assigned here
nameSpacedDataBuilder.putEntryString(NAMESPACE, "issue_date", (formattedIssueDate))
nameSpacedDataBuilder.putEntryString(NAMESPACE, "expiry_date", (formattedExpiryDate))
(data.get("driving_privileges") as HashMap<String, String>)["issue_date"] = formattedIssueDate
(data.get("driving_privileges") as MutableMap<String, String>)["expiry_date"] = formattedExpiryDate
data.keys.forEach { key ->
nameSpacedDataBuilder.putEntryString(NAMESPACE, key, data[key].toString())
}


val nameSpacedData: NameSpacedData =
nameSpacedDataBuilder
.build()
Expand All @@ -50,48 +68,42 @@ class MdocGenerator {
val calculateDigestsForNameSpace =
MdocUtil.calculateDigestsForNameSpace(NAMESPACE, generatedIssuerNameSpaces, DIGEST_ALGORITHM)

val mobileSecurityObjectGenerator = MobileSecurityObjectGenerator(DIGEST_ALGORITHM, NAMESPACE, devicePublicKey)
val mobileSecurityObjectGenerator = MobileSecurityObjectGenerator(DIGEST_ALGORITHM, DOCTYPE, devicePublicKey)
mobileSecurityObjectGenerator.addDigestIdsForNamespace(NAMESPACE, calculateDigestsForNameSpace)
val expirationTime: Long = kotlinx.datetime.Instant.Companion.DISTANT_FUTURE.toEpochMilliseconds()
//Validity of MSO & its signature is assigned here
val currentTimestamp = Timestamp.now()
val validUntil = Timestamp.ofEpochMilli(addYearsToDate(currentTimestamp.toEpochMilli(), 2))
mobileSecurityObjectGenerator.setValidityInfo(
Timestamp.now(),
Timestamp.now(),
Timestamp.ofEpochMilli(expirationTime),
currentTimestamp,
currentTimestamp,
validUntil,
null
)
val mso: ByteArray = mobileSecurityObjectGenerator.generate()

val coseSign1Sign: DataItem = Util.coseSign1Sign(
issuerKeypair.private,
ECDSA_ALGORITHM,
mso.copyOf(),
Util.cborEncode(Util.cborBuildTaggedByteString(mso)),
null,
listOf(issuerKeyPairAndCertificate.caCertificate(), issuerKeyPairAndCertificate.issuerCertificate())
listOf(issuerDetails.certificate)
)

return construct(generatedIssuerNameSpaces, coseSign1Sign)
}

@Throws(Exception::class)
private fun readKeypairAndCertificates(caKeyAndCertificate: String,issuerKeyAndCertificate: String): IssuerKeyPairAndCertificate? {
val pkcS12Reader = PKCS12Reader()
val caDetails: KeyPairAndCertificate = pkcS12Reader.extract(caKeyAndCertificate)
val issuerDetails: KeyPairAndCertificate = pkcS12Reader.extract(issuerKeyAndCertificate)
if (issuerDetails != null && caDetails != null) {
return IssuerKeyPairAndCertificate(
issuerDetails.keyPair,
issuerDetails.certificate,
caDetails.certificate
)
}
return null
}

private fun construct(nameSpaces: MutableMap<String, MutableList<ByteArray>>, issuerAuth: DataItem): String? {
val mDoc = MDoc(DOCTYPE, IssuerSigned(nameSpaces, issuerAuth))
val cbor = mDoc.toCBOR()
return Base64.getUrlEncoder().encodeToString(cbor)
}

private fun addYearsToDate(dateInEpochMillis: Long, years: Int): Long {
val instant: Instant = Instant.ofEpochMilli(dateInEpochMillis)
val futureInstant: Instant = instant.plus((years*365).toLong(), ChronoUnit.DAYS)

return futureInstant.toEpochMilli()
}
}

data class MDoc(val docType: String, val issuerSigned: IssuerSigned) {
Expand All @@ -100,6 +112,7 @@ data class MDoc(val docType: String, val issuerSigned: IssuerSigned) {
CborEncoder(byteArrayOutputStream).encode(
CborBuilder().addMap()
.put("docType", docType)
.put("id", UUIDGenerator().generate())
.put(CBORConverter.toDataItem("issuerSigned"), CBORConverter.toDataItem(issuerSigned.toMap()))
.end()
.build()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.mosip.certify.util;

import java.util.UUID;

public class UUIDGenerator {
public String generate() {
return "urn:uuid:" + UUID.randomUUID();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.mosip.certify.mock.integration.mocks;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;


public class MdocGeneratorTest {
@Test
void shouldGenerateMdocDataSuccessfully() {
Map<String, Object> data = new HashMap<>();
data.put("family_name", "Mock");
data.put("given_name", "User");
data.put("birth_date", "2001-11-06");
data.put("issuing_country", "MK");
data.put("document_number", 1233);
data.put("driving_privileges", new HashMap<>() {{
put("vehicle_category_code", "A");
}});
String generatedMdoc = new MdocGenerator().generate(data,
"did:jwk:eyJrdHkiOiJFQyIsInVzZSI6InNpZyIsImNydiI6IlAtMjU2Iiwia2lkIjoiZEp2UzIzOXkyQk5Jc3VJdzZ4dG12M0QtLVotbC1yaDlZZ1NQYmhhOGRVVSIsIngiOiI0eDJtTUFHRHRMV3drRUtCMExnUHBYYmZzbVQtZ2FFeVg4c2lkZlFJV2NZIiwieSI6IlBkeU5LVlhyU1piNENZUW1vSzZsWDdadXgwRElCY25oSjktX2E3WmxZdGMiLCJhbGciOiJFUzI1NiJ9",
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg2U+wq/9uXZdMqJgjpaZ0SIkXLlVzZzVkhFKZIxD8adyhRANCAASO1Fw5eAjJH/GoYH4zp3SqSuNBY4EYZ2U+B8h9vbFbR6BkBUTP/nkhcKh9ZqmtEbFfupBOU0BnIHKeJrLaPOFH||LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJ3RENDQVdXZ0F3SUJBZ0lVZnFVZ0pPd0NHUXlLOGkwNVAyL29sNW01dkNZd0NnWUlLb1pJemowRUF3SXcKVGpFTE1Ba0dBMVVFQmhNQ1RVc3hEakFNQmdOVkJBZ01CVTFMTFV0Qk1SRXdEd1lEVlFRSERBaE5iMk5yUTJsMAplVEVOTUFzR0ExVUVDZ3dFVFc5amF6RU5NQXNHQTFVRUN3d0VUVzlqYXpBZUZ3MHlOREV3TWpJd056QXlOVEJhCkZ3MHlOVEV3TWpJd056QXlOVEJhTUU0eEN6QUpCZ05WQkFZVEFrMUxNUTR3REFZRFZRUUlEQVZOU3kxTFFURVIKTUE4R0ExVUVCd3dJVFc5amEwTnBkSGt4RFRBTEJnTlZCQW9NQkUxdlkyc3hEVEFMQmdOVkJBc01CRTF2WTJzdwpXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU08xRnc1ZUFqSkgvR29ZSDR6cDNTcVN1TkJZNEVZCloyVStCOGg5dmJGYlI2QmtCVVRQL25raGNLaDlacW10RWJGZnVwQk9VMEJuSUhLZUpyTGFQT0ZIb3lFd0h6QWQKQmdOVkhRNEVGZ1FVMm9BZktsQmh6QmFoNVIrWXkvaEp2TzJpWVc4d0NnWUlLb1pJemowRUF3SURTUUF3UmdJaApBT3lDelAzQUpybnE2U2wvSytyM2Z2VnZrYUdSSmx2ZndidkVXaDlhQVcwbkFpRUFyRUFLV1VnNjF5VjRvUk1NClVacmRxdG9BT01wM2FLeHFGQzFkbkJDWSt2VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=");

Assertions.assertNotNull(generatedMdoc);
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.mosip.certify.util;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertTrue;

class UUIDGeneratorTest {
@Test
void shouldReturnUUIDInRequiredFormatWhenGenerated() {
String generatedUUID = new UUIDGenerator().generate();

assertTrue(generatedUUID.matches("^urn:uuid:[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$"));
}
}
Loading

0 comments on commit d963dd6

Please sign in to comment.