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

[INJIMOB-1862] Modifications in mdoc generation #73

Merged
merged 8 commits into from
Nov 5, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,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 @@ -252,7 +249,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 +265,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,15 @@ 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 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 @@ -26,22 +32,33 @@ class MdocGenerator {
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 fullDateFormatter = DateTimeFormatter.ISO_LOCAL_DATE
KiruthikaJeyashankar marked this conversation as resolved.
Show resolved Hide resolved
val issueDate: LocalDate = LocalDate.now()
val formattedIssueDate: String = issueDate.format(fullDateFormatter)
val expiryDate = issueDate.plusYears(5)
val formattedExpiryDate = expiryDate.format(fullDateFormatter)
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 +67,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 Down

This file was deleted.

Loading