From 9ff0dde49e818348df5ba9c7bca91d165227234b Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 1 Feb 2022 14:16:00 +0100 Subject: - smplified api for level 2 signature --- src/main/java/org/uic/barcode/Encoder.java | 52 ++++ .../test/DynamicFrameV2SignatureInsert2Test.java | 270 +++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java index 51e86a2..9afddce 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; +import java.util.zip.DataFormatException; import org.uic.barcode.dynamicContent.api.IUicDynamicContent; import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; @@ -163,6 +164,57 @@ public class Encoder { } + /** + * Instantiates a new encoder for a level 2 encoding with tan encoded dynamic frame containing the level 1 data and signature. + * + * @param level1Data the level 1 data (binary as signed) + * @param signatureLevel1 the signature of the level 1 data + * @param version the version of the bar code + * @throws IOException Signals that an I/O exception has occurred. + * @throws EncodingFormatException the encoding format exception + * @throws DataFormatException + */ + public Encoder(byte[] encoded, int version) throws IOException, EncodingFormatException, DataFormatException { + + Decoder decoder = new Decoder(encoded); + + if (decoder.getDynamicFrame() == null) { + throw new EncodingFormatException("No dynamic frame included"); + } + + + dynamicFrame = decoder.getDynamicFrame(); + byte[] level1DataBin = decoder.getEncodedLevel1Data(); + byte[] signatureLevel1 = decoder.getLevel1Signature(); + + if (version == 1) { + + dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1); + + ILevel1Data l1 = DynamicFrameCoderV1.decodeLevel1(level1DataBin); + + dynamicFrame.getLevel2Data().setLevel1Data(l1); + + dynamicFrame.getLevel2Data().setLevel1Signature(signatureLevel1); + + } else if (version == 2) { + + dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2); + + ILevel1Data l1 = DynamicFrameCoderV2.decodeLevel1(level1DataBin); + + dynamicFrame.getLevel2Data().setLevel1Data(l1); + + dynamicFrame.getLevel2Data().setLevel1Signature(signatureLevel1); + + } else { + throw new EncodingFormatException("Version of the dynamic header not supported"); + } + + + } + + /** * Signing level 2 of a dynamic bar code diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java new file mode 100644 index 0000000..a7d5098 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java @@ -0,0 +1,270 @@ +package org.uic.barcode.test; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.Security; +import java.security.SignatureException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.TimeZone; +import java.util.zip.DataFormatException; + +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.junit.Before; +import org.junit.Test; +import org.uic.barcode.Decoder; +import org.uic.barcode.Encoder; +import org.uic.barcode.dynamicFrame.Constants; +import org.uic.barcode.test.utils.DynamicTestContent; +import org.uic.barcode.test.utils.SimpleUICTestTicket; +import org.uic.barcode.ticket.EncodingFormatException; +import org.uic.barcode.ticket.api.spec.IUicRailTicket; + +public class DynamicFrameV2SignatureInsert2Test { + + public String signatureAlgorithmOID = null; + public String elipticCurve = null; + public String keyPairAlgorithmOID = null; + + public KeyPair keyPairLevel1 = null; + public KeyPair keyPairLevel2 = null; + + public byte[] passIdHash = "PassId".getBytes(); + public byte[] phoneIdHash = "myPhone".getBytes(); + + public IUicRailTicket testFCBticket = null; + + ZonedDateTime originalTimeStamp = ZonedDateTime.now(ZoneId.of("UTC")); + + @Before public void initialize() { + + signatureAlgorithmOID = Constants.ECDSA_SHA256; + keyPairAlgorithmOID = Constants.KG_EC_256; + elipticCurve = "secp256k1"; + + testFCBticket = SimpleUICTestTicket.getUicTestTicket(); + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPairLevel1 = generateECKeys(keyPairAlgorithmOID, elipticCurve); + keyPairLevel2 = generateECKeys(keyPairAlgorithmOID, elipticCurve); + } catch (Exception e) { + assert(false); + } + + + assert(keyPairLevel1 != null); + assert(keyPairLevel2 != null); + + } + + + @Test public void testDynamicHeaderBarcodeDecoding() { + + //--------------------------------------------------------------------------- + //create barcode data + IUicRailTicket ticket = testFCBticket; + + Encoder enc = null; + try { + enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 2, 3); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + assert(enc != null); + + //complete level 1 data + enc.setLevel1Algs(signatureAlgorithmOID, keyPairAlgorithmOID); + enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID,keyPairLevel2.getPublic()); + enc.getDynamicFrame().getLevel2Data().getLevel1Data().setEndOfBarcodeValidity(getUtcDate("2021.03.04-12:30")); + enc.getDynamicFrame().getLevel2Data().getLevel1Data().setValidityDuration(100L); + + + //sign level 1 data + try { + enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + // encode + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + assert(encoded != null); + + + + //---------------------------------------------------------------------------------------------- + //decode and check level 1 + Decoder dec = null; + try { + dec = new Decoder(encoded); + } catch (IOException e) { + assert(false); + } catch (EncodingFormatException e) { + assert(false); + } catch (DataFormatException e) { + assert(false); + } + assert(dec != null); + + String keyId = null; + try { + keyId = dec.getLevel1KeyId(); + } catch (EncodingFormatException e3) { + assert(false); + } + assert(keyId != null); + + + + int signatureCheck = 0; + try { + signatureCheck = dec.validateLevel1(keyPairLevel1.getPublic(),null); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + + + + + //-------------------------------------------------------------------------------------------------- + // get encoder with dynamic frame to continue + try { + enc = new Encoder(encoded, 2); + } catch (Exception e1) { + assert(false); + } + + + //set dynamic content + try { + enc.setDynamicData(DynamicTestContent.createDynamicTestContent()); + } catch (EncodingFormatException e1) { + assert(false); + } + //----------- + // sign level 2 + try { + enc.signLevel2(keyPairLevel2.getPrivate()); + } catch (Exception e) { + assert(false); + } + + //------------------------ + //encode complete bar code + encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + assert(encoded != null); + + //---------------------------------------------------------------------------------------------------- + //decode full bar code + + dec = null; + try { + dec = new Decoder(encoded); + } catch (IOException e) { + assert(false); + } catch (EncodingFormatException e) { + assert(false); + } catch (DataFormatException e) { + assert(false); + } + assert(dec != null); + + //--------------------------------------------------------------------------------------------------- + //check level 1 signature + + signatureCheck = 0; + try { + signatureCheck = dec.validateLevel1(keyPairLevel1.getPublic(),null); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + //-------------------------------------------------------------------------------------------------------- + //check level 2 signature + + signatureCheck = 0; + try { + signatureCheck = dec.validateLevel2(); + } catch (Exception e) { + assert(false); + } + assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK); + + + } + + public KeyPair generateECDSAKeys(String keyAlgorithmName, String paramName) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + + ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(paramName); + KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC"); + g.initialize(ecSpec, new SecureRandom()); + return g.generateKeyPair(); + + } + + public KeyPair generateECKeys(String keyAlgorithmOid, String curve) throws Exception{ + + String keyAlgorithmName = "ECDSA"; + ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curve); + KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC"); + g.initialize(ecSpec, new SecureRandom()); + return g.generateKeyPair(); + + } + + public Date getUtcDate(String s) { + + TimeZone local = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + Date date = null; + try { + date = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).parse(s); + } catch (ParseException e1) { + assert(false); + } + TimeZone.setDefault(local); + + return date; + + } + + public String formatUTC(Date date) { + + TimeZone local = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + String dateS = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).format(date); + TimeZone.setDefault(local); + return dateS; + + } + + +} -- cgit v1.2.3