diff --git a/pom.xml b/pom.xml index 2a78b18..90d2913 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,8 @@ 5.4.6 1.18.20 4.3.3 - 0.2.2-SNAPSHOT + 1.0.1 + 1.5.10 1.5.7 5.7.1 1.4.2.Final @@ -77,7 +78,7 @@ ehd-github - https://maven.pkg.github.com/ehn-digital-green-development/* + https://maven.pkg.github.com/ehn-dcc-development/* @@ -235,18 +236,28 @@ ehn.techiop.hcert - hcert-kotlin + hcert-kotlin-jvm ${hcert-kotlin.version} - com.augustcellars.cose - cose-java - 1.1.0 + org.jetbrains.kotlinx + kotlinx-serialization-json + 1.2.1 org.jetbrains.kotlin kotlin-stdlib-jdk8 - 1.4.31 + ${kotlin.version} + + + org.jetbrains.kotlinx + kotlinx-datetime-jvm + 0.2.1 + + + com.augustcellars.cose + cose-java + 1.1.0 com.fasterxml.jackson.dataformat diff --git a/src/main/java/eu/europa/ec/dgc/issuance/config/HcertLibConfig.java b/src/main/java/eu/europa/ec/dgc/issuance/config/HcertLibConfig.java index 81ee537..5230271 100644 --- a/src/main/java/eu/europa/ec/dgc/issuance/config/HcertLibConfig.java +++ b/src/main/java/eu/europa/ec/dgc/issuance/config/HcertLibConfig.java @@ -1,13 +1,17 @@ package eu.europa.ec.dgc.issuance.config; import ehn.techiop.hcert.kotlin.chain.Base45Service; +import ehn.techiop.hcert.kotlin.chain.CborService; import ehn.techiop.hcert.kotlin.chain.CompressorService; import ehn.techiop.hcert.kotlin.chain.ContextIdentifierService; import ehn.techiop.hcert.kotlin.chain.CoseService; +import ehn.techiop.hcert.kotlin.chain.SchemaValidationService; import ehn.techiop.hcert.kotlin.chain.impl.DefaultBase45Service; +import ehn.techiop.hcert.kotlin.chain.impl.DefaultCborService; import ehn.techiop.hcert.kotlin.chain.impl.DefaultCompressorService; import ehn.techiop.hcert.kotlin.chain.impl.DefaultContextIdentifierService; import ehn.techiop.hcert.kotlin.chain.impl.DefaultCoseService; +import ehn.techiop.hcert.kotlin.chain.impl.DefaultSchemaValidationService; import eu.europa.ec.dgc.issuance.service.EhdCryptoService; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; @@ -38,4 +42,14 @@ Base45Service base45Service() { return new DefaultBase45Service(); } + @Bean + CborService cborService() { + return new DefaultCborService(); + } + + @Bean + SchemaValidationService schemaValidationService() { + return new DefaultSchemaValidationService(); + } + } diff --git a/src/main/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciBackendController.java b/src/main/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciBackendController.java index faad8f7..467e35c 100644 --- a/src/main/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciBackendController.java +++ b/src/main/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciBackendController.java @@ -1,12 +1,10 @@ package eu.europa.ec.dgc.issuance.restapi.controller; -import ehn.techiop.hcert.data.Eudgc; import eu.europa.ec.dgc.issuance.restapi.dto.EgdcCodeData; import eu.europa.ec.dgc.issuance.service.DgciService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import javax.validation.Valid; import lombok.AllArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.http.MediaType; @@ -17,7 +15,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/context") +@RequestMapping("/dgci") @AllArgsConstructor @ConditionalOnExpression("${issuance.endpoints.backendIssuing:false}") public class DgciBackendController { @@ -31,7 +29,7 @@ public class DgciBackendController { @ApiResponse(responseCode = "200", description = "signed edgc qr code created"), @ApiResponse(responseCode = "400", description = "wrong issue data")}) @PutMapping(value = "/issue", consumes = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity createEdgc(@Valid @RequestBody Eudgc eudgc) { + public ResponseEntity createEdgc(@RequestBody String eudgc) { EgdcCodeData egdcCodeData = dgciService.createEdgc(eudgc); return ResponseEntity.ok(egdcCodeData); } diff --git a/src/main/java/eu/europa/ec/dgc/issuance/restapi/dto/EgdcCodeData.java b/src/main/java/eu/europa/ec/dgc/issuance/restapi/dto/EgdcCodeData.java index 06484f1..370023e 100644 --- a/src/main/java/eu/europa/ec/dgc/issuance/restapi/dto/EgdcCodeData.java +++ b/src/main/java/eu/europa/ec/dgc/issuance/restapi/dto/EgdcCodeData.java @@ -5,6 +5,6 @@ @Data public class EgdcCodeData { String dgci; - String qrcCode; + String qrCode; String tan; } diff --git a/src/main/java/eu/europa/ec/dgc/issuance/service/ConfigurableCborService.java b/src/main/java/eu/europa/ec/dgc/issuance/service/ConfigurableCborService.java deleted file mode 100644 index ffc30e2..0000000 --- a/src/main/java/eu/europa/ec/dgc/issuance/service/ConfigurableCborService.java +++ /dev/null @@ -1,49 +0,0 @@ -package eu.europa.ec.dgc.issuance.service; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.dataformat.cbor.databind.CBORMapper; -import com.upokecenter.cbor.CBORObject; -import ehn.techiop.hcert.data.Eudgc; -import ehn.techiop.hcert.kotlin.chain.impl.DefaultCborService; -import eu.europa.ec.dgc.issuance.config.IssuanceConfigProperties; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.springframework.stereotype.Service; - -/** - * own cbor service. - * The default one inject fixed country code and expiration period - * - */ -@Service -@RequiredArgsConstructor -public class ConfigurableCborService extends DefaultCborService { - public static final int ISSUER = 1; - public static final int ISSUED_AT = 6; - public static final int EXPIRATION = 4; - public static final int HCERT = -260; - public static final int HCERT_VERSION = 1; - - private final ExpirationService expirationService; - private final IssuanceConfigProperties issuanceConfigProperties; - - @Override - public byte[] encode(@NotNull Eudgc input) { - byte[] cbor; - try { - cbor = new CBORMapper().writeValueAsBytes(input); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException(e); - } - ExpirationService.CwtTimeFields cwtTimes = expirationService.calculateCwtExpiration(input); - CBORObject coseContainer = CBORObject.NewMap(); - coseContainer.set(CBORObject.FromObject(ISSUER), - CBORObject.FromObject(issuanceConfigProperties.getCountryCode())); - coseContainer.set(CBORObject.FromObject(ISSUED_AT),CBORObject.FromObject(cwtTimes.getIssuedAt())); - coseContainer.set(CBORObject.FromObject(EXPIRATION),CBORObject.FromObject(cwtTimes.getExpiration())); - CBORObject hcert = CBORObject.NewMap(); - hcert.set(CBORObject.FromObject(HCERT_VERSION),CBORObject.DecodeFromBytes(cbor)); - coseContainer.set(CBORObject.FromObject(HCERT),hcert); - return coseContainer.EncodeToBytes(); - } -} diff --git a/src/main/java/eu/europa/ec/dgc/issuance/service/ConfigurableCwtService.java b/src/main/java/eu/europa/ec/dgc/issuance/service/ConfigurableCwtService.java new file mode 100644 index 0000000..524855e --- /dev/null +++ b/src/main/java/eu/europa/ec/dgc/issuance/service/ConfigurableCwtService.java @@ -0,0 +1,43 @@ +package eu.europa.ec.dgc.issuance.service; + +import com.upokecenter.cbor.CBORObject; +import ehn.techiop.hcert.kotlin.chain.CwtService; +import ehn.techiop.hcert.kotlin.chain.VerificationResult; +import ehn.techiop.hcert.kotlin.crypto.CwtHeaderKeys; +import ehn.techiop.hcert.kotlin.data.GreenCertificate; +import eu.europa.ec.dgc.issuance.config.IssuanceConfigProperties; +import kotlinx.serialization.json.Json; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ConfigurableCwtService implements CwtService { + private final ExpirationService expirationService; + private final IssuanceConfigProperties issuanceConfigProperties; + + @NotNull + @Override + public byte[] decode(@NotNull byte[] bytes, @NotNull VerificationResult verificationResult) { + throw new UnsupportedOperationException("decoding not supported"); + } + + @NotNull + @Override + public byte[] encode(@NotNull byte[] bytes) { + CBORObject cwtMap = CBORObject.NewMap(); + cwtMap.Add(CwtHeaderKeys.ISSUER.getIntVal(), issuanceConfigProperties.getCountryCode()); + CBORObject dcc = CBORObject.DecodeFromBytes(bytes); + GreenCertificate greenCertificate = Json.Default.decodeFromString(GreenCertificate.Companion.serializer(), + dcc.ToJSONString()); + ExpirationService.CwtTimeFields cwtTimes = expirationService.calculateCwtExpiration(greenCertificate); + + cwtMap.Add(CwtHeaderKeys.ISSUED_AT.getIntVal(), cwtTimes.issuedAt); + cwtMap.Add(CwtHeaderKeys.EXPIRATION.getIntVal(), cwtTimes.expiration); + CBORObject hcertMap = CBORObject.NewMap(); + hcertMap.Add(CwtHeaderKeys.EUDGC_IN_HCERT.getIntVal(),dcc); + cwtMap.Add(CwtHeaderKeys.HCERT.getIntVal(), hcertMap); + return cwtMap.EncodeToBytes(); + } +} diff --git a/src/main/java/eu/europa/ec/dgc/issuance/service/DgciService.java b/src/main/java/eu/europa/ec/dgc/issuance/service/DgciService.java index 2db57d9..0f7d0ee 100644 --- a/src/main/java/eu/europa/ec/dgc/issuance/service/DgciService.java +++ b/src/main/java/eu/europa/ec/dgc/issuance/service/DgciService.java @@ -23,13 +23,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.nimbusds.jose.jwk.Curve; import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.util.Base64URL; import com.upokecenter.cbor.CBORObject; import com.upokecenter.cbor.CBORType; -import ehn.techiop.hcert.data.Eudgc; import ehn.techiop.hcert.kotlin.chain.Base45Service; import ehn.techiop.hcert.kotlin.chain.CborService; import ehn.techiop.hcert.kotlin.chain.Chain; @@ -37,6 +37,9 @@ import ehn.techiop.hcert.kotlin.chain.CompressorService; import ehn.techiop.hcert.kotlin.chain.ContextIdentifierService; import ehn.techiop.hcert.kotlin.chain.CoseService; +import ehn.techiop.hcert.kotlin.chain.CwtService; +import ehn.techiop.hcert.kotlin.chain.SchemaValidationService; +import ehn.techiop.hcert.kotlin.data.GreenCertificate; import eu.europa.ec.dgc.issuance.config.IssuanceConfigProperties; import eu.europa.ec.dgc.issuance.entity.DgciEntity; import eu.europa.ec.dgc.issuance.entity.GreenCertificateType; @@ -71,6 +74,8 @@ import java.util.Base64; import java.util.List; import java.util.Optional; +import kotlinx.serialization.SerializationException; +import kotlinx.serialization.json.Json; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; @@ -93,9 +98,11 @@ public enum DgciStatus { private final DgciGenerator dgciGenerator; private final CborService cborService; private final CoseService coseService; + private final CwtService cwtService; private final ContextIdentifierService contextIdentifierService; private final CompressorService compressorService; private final Base45Service base45Service; + private final SchemaValidationService schemaValidationService; private final ExpirationService expirationService; private static final int MAX_CLAIM_RETRY_TAN = 3; @@ -363,37 +370,42 @@ private boolean verifySignature(ClaimRequest claimRequest) { /** * Create edgc in backend. * - * @param eudgc certificate + * @param dccJson certificate * @return edgc qr code and tan */ - public EgdcCodeData createEdgc(Eudgc eudgc) { + public EgdcCodeData createEdgc(String dccJson) { String dgci = dgciGenerator.newDgci(); + dccJson = updateCI(dccJson, dgci); + + GreenCertificate eudgc; + try { + eudgc = Json.Default.decodeFromString(GreenCertificate.Companion.serializer(), dccJson); + } catch (SerializationException se) { + throw new WrongRequest(se.getMessage()); + } GreenCertificateType greenCertificateType = GreenCertificateType.Vaccination; - if (eudgc.getR() != null) { - for (val v : eudgc.getR()) { - v.setCi(dgci); + if (eudgc.getRecoveryStatements() != null) { + for (val v : eudgc.getRecoveryStatements()) { greenCertificateType = GreenCertificateType.Recovery; } } - if (eudgc.getT() != null) { - for (val v : eudgc.getT()) { - v.setCi(dgci); + if (eudgc.getTests() != null) { + for (val v : eudgc.getTests()) { greenCertificateType = GreenCertificateType.Test; } } - if (eudgc.getV() != null) { - for (val v : eudgc.getV()) { - v.setCi(dgci); + if (eudgc.getVaccinations() != null) { + for (val v : eudgc.getVaccinations()) { greenCertificateType = GreenCertificateType.Vaccination; } } Chain cborProcessingChain = - new Chain(cborService, coseService, - contextIdentifierService, compressorService, base45Service); + new Chain(cborService, cwtService, coseService, + contextIdentifierService, compressorService, base45Service, schemaValidationService); ChainResult chainResult = cborProcessingChain.encode(eudgc); EgdcCodeData egdcCodeData = new EgdcCodeData(); - egdcCodeData.setQrcCode(chainResult.getStep5Prefixed()); + egdcCodeData.setQrCode(chainResult.getStep5Prefixed()); egdcCodeData.setDgci(dgci); Tan ta = Tan.create(); egdcCodeData.setTan(ta.getRawTan()); @@ -411,6 +423,34 @@ public EgdcCodeData createEdgc(Eudgc eudgc) { return egdcCodeData; } + private String updateCI(String dccJson, String dgci) { + // The fields can be not modified on GreenCertificate object so we need to set ci on json level + ObjectMapper mapper = new ObjectMapper(); + try { + JsonNode dccTree = mapper.readTree(dccJson); + updateCI(dccTree, dgci); + return mapper.writeValueAsString(dccTree); + } catch (JsonProcessingException e) { + throw new WrongRequest(e.getMessage()); + } + } + + private void updateCI(JsonNode jsonNode, String dgci) { + if (jsonNode.isObject()) { + if (jsonNode.has("ci")) { + ((ObjectNode)jsonNode).put("ci",dgci); + } else { + for (JsonNode value : jsonNode) { + updateCI(value, dgci); + } + } + } else if (jsonNode.isArray()) { + for (JsonNode item : jsonNode) { + updateCI(item, dgci); + } + } + } + /** * Check if dgci exists. * diff --git a/src/main/java/eu/europa/ec/dgc/issuance/service/EhdCryptoService.java b/src/main/java/eu/europa/ec/dgc/issuance/service/EhdCryptoService.java index 3075740..9750418 100644 --- a/src/main/java/eu/europa/ec/dgc/issuance/service/EhdCryptoService.java +++ b/src/main/java/eu/europa/ec/dgc/issuance/service/EhdCryptoService.java @@ -21,12 +21,15 @@ package eu.europa.ec.dgc.issuance.service; import COSE.AlgorithmID; -import COSE.CoseException; -import COSE.HeaderKeys; -import COSE.OneKey; import com.upokecenter.cbor.CBORObject; import ehn.techiop.hcert.kotlin.chain.CryptoService; import ehn.techiop.hcert.kotlin.chain.VerificationResult; +import ehn.techiop.hcert.kotlin.crypto.CertificateAdapter; +import ehn.techiop.hcert.kotlin.crypto.CoseHeaderKeys; +import ehn.techiop.hcert.kotlin.crypto.JvmPrivKey; +import ehn.techiop.hcert.kotlin.crypto.JvmPubKey; +import ehn.techiop.hcert.kotlin.crypto.PrivKey; +import ehn.techiop.hcert.kotlin.crypto.PubKey; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateCrtKey; @@ -39,7 +42,7 @@ public class EhdCryptoService implements CryptoService { private final X509Certificate cert; private final byte[] kid; - private final List> headers; + private final List> headers; private final PrivateKey privateKey; /** @@ -52,48 +55,37 @@ public EhdCryptoService(CertificateService certificateService) { this.privateKey = certificateService.getPrivateKey(); kid = certificateService.getKid(); if (this.privateKey instanceof RSAPrivateCrtKey) { - headers = Arrays.asList(new Pair<>(HeaderKeys.Algorithm, AlgorithmID.RSA_PSS_256.AsCBOR()), - new Pair<>(HeaderKeys.KID, CBORObject.FromObject(kid))); + headers = Arrays.asList(new Pair<>(CoseHeaderKeys.ALGORITHM, AlgorithmID.RSA_PSS_256.AsCBOR()), + new Pair<>(CoseHeaderKeys.KID, CBORObject.FromObject(kid))); } else { - headers = Arrays.asList(new Pair<>(HeaderKeys.Algorithm, AlgorithmID.ECDSA_256.AsCBOR()), - new Pair<>(HeaderKeys.KID, CBORObject.FromObject(kid))); + headers = Arrays.asList(new Pair<>(CoseHeaderKeys.ALGORITHM, AlgorithmID.ECDSA_256.AsCBOR()), + new Pair<>(CoseHeaderKeys.KID, CBORObject.FromObject(kid))); } } + @Override - public List> getCborHeaders() { + public List> getCborHeaders() { return headers; } @Override - public COSE.OneKey getCborSigningKey() { - try { - return new OneKey(cert.getPublicKey(), privateKey); - } catch (CoseException e) { - throw new RuntimeException(e); - } + public PrivKey getCborSigningKey() { + return new JvmPrivKey(privateKey); } @Override - public COSE.OneKey getCborVerificationKey(byte[] bytes, VerificationResult verificationResult) { + public PubKey getCborVerificationKey(byte[] bytes, VerificationResult verificationResult) { if (Arrays.compare(this.kid, kid) == 0) { - try { - return new OneKey(cert.getPublicKey(), privateKey); - } catch (CoseException e) { - throw new RuntimeException(e); - } + return new JvmPubKey(cert.getPublicKey()); } else { throw new IllegalArgumentException("unknown kid"); } } @Override - public X509Certificate getCertificate() { - if (Arrays.compare(this.kid, kid) == 0) { - return cert; - } else { - throw new IllegalArgumentException("unknown kid"); - } + public CertificateAdapter getCertificate() { + return new CertificateAdapter(cert); } @Override diff --git a/src/main/java/eu/europa/ec/dgc/issuance/service/ExpirationService.java b/src/main/java/eu/europa/ec/dgc/issuance/service/ExpirationService.java index 72cb468..f646af5 100644 --- a/src/main/java/eu/europa/ec/dgc/issuance/service/ExpirationService.java +++ b/src/main/java/eu/europa/ec/dgc/issuance/service/ExpirationService.java @@ -1,14 +1,12 @@ package eu.europa.ec.dgc.issuance.service; -import ehn.techiop.hcert.data.Eudgc; +import ehn.techiop.hcert.kotlin.data.GreenCertificate; import eu.europa.ec.dgc.issuance.config.IssuanceConfigProperties; import eu.europa.ec.dgc.issuance.entity.GreenCertificateType; import java.time.Duration; import java.time.Instant; -import java.time.LocalDate; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; -import java.util.Date; import lombok.Data; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -55,27 +53,27 @@ public Duration expirationForType(GreenCertificateType greenCertificateType) { * @param eudgc json data of dgc * @return the times */ - public CwtTimeFields calculateCwtExpiration(Eudgc eudgc) { + public CwtTimeFields calculateCwtExpiration(GreenCertificate eudgc) { CwtTimeFields result = new CwtTimeFields(); GreenCertificateType greenCertificateType; long expirationTime; long issueTime = Instant.now().getEpochSecond(); long expirationStartTime = issueTime; - if (eudgc.getT() != null && !eudgc.getT().isEmpty()) { + if (eudgc.getTests() != null && !eudgc.getTests().isEmpty()) { greenCertificateType = GreenCertificateType.Test; - expirationStartTime = extractTimesSec(eudgc.getT().get(0).getSc(),expirationStartTime); + expirationStartTime = extractTimesSec(eudgc.getTests().get(0).getDateTimeSample(),expirationStartTime); expirationTime = expirationStartTime + expirationForType(greenCertificateType).get(ChronoUnit.SECONDS); - } else if (eudgc.getR() != null && !eudgc.getR().isEmpty()) { + } else if (eudgc.getRecoveryStatements() != null && !eudgc.getRecoveryStatements().isEmpty()) { greenCertificateType = GreenCertificateType.Recovery; expirationTime = expirationStartTime + expirationForType(greenCertificateType).get(ChronoUnit.SECONDS); - expirationTime = extractTimesSec(eudgc.getR().get(0).getDu(),expirationTime); - } else if (eudgc.getV() != null && !eudgc.getV().isEmpty()) { + expirationTime = extractTimesSec(eudgc.getRecoveryStatements().get(0).getCertificateValidUntil(), + expirationTime); + } else if (eudgc.getVaccinations() != null && !eudgc.getVaccinations().isEmpty()) { greenCertificateType = GreenCertificateType.Vaccination; - expirationStartTime = extractTimesSec(eudgc.getV().get(0).getDt(),expirationStartTime); + expirationStartTime = extractTimesSec(eudgc.getVaccinations().get(0).getDate(),expirationStartTime); expirationTime = expirationStartTime + expirationForType(greenCertificateType).get(ChronoUnit.SECONDS); } else { - // fallback greenCertificateType = GreenCertificateType.Vaccination; expirationTime = expirationStartTime + expirationForType(greenCertificateType).get(ChronoUnit.SECONDS); } @@ -84,20 +82,20 @@ public CwtTimeFields calculateCwtExpiration(Eudgc eudgc) { return result; } - private long extractTimesSec(Date date, long defaultTimeSec) { + private long extractTimesSec(kotlinx.datetime.Instant date, long defaultTimeSec) { long timeSec; if (date != null) { - timeSec = date.toInstant().getEpochSecond(); + timeSec = date.getEpochSeconds(); } else { timeSec = defaultTimeSec; } return timeSec; } - private long extractTimesSec(String dateAsString, long defaultTimeSec) { + private long extractTimesSec(kotlinx.datetime.LocalDate localDate, long defaultTimeSec) { long timeSec; - if (dateAsString != null && dateAsString.length() > 0) { - timeSec = LocalDate.parse(dateAsString).atStartOfDay().toInstant(ZoneOffset.UTC).getEpochSecond(); + if (localDate != null) { + timeSec = localDate.getValue$kotlinx_datetime().atStartOfDay().toEpochSecond(ZoneOffset.UTC); } else { timeSec = defaultTimeSec; } diff --git a/src/test/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciControllerTest.java b/src/test/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciControllerTest.java index ed89974..fbca81b 100644 --- a/src/test/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciControllerTest.java +++ b/src/test/java/eu/europa/ec/dgc/issuance/restapi/controller/DgciControllerTest.java @@ -1,7 +1,5 @@ package eu.europa.ec.dgc.issuance.restapi.controller; -import com.fasterxml.jackson.databind.ObjectMapper; -import ehn.techiop.hcert.data.Eudgc; import eu.europa.ec.dgc.issuance.restapi.dto.EgdcCodeData; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -17,12 +15,10 @@ public class DgciControllerTest { @Test void checkBackendIssuing() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - Eudgc edgc = mapper.readValue("{\"ver\":\"1.0.0\",\"nam\":{\"fn\":\"Garcia\",\"fnt\":\"GARCIA\"," + + String edgc = "{\"ver\":\"1.0.0\",\"nam\":{\"fn\":\"Garcia\",\"fnt\":\"GARCIA\"," + "\"gn\":\"Francisco\",\"gnt\":\"FRANCISCO\"},\"dob\":\"1991-01-01\",\"v\":[{\"tg\":\"840539006\"," + "\"vp\":\"1119305005\",\"mp\":\"EU/1/20/1507\",\"ma\":\"ORG-100001699\",\"dn\":1,\"sd\":2,\"dt\":" + - "\"2021-05-14\",\"co\":\"CY\",\"is\":\"Neha\",\"ci\":\"dgci:V1:CY:HIP4OKCIS8CXKQMJSSTOJXAMP:03\"}]}" - ,Eudgc.class); + "\"2021-05-14\",\"co\":\"CY\",\"is\":\"Neha\",\"ci\":\"dgci:V1:CY:HIP4OKCIS8CXKQMJSSTOJXAMP:03\"}]}"; ResponseEntity responseEntity = dgciController.createEdgc(edgc); assertNotNull(responseEntity.getBody()); } diff --git a/src/test/java/eu/europa/ec/dgc/issuance/service/DGCGenTest.java b/src/test/java/eu/europa/ec/dgc/issuance/service/DGCGenTest.java index 432cb23..9eb5e69 100644 --- a/src/test/java/eu/europa/ec/dgc/issuance/service/DGCGenTest.java +++ b/src/test/java/eu/europa/ec/dgc/issuance/service/DGCGenTest.java @@ -2,7 +2,8 @@ import com.upokecenter.cbor.CBORObject; import com.upokecenter.cbor.CBORType; -import ehn.techiop.hcert.kotlin.chain.common.Base45Encoder; +import ehn.techiop.hcert.kotlin.chain.Base45Service; +import ehn.techiop.hcert.kotlin.chain.impl.DefaultBase45Service; import eu.europa.ec.dgc.issuance.entity.GreenCertificateType; import eu.europa.ec.dgc.issuance.restapi.dto.DgciIdentifier; import eu.europa.ec.dgc.issuance.restapi.dto.DgciInit; @@ -114,8 +115,8 @@ private String coseToQRCode(byte[] cose) throws IOException { ByteArrayInputStream bis = new ByteArrayInputStream(cose); DeflaterInputStream compessedInput = new DeflaterInputStream(bis, new Deflater(9)); byte[] coseCompressed = compessedInput.readAllBytes(); - Base45Encoder base45Encoder = new Base45Encoder(); - String coded = base45Encoder.encode(coseCompressed); + Base45Service base45Service = new DefaultBase45Service(); + String coded = base45Service.encode(coseCompressed); return "HC1:"+coded; } } diff --git a/src/test/java/eu/europa/ec/dgc/issuance/service/DgciServiceTest.java b/src/test/java/eu/europa/ec/dgc/issuance/service/DgciServiceTest.java index cedd7d5..4d0bd6f 100644 --- a/src/test/java/eu/europa/ec/dgc/issuance/service/DgciServiceTest.java +++ b/src/test/java/eu/europa/ec/dgc/issuance/service/DgciServiceTest.java @@ -4,7 +4,6 @@ import COSE.CoseException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import ehn.techiop.hcert.data.Eudgc; import ehn.techiop.hcert.kotlin.chain.SampleData; import eu.europa.ec.dgc.issuance.config.IssuanceConfigProperties; import eu.europa.ec.dgc.issuance.entity.DgciEntity; @@ -99,11 +98,9 @@ void testDGCISign() throws Exception { @Test void testCreateEdgcBackend() throws Exception { String vacDataJson = SampleData.Companion.getVaccination(); - ObjectMapper objectMapper = new ObjectMapper(); - Eudgc eudgc = objectMapper.readValue(vacDataJson,Eudgc.class); - EgdcCodeData egdcCodeData = dgciService.createEdgc(eudgc); + EgdcCodeData egdcCodeData = dgciService.createEdgc(vacDataJson); assertNotNull(egdcCodeData); - assertNotNull(egdcCodeData.getQrcCode()); + assertNotNull(egdcCodeData.getQrCode()); Optional dgciEnitiyOpt = dgciRepository.findByDgci(egdcCodeData.getDgci()); assertTrue(dgciEnitiyOpt.isPresent()); assertEquals(GreenCertificateType.Vaccination,dgciEnitiyOpt.get().getGreenCertificateType()); @@ -112,7 +109,7 @@ void testCreateEdgcBackend() throws Exception { assertNotNull(dgciEnitiyOpt.get().getHashedTan()); assertNotNull(dgciEnitiyOpt.get().getExpiresAt()); - EgcDecodeResult decodeResult = edgcValidator.decodeEdgc(egdcCodeData.getQrcCode()); + EgcDecodeResult decodeResult = edgcValidator.decodeEdgc(egdcCodeData.getQrCode()); assertTrue(decodeResult.isValidated()); assertNull(decodeResult.getErrorMessage()); JsonNode cborJson = decodeResult.getCborJson(); @@ -128,11 +125,9 @@ void testCreateEdgcBackend() throws Exception { @Test void testWalletClaim() throws Exception { String vacDataJson = SampleData.Companion.getVaccination(); - ObjectMapper objectMapper = new ObjectMapper(); - Eudgc eudgc = objectMapper.readValue(vacDataJson,Eudgc.class); - EgdcCodeData egdcCodeData = dgciService.createEdgc(eudgc); + EgdcCodeData egdcCodeData = dgciService.createEdgc(vacDataJson); assertNotNull(egdcCodeData); - assertNotNull(egdcCodeData.getQrcCode()); + assertNotNull(egdcCodeData.getQrCode()); Optional dgciEnitiyOpt = dgciRepository.findByDgci(egdcCodeData.getDgci()); assertTrue(dgciEnitiyOpt.isPresent()); assertFalse(dgciEnitiyOpt.get().isClaimed()); @@ -140,7 +135,7 @@ void testWalletClaim() throws Exception { String certHash = dgciEnitiyOpt.get().getCertHash(); assertEquals(GreenCertificateType.Vaccination,dgciEnitiyOpt.get().getGreenCertificateType()); - EgcDecodeResult decodeResult = edgcValidator.decodeEdgc(egdcCodeData.getQrcCode()); + EgcDecodeResult decodeResult = edgcValidator.decodeEdgc(egdcCodeData.getQrCode()); assertTrue(decodeResult.isValidated()); assertNull(decodeResult.getErrorMessage()); @@ -166,6 +161,7 @@ void testWalletClaim() throws Exception { assertNotNull(didDocument); assertNotNull(didDocument.getAuthentication()); assertFalse(didDocument.getAuthentication().isEmpty()); + ObjectMapper objectMapper = new ObjectMapper(); System.out.println(objectMapper.writeValueAsString(didDocument.getAuthentication().get(0).getPublicKeyJsw())); } @@ -179,11 +175,9 @@ private String sha256(String toHash) throws NoSuchAlgorithmException { @Test void testWalletClaimEC() throws Exception { String vacDataJson = SampleData.Companion.getVaccination(); - ObjectMapper objectMapper = new ObjectMapper(); - Eudgc eudgc = objectMapper.readValue(vacDataJson,Eudgc.class); - EgdcCodeData egdcCodeData = dgciService.createEdgc(eudgc); + EgdcCodeData egdcCodeData = dgciService.createEdgc(vacDataJson); assertNotNull(egdcCodeData); - assertNotNull(egdcCodeData.getQrcCode()); + assertNotNull(egdcCodeData.getQrCode()); Optional dgciEnitiyOpt = dgciRepository.findByDgci(egdcCodeData.getDgci()); assertTrue(dgciEnitiyOpt.isPresent()); assertFalse(dgciEnitiyOpt.get().isClaimed()); @@ -191,7 +185,7 @@ void testWalletClaimEC() throws Exception { String certHash = dgciEnitiyOpt.get().getCertHash(); assertEquals(GreenCertificateType.Vaccination,dgciEnitiyOpt.get().getGreenCertificateType()); - EgcDecodeResult decodeResult = edgcValidator.decodeEdgc(egdcCodeData.getQrcCode()); + EgcDecodeResult decodeResult = edgcValidator.decodeEdgc(egdcCodeData.getQrCode()); assertTrue(decodeResult.isValidated()); assertNull(decodeResult.getErrorMessage()); @@ -209,6 +203,7 @@ void testWalletClaimEC() throws Exception { assertNotNull(didDocument); assertNotNull(didDocument.getAuthentication()); assertFalse(didDocument.getAuthentication().isEmpty()); + ObjectMapper objectMapper = new ObjectMapper(); System.out.println(objectMapper.writeValueAsString(didDocument.getAuthentication().get(0).getPublicKeyJsw())); } diff --git a/src/test/java/eu/europa/ec/dgc/issuance/service/ExpirationServiceTest.java b/src/test/java/eu/europa/ec/dgc/issuance/service/ExpirationServiceTest.java index 9c09809..5420220 100644 --- a/src/test/java/eu/europa/ec/dgc/issuance/service/ExpirationServiceTest.java +++ b/src/test/java/eu/europa/ec/dgc/issuance/service/ExpirationServiceTest.java @@ -1,10 +1,11 @@ package eu.europa.ec.dgc.issuance.service; import com.fasterxml.jackson.databind.ObjectMapper; -import ehn.techiop.hcert.data.Eudgc; import ehn.techiop.hcert.kotlin.chain.SampleData; +import ehn.techiop.hcert.kotlin.data.GreenCertificate; import java.time.LocalDateTime; import java.time.ZoneOffset; +import kotlinx.serialization.json.Json; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -20,21 +21,21 @@ class ExpirationServiceTest { @Test void testExpriationCalculation() throws Exception { String vacDataJson = SampleData.Companion.getVaccination(); - Eudgc eudgc = testCalculation("vactination",vacDataJson); - System.out.println(eudgc.getV().get(0).getDt()); + GreenCertificate eudgc = testCalculation("vactination",vacDataJson); + System.out.println(eudgc.getVaccinations().get(0).getDate()); String recoveryDataJson = SampleData.Companion.getRecovery(); eudgc = testCalculation("recovery",recoveryDataJson); - System.out.println(eudgc.getR().get(0).getDu()); + System.out.println(eudgc.getRecoveryStatements().get(0).getCertificateValidUntil()); String testDataJson = SampleData.Companion.getTestNaa(); eudgc = testCalculation("test",testDataJson); - System.out.println(eudgc.getT().get(0).getSc().toInstant().atOffset(ZoneOffset.UTC)); + System.out.println(eudgc.getTests().get(0).getDateTimeSample()); assertNotNull(eudgc); } - private Eudgc testCalculation(String description, String vacDataJson) throws com.fasterxml.jackson.core.JsonProcessingException { + private GreenCertificate testCalculation(String description, String vacDataJson) throws com.fasterxml.jackson.core.JsonProcessingException { System.out.println("testing: "+description); - Eudgc eudgc = objectMapper.readValue(vacDataJson,Eudgc.class); + GreenCertificate eudgc = Json.Default.decodeFromString(GreenCertificate.Companion.serializer(), vacDataJson); ExpirationService.CwtTimeFields expTime = expirationService.calculateCwtExpiration(eudgc); LocalDateTime issuedAt = LocalDateTime.ofEpochSecond(expTime.getIssuedAt(), 0, ZoneOffset.UTC); assertNotNull(issuedAt);