summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCGantert345 <57003061+CGantert345@users.noreply.github.com>2022-02-10 14:00:06 +0100
committerGitHub <noreply@github.com>2022-02-10 14:00:06 +0100
commit7fe844da786691bf839f169bcab8e71b5021329e (patch)
treedad727a39dc76d330fe28480e24e8a846c36b760 /src
parentMerge pull request #41 from UnionInternationalCheminsdeFer/1.2.13 (diff)
parentversion number update (diff)
downloadUIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.tar
UIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.tar.gz
UIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.tar.bz2
UIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.tar.lz
UIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.tar.xz
UIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.tar.zst
UIC-barcode-7fe844da786691bf839f169bcab8e71b5021329e.zip
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/uic/barcode/Decoder.java120
-rw-r--r--src/main/java/org/uic/barcode/Encoder.java217
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java80
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java75
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java1
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java30
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java6
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/Decoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/IntCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java4
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java29
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/StringCoder.java2
-rw-r--r--src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java46
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java213
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java129
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/api/SimpleUicDynamicContent.java150
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoCoordinateSystemType.java1
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoUnitType.java1
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLatitudeType.java1
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLongitudeType.java1
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java14
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java14
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/Constants.java5
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java337
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/DynamicFrameCoder.java107
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/IData.java39
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java225
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java202
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java25
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java52
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java499
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java264
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java56
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/package.html9
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/DataType.java)5
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java229
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java221
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java)2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java74
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java)2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java96
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java230
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java235
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java392
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java)2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java25
-rw-r--r--src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java37
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/UperEncodeFieldOrderTest.java2
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/UperEncodeIntegerExtensionTest.java2
-rw-r--r--src/test/java/org/uic/barcode/asn1/test/UperEncodeSequenceOfStringTest.java2
-rw-r--r--src/test/java/org/uic/barcode/test/AsnLevelDynamicContentTest.java112
-rw-r--r--src/test/java/org/uic/barcode/test/BinaryStringTest.java61
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java118
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java10
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java10
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java228
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java8
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java10
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java10
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java8
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java176
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java270
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsertTest.java289
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java212
-rw-r--r--src/test/java/org/uic/barcode/test/TimeStampTest.java36
-rw-r--r--src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java40
-rw-r--r--src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java10
-rw-r--r--src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java24
72 files changed, 5638 insertions, 516 deletions
diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java
index 9f102d3..9f5ea82 100644
--- a/src/main/java/org/uic/barcode/Decoder.java
+++ b/src/main/java/org/uic/barcode/Decoder.java
@@ -8,12 +8,13 @@ import java.security.PublicKey;
import java.security.SignatureException;
import java.util.zip.DataFormatException;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
-import org.uic.barcode.dynamicFrame.Level1DataType;
-import org.uic.barcode.dynamicFrame.Level2DataType;
-import org.uic.barcode.dynamicFrame.SequenceOfDataType;
+import org.uic.barcode.dynamicFrame.api.DynamicFrameCoder;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.ILevel2Data;
import org.uic.barcode.staticFrame.StaticFrame;
import org.uic.barcode.staticFrame.UFLEXDataRecord;
import org.uic.barcode.staticFrame.UTLAYDataRecord;
@@ -33,7 +34,7 @@ public class Decoder {
/** The dynamic frame. */
- private DynamicFrame dynamicFrame = null;
+ private IDynamicFrame dynamicFrame = null;
/** The static frame. */
private StaticFrame staticFrame = null;
@@ -78,10 +79,36 @@ public class Decoder {
* @throws IOException Signals that an I/O exception has occurred.
* @throws EncodingFormatException the encoding format exception
*/
- public int validateLevel1(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException {
- if (!isStaticHeader(data)) {
+ public int validateLevel1(PublicKey key) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException {
+ if (dynamicFrame != null) {
return dynamicFrame.validateLevel1(key) ;
} else {
+ if (staticFrame != null) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } else {
+ return Constants.LEVEL1_VALIDATION_FRAUD;
+ }
+ }
+ }
+
+ /**
+ * Validate level 1.
+ *
+ * @param key the public key
+ * @param signingAlg the signing algorithm OID
+ * @return the return code indicating errors
+ * @throws InvalidKeyException the invalid key exception
+ * @throws NoSuchAlgorithmException the no such algorithm exception
+ * @throws SignatureException the signature exception
+ * @throws IllegalArgumentException the illegal argument exception
+ * @throws UnsupportedOperationException the unsupported operation exception
+ * @throws IOException Signals that an I/O exception has occurred.
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel1(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException {
+ if (dynamicFrame != null) {
+ return dynamicFrame.validateLevel1(key, signingAlg) ;
+ } else {
if (staticFrame.verifyByAlgorithmOid(key,signingAlg)) {
return Constants.LEVEL1_VALIDATION_OK;
} else {
@@ -90,7 +117,6 @@ public class Decoder {
}
}
-
/**
* Validate level 1.
*
@@ -122,8 +148,9 @@ public class Decoder {
* Validate level 2.
*
* @return the return code indicating errors
+ * @throws EncodingFormatException
*/
- public int validateLevel2() {
+ public int validateLevel2() throws EncodingFormatException {
if (!isStaticHeader(data)) {
return dynamicFrame.validateLevel2() ;
} else {
@@ -136,7 +163,7 @@ public class Decoder {
* @param prov - provider of the java security implementation in case a dedicated provider must be used
* @return the return code indicating errors
*/
- public int validateLevel2(Provider prov) {
+ public int validateLevel2(Provider prov) throws EncodingFormatException {
if (!isStaticHeader(data)) {
return dynamicFrame.validateLevel2(prov) ;
} else {
@@ -156,24 +183,22 @@ public class Decoder {
public void decode(byte[] data) throws IOException, EncodingFormatException, DataFormatException {
if (!isStaticHeader(data)) {
-
- dynamicFrame = DynamicFrame.decode(data);
- Level2DataType level2 = dynamicFrame.getLevel2SignedData();
+ dynamicFrame = DynamicFrameCoder.decode(data);
- Level1DataType level1 = level2.getLevel1Data();
+ ILevel2Data level2 = dynamicFrame.getLevel2Data();
- SequenceOfDataType dataList = level1.getData();
+ ILevel1Data level1 = level2.getLevel1Data();
- for (DataType level1Content : dataList) {
+ for (IData level1Content : level1.getData()) {
uicTicketCoder = new UicRailTicketCoder();
if (level1Content.getFormat().equals("FCB1")) {
- uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 1);
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 1);
} else if (level1Content.getFormat().equals("FCB2")) {
- uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 2);
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 2);
} else if (level1Content.getFormat().equals("FCB3")) {
- uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 3);
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 3);
}
}
@@ -227,22 +252,33 @@ public class Decoder {
public TicketLayout getLayout() {
return layout;
}
-
+
/**
* Gets the dynamic header.
*
* @return the dynamic header
*/
- public DynamicFrame getDynamicHeader() {
+ public IDynamicFrame getDynamicFrame() {
return dynamicFrame;
}
/**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic header
+ */
+ public IUicDynamicContent getDynamicContent() {
+ if (dynamicFrame == null) return null;
+
+ return dynamicFrame.getDynamicContent();
+ }
+
+ /**
* Sets the dynamic header.
*
* @param dynamicHeader the new dynamic header
*/
- public void setDynamicHeader(DynamicFrame dynamicHeader) {
+ public void setDynamicHeader(IDynamicFrame dynamicHeader) {
this.dynamicFrame = dynamicHeader;
}
@@ -264,14 +300,46 @@ public class Decoder {
this.staticFrame = staticFrame;
}
- public DataType getLevel2Data() {
- if (!isStaticHeader(data) && dynamicFrame.getLevel2SignedData() != null) {
- return dynamicFrame.getLevel2SignedData().getLevel2Data();
+ public IData getLevel2Data() {
+ if (!isStaticHeader(data) && dynamicFrame.getLevel2Data() != null) {
+ return dynamicFrame.getLevel2Data().getLevel2Data();
}
return null;
}
+ public byte[] getEncodedLevel1Data() throws IOException, EncodingFormatException {
+ if (!isStaticHeader(data)) {
+ return dynamicFrame.getLevel1DataBin();
+ } else if (staticFrame != null) {
+ return staticFrame.getDataForSignature();
+ } else {
+ throw new EncodingFormatException("Unknown Header");
+ }
+ }
+ public byte[] getLevel1Signature() throws IOException, EncodingFormatException {
+
+ if (!isStaticHeader(data)) {
+ return dynamicFrame.getLevel2Data().getLevel1Signature();
+ } else if (staticFrame != null) {
+ return staticFrame.getDataForSignature();
+ } else {
+ throw new EncodingFormatException("Unknown Header");
+ }
+ }
+ public String getLevel1KeyId() throws EncodingFormatException {
+
+ if (dynamicFrame != null
+ && dynamicFrame.getLevel2Data() != null
+ && dynamicFrame.getLevel2Data().getLevel1Data() != null) {
+ return dynamicFrame.getLevel2Data().getLevel1Data().getKeyId().toString();
+ } else if (staticFrame != null) {
+ return staticFrame.getSignatureKey();
+ } else {
+ throw new EncodingFormatException("Unknown Header");
+ }
+
+ }
}
diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java
index f0f8d14..9afddce 100644
--- a/src/main/java/org/uic/barcode/Encoder.java
+++ b/src/main/java/org/uic/barcode/Encoder.java
@@ -4,15 +4,21 @@ 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.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
-import org.uic.barcode.dynamicFrame.Level1DataType;
-import org.uic.barcode.dynamicFrame.Level2DataType;
-import org.uic.barcode.dynamicFrame.SequenceOfDataType;
+import org.uic.barcode.dynamicFrame.api.DynamicFrameCoder;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.api.SimpleDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel2Data;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrameCoderV1;
+import org.uic.barcode.dynamicFrame.v2.DynamicFrameCoderV2;
import org.uic.barcode.staticFrame.StaticFrame;
import org.uic.barcode.staticFrame.UFLEXDataRecord;
import org.uic.barcode.staticFrame.UHEADDataRecord;
@@ -33,7 +39,7 @@ import org.uic.barcode.ticket.api.spec.IUicRailTicket;
public class Encoder {
/** The dynamic frame. */
- private DynamicFrame dynamicFrame = null;
+ private IDynamicFrame dynamicFrame = null;
/** The static frame. */
private StaticFrame staticFrame = null;
@@ -86,18 +92,19 @@ public class Encoder {
} else if (barcodeType == UIC_BARCODE_TYPE_DOSIPAS) {
- dynamicFrame = new DynamicFrame();
- dynamicFrame.setLevel2SignedData(new Level2DataType());
- dynamicFrame.getLevel2SignedData().setLevel1Data(new Level1DataType());
- dynamicFrame.getLevel2SignedData().getLevel1Data().setData(new SequenceOfDataType());
+ dynamicFrame = new SimpleDynamicFrame();
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
+ dynamicFrame.getLevel2Data().setLevel1Data(new SimpleLevel1Data());
if (ticket != null) {
if (version == 1) {
- dynamicFrame.setFormat("U1");
- }
+ dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1);
+ } else if (version == 2) {
+ dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2);
+ }
- DataType ticketData = new DataType();
+ IData ticketData = new SimpleData();
UicRailTicketCoder uicTicketCoder = new UicRailTicketCoder();
if (fcbVersion == 1 || fcbVersion == 13) {
@@ -107,13 +114,106 @@ public class Encoder {
} else if (fcbVersion == 3) {
ticketData.setFormat(Constants.DATA_TYPE_FCB_VERSION_3);
}
- ticketData.setData(new OctetString(uicTicketCoder.encode(ticket, fcbVersion)));
- dynamicFrame.getLevel2SignedData().getLevel1Data().getData().add(ticketData);
+ ticketData.setData(uicTicketCoder.encode(ticket, fcbVersion));
+ dynamicFrame.getLevel2Data().getLevel1Data().addData(ticketData);
}
}
}
+ /**
+ * Instantiates a new encoder for a level 2 encoding.
+ *
+ * @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
+ */
+ public Encoder(byte[] level1DataBin, byte[] signatureLevel1, int version) throws IOException, EncodingFormatException {
+
+
+ dynamicFrame = new SimpleDynamicFrame();
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
+
+ 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");
+ }
+
+
+ }
+
+
+ /**
+ * 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");
+ }
+
+
+ }
+
/**
@@ -150,8 +250,8 @@ public class Encoder {
*/
public void setLevel1Algs(String level1SigningAlg, String level1KeyAlg) {
if (dynamicFrame != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1SigningAlg(level1SigningAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1KeyAlg(level1KeyAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(level1SigningAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1KeyAlg(level1KeyAlg);
}
}
@@ -164,51 +264,62 @@ public class Encoder {
*/
public void setLevel2Algs(String level2SigningAlg, String level2KeyAlg, PublicKey publicKey) {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
- if (dynamicFrame.getLevel2SignedData().getLevel1Data() == null) {
- dynamicFrame.getLevel2SignedData().setLevel1Data(new Level1DataType());
+ if (dynamicFrame.getLevel2Data().getLevel1Data() == null) {
+ dynamicFrame.getLevel2Data().setLevel1Data(new SimpleLevel1Data());
}
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel2SigningAlg(level2SigningAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel2KeyAlg(level2KeyAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel2SigningAlg(level2SigningAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel2KeyAlg(level2KeyAlg);
if (publicKey != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel2publicKey(new OctetString(publicKey.getEncoded()));
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel2publicKey(publicKey.getEncoded());
}
}
}
- public void setLevel2Data(DataType level2data) {
+ public void setDynamicData(IUicDynamicContent content) throws EncodingFormatException {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
- dynamicFrame.getLevel2SignedData().setLevel2Data(level2data);
+ dynamicFrame.addDynamicContent(content);
+ }
+ }
+
+ public void setLevel2Data(IData level2data) {
+ if (dynamicFrame != null) {
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
+ }
+ dynamicFrame.getLevel2Data().setLevel2Data(level2data);
}
}
public void setDynamicContentDataUIC1(UicDynamicContentDataFDC1 dcd) {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
- dynamicFrame.getLevel2SignedData().setLevel2Data(dcd.getDataType());
+ dynamicFrame.getLevel2Data().setLevel2Data(dcd.getApiDataType());
}
}
- public DataType getLevel2Data() {
- if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) {
- return dynamicFrame.getLevel2SignedData().getLevel2Data();
+ public IData getLevel2Data() {
+ if (dynamicFrame != null && dynamicFrame.getLevel2Data() != null) {
+ return dynamicFrame.getLevel2Data().getLevel2Data();
}
return null;
}
- public UicDynamicContentDataFDC1 getDynamicContentDataUIC1() {
- if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) {
- return dynamicFrame.getDynamicDataFDC1();
+
+ public IUicDynamicContent getDynamicContent() {
+ if (dynamicFrame != null && dynamicFrame.getLevel2Data() != null) {
+ return dynamicFrame.getDynamicContent();
}
return null;
}
+
/**
@@ -222,10 +333,10 @@ public class Encoder {
*/
public void signLevel1(String securityProvider,PrivateKey key,String signingAlg, String keyId) throws Exception {
if (dynamicFrame != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setSecurityProvider(securityProvider);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1SigningAlg(signingAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setKeyId(Long.parseLong(keyId));
- dynamicFrame.getLevel2SignedData().signLevel1(key);
+ dynamicFrame.getLevel2Data().getLevel1Data().setSecurityProvider(securityProvider);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(signingAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setKeyId(Long.parseLong(keyId));
+ dynamicFrame.signLevel1(key);
} else if (staticFrame != null) {
staticFrame.setSignatureKey(keyId);
staticFrame.setSecurityProvider(securityProvider);
@@ -248,10 +359,10 @@ public class Encoder {
*/
public void signLevel1(String securityProvider,PrivateKey key,String signingAlg, String keyId, Provider prov) throws Exception {
if (dynamicFrame != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setSecurityProvider(securityProvider);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1SigningAlg(signingAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setKeyId(Long.parseLong(keyId));
- dynamicFrame.getLevel2SignedData().signLevel1(key, prov);
+ dynamicFrame.getLevel2Data().getLevel1Data().setSecurityProvider(securityProvider);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(signingAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setKeyId(Long.parseLong(keyId));
+ dynamicFrame.signLevel1(key,prov);
} else if (staticFrame != null) {
staticFrame.setSignatureKey(keyId);
staticFrame.setSecurityProvider(securityProvider);
@@ -281,7 +392,7 @@ public class Encoder {
*
* @return the dynamic frame
*/
- public DynamicFrame getDynamicFrame() {
+ public IDynamicFrame getDynamicFrame() {
return dynamicFrame;
}
@@ -307,7 +418,7 @@ public class Encoder {
*/
public byte[] encode() throws IOException, Exception {
if (dynamicFrame != null) {
- return dynamicFrame.encode();
+ return DynamicFrameCoder.encode(dynamicFrame);
} else if (staticFrame != null) {
return staticFrame.encode();
}
@@ -315,7 +426,15 @@ public class Encoder {
}
-
+ public byte[] getEncodedLevel1Data() throws IOException, EncodingFormatException {
+ if (dynamicFrame != null) {
+ return DynamicFrameCoder.encodeLevel1(dynamicFrame);
+ } else if (staticFrame != null) {
+ return staticFrame.getDataForSignature();
+ } else {
+ throw new EncodingFormatException("Unknown Header");
+ }
+ }
diff --git a/src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java b/src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java
new file mode 100644
index 0000000..0d5d1da
--- /dev/null
+++ b/src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java
@@ -0,0 +1,80 @@
+package org.uic.barcode.asn1.uper;
+
+public class AsnExtractor {
+
+ private String path = null;
+
+ private boolean extractionStarted = false;
+ private boolean extractionCompleted = false;
+
+ private BitBuffer bitBuffer = null;
+ private int startBit = 0;
+ private int endBit = 0;
+
+ AsnExtractor(String path, BitBuffer bitBuffer) {
+ this.path = path;
+ this.bitBuffer = bitBuffer;
+ }
+
+ public byte[] getResult() {
+
+ if (!extractionCompleted) {
+ return null;
+ }
+
+ if (!(endBit > startBit)) {
+ return null;
+ }
+
+ String bitString = bitBuffer.toBooleanString(startBit, endBit - startBit);
+
+ while (bitString.length() % 8 != 0) {
+ bitString = bitString + "0";
+ }
+
+ return AsnUtils.fromBooleanString(bitString);
+
+ }
+
+
+
+ public boolean found(String className) {
+
+ if (extractionStarted || extractionCompleted) return false;
+
+ if (path != null && path.length() > 0 && className != null & className.length() > 0) {
+ if (className.endsWith(path)){
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void startExtraction(int position) {
+
+ if (path == null || path.length() == 0 || bitBuffer == null) {
+ return;
+ }
+
+ if (!extractionCompleted && !extractionStarted) {
+ extractionStarted = true;
+ startBit = position;
+ }
+ }
+
+ public void endExtraction(int position) {
+ if (extractionStarted) {
+ extractionCompleted = true;
+ endBit = position;
+ }
+
+ }
+
+ public boolean isStarted() {
+ return extractionStarted;
+ }
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java
new file mode 100644
index 0000000..414f181
--- /dev/null
+++ b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java
@@ -0,0 +1,75 @@
+package org.uic.barcode.asn1.uper;
+
+import java.math.BigInteger;
+
+public class AsnUtils {
+
+
+ private static byte[] mask = new byte[] {
+ (byte) 0b1000_0000,
+ 0b0100_0000,
+ 0b0010_0000,
+ 0b0001_0000,
+ 0b0000_1000,
+ 0b0000_0100,
+ 0b0000_0010,
+ 0b0000_0001,
+ };
+
+
+ public static byte[] fromBooleanString(final String s) {
+
+ char[] ascii = s.toCharArray();
+ if (ascii == null || ascii.length == 0) {
+ return null;
+ }
+ // get length/8 times bytes with 3 bit shifts to the right of the length
+ final byte[] l_raw = new byte[ascii.length >> 3];
+ /*
+ * We decr index jj by 8 as we go along to not recompute indices using multiplication every time inside the
+ * loop.
+ */
+ for (int ii = 0, jj = 0; ii < l_raw.length; ii++, jj += 8) {
+ for (int bits = 0; bits < mask.length; ++bits) {
+ if (ascii[jj + bits] == '1') {
+ l_raw[ii] |= mask[bits];
+ }
+ }
+ }
+ return l_raw;
+ }
+
+ public static String toBooleanString(byte[] bytes) {
+ StringBuilder sb = new StringBuilder(bytes.length);
+ for (int i = 0; i < bytes.length*8;i++) {
+ sb.append(AsnUtils.get(bytes,i) ? "1" : "0");
+ }
+ return sb.toString();
+ }
+
+ public static boolean get(byte[] bytes, int index) {
+
+ if (index < 0) {
+ throw new IndexOutOfBoundsException("Index " + index + " is less than 0");
+ } else if (index >= bytes.length * 8) {
+ throw new IndexOutOfBoundsException("Index " + index + " violates the limit " + bytes.length*8);
+ }
+ boolean result = (bytes[index / 8] & mask[index % 8]) != 0;
+ return result;
+ }
+
+ public static byte[] shiftBytesToLeft(byte[] bytes, int shift) {
+
+ // create from array
+ BigInteger bigInt = new BigInteger(bytes);
+
+ // shift
+ BigInteger shiftInt = bigInt.shiftLeft(shift);
+
+ // back to array
+ return shiftInt.toByteArray();
+
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java b/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java
index bba0de7..21d0e03 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java
@@ -19,6 +19,7 @@ public interface BitBuffer {
BitBuffer flip();
String toBooleanString(int startIndex, int length);
String toBooleanStringFromPosition(int startIndex);
+ byte[] fromBooleanString(String s);
byte[] array();
BitBuffer putByte(byte element);
byte getByte();
diff --git a/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java b/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java
index 19aac9b..6f435c4 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java
@@ -97,7 +97,7 @@ class BitStringCoder implements Decoder, Encoder {
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),
extraAnnotations);
if (!Asn1VarSizeBitstring.class.isAssignableFrom(classOfT)) {
diff --git a/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java b/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java
index 3bd7a38..892f851 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java
@@ -22,7 +22,7 @@ class BooleanCoder implements Decoder, Encoder {
@SuppressWarnings("unchecked")
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
Boolean result = new Boolean(bitbuffer.get());
UperEncoder.logger.debug(String.format("BOOL: decoded as %s",result));
return (T) result;
diff --git a/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java b/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java
index 3ed3eed..e409005 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java
@@ -3,7 +3,7 @@ package org.uic.barcode.asn1.uper;
public class ByteBitBuffer implements BitBuffer {
-
+
byte[] bytes;
byte[] mask = new byte[] {
(byte) 0b1000_0000,
@@ -45,7 +45,8 @@ public class ByteBitBuffer implements BitBuffer {
bytes = newbytes;
}
- @Override public BitBuffer put(int index, boolean element) {
+ @Override
+ public BitBuffer put(int index, boolean element) {
if (bytes.length <= index / 8) {
if (isFinite) { throw new IndexOutOfBoundsException(); }
else { grow(); }
@@ -58,21 +59,24 @@ public class ByteBitBuffer implements BitBuffer {
return this;
}
- @Override public BitBuffer put(boolean element) {
+ @Override
+ public BitBuffer put(boolean element) {
put(position, element);
position++;
limit = limit < position ? position : limit; // TODO: should it be here?
return this;
}
- @Override public BitBuffer putByte(byte element) {
+ @Override
+ public BitBuffer putByte(byte element) {
for (int i = 0; i < 8; i++) {
put((element & mask[i]) != 0);
}
return this;
}
- @Override public BitBuffer putByteArray(int index, byte[] data) {
+ @Override
+ public BitBuffer putByteArray(int index, byte[] data) {
for (int l = 0; l < data.length;l++) {
for (int i = 0; i < 8; i++) {
@@ -83,7 +87,8 @@ public class ByteBitBuffer implements BitBuffer {
}
- @Override public byte getByte() {
+ @Override
+ public byte getByte() {
byte result = 0;
for (int i = 0; i < 8; i++) {
result |= (get() ? 1 : 0) << (7 - i);
@@ -91,11 +96,13 @@ public class ByteBitBuffer implements BitBuffer {
return result;
}
- @Override public int limit() {
+ @Override
+ public int limit() {
return limit;
}
- @Override public String toBooleanString(int startIndex, int length) {
+ @Override
+ public String toBooleanString(int startIndex, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = startIndex; i < startIndex + length; i++) {
sb.append(get(i) ? "1" : "0");
@@ -267,5 +274,12 @@ public class ByteBitBuffer implements BitBuffer {
return stringBuilder.toString().trim();
}
+
+ public byte[] fromBooleanString(final String s) {
+
+ return AsnUtils.fromBooleanString(s);
+
+ }
+
}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java b/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java
index f26a598..5ecb925 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java
@@ -21,7 +21,7 @@ class ByteCoder implements Decoder, Encoder {
@SuppressWarnings("unchecked")
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
UperEncoder.logger.debug("BYTE");
return (T) new Byte((byte) UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, 255, false)));
}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java b/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java
index d17a813..0bbce73 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java
@@ -95,7 +95,7 @@ class ChoiceCoder implements Decoder, Encoder {
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field1,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),extraAnnotations);
UperEncoder.logger.debug(String.format("CHOICE: %s", classOfT.getName()));
T result = UperEncoder.instantiate(classOfT);
@@ -120,7 +120,7 @@ class ChoiceCoder implements Decoder, Encoder {
Class<?> classOfElement = field != null ? field.getType() : null;
if (field != null) {
try {
- Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations());
+ Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations(),extractor);
if (field != null) {
field.set(result, decodedValue);
}
@@ -144,7 +144,7 @@ class ChoiceCoder implements Decoder, Encoder {
UperEncoder.newRange(0, sorter.ordinaryFields.size() - 1, false));
Field f = sorter.ordinaryFields.get(index);
UperEncoder.logger.debug(String.format("CHOICE: selected %s", f.getName()));
- Object fieldValue = UperEncoder.decodeAny(bitbuffer, f.getType(),f, f.getAnnotations());
+ Object fieldValue = UperEncoder.decodeAny(bitbuffer, f.getType(),f, f.getAnnotations(),extractor);
try {
f.set(result, fieldValue);
} catch (IllegalArgumentException | IllegalAccessException e) {
diff --git a/src/main/java/org/uic/barcode/asn1/uper/Decoder.java b/src/main/java/org/uic/barcode/asn1/uper/Decoder.java
index 947a752..3140443 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/Decoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/Decoder.java
@@ -5,6 +5,6 @@ import java.lang.reflect.Field;
public interface Decoder {
<T> boolean canDecode(Class<T> classOfT, Annotation[] extraAnnotations);
- <T> T decode(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations);
+ <T> T decode(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations,AsnExtractor extractor);
<T> T getDefault(Class<T> classOfT, Annotation[] extraAnnotations);
}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java b/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java
index 5d78bc7..3bfdec9 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java
@@ -82,7 +82,7 @@ class EnumCoder implements Decoder, Encoder {
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations);
UperEncoder.logger.debug("ENUM");
boolean extensionPresent = false;
diff --git a/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java b/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java
index 5964a64..e5e48c1 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java
@@ -27,7 +27,7 @@ class IntCoder implements Encoder, Decoder {
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),extraAnnotations);
String pos = String.format("Position: %d.%d", bitbuffer.position()/8 , bitbuffer.position() % 8);
UperEncoder.logger.debug(String.format("%s: INTEGER",pos));
diff --git a/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java b/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java
index a7ae7ba..d0ce782 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java
@@ -96,7 +96,7 @@ class SeqOfCoder implements Decoder, Encoder {
@SuppressWarnings("unchecked")
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT,Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),
extraAnnotations);
UperEncoder.logger.debug(String.format("SEQUENCE OF for %s", classOfT));
@@ -135,7 +135,7 @@ class SeqOfCoder implements Decoder, Encoder {
}
}
for (int i = 0; i < size; i++) {
- coll.add(UperEncoder.decodeAny(bitbuffer, classOfElements,field, annotationArray));
+ coll.add(UperEncoder.decodeAny(bitbuffer, classOfElements,field, annotationArray, extractor));
}
T result = null;
diff --git a/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java b/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java
index ce89a3e..3af7217 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java
@@ -150,13 +150,24 @@ class SequenceCoder implements Decoder, Encoder {
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT,Field f1,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations,
+ AsnExtractor extractor) {
UperEncoder.logger.debug(String.format("decode SEQUENCE %s",classOfT.getSimpleName()));
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),extraAnnotations);
T result = UperEncoder.instantiate(classOfT);
- Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT);
+ Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT);
boolean hasExtensionMarker = UperEncoder.hasExtensionMarker(annotations);
boolean extensionPresent = false;
+
+ //check Extraction
+ boolean extract = false;
+ if (extractor != null && !extractor.isStarted() && extractor.found(classOfT.getCanonicalName())) {
+ extractor.startExtraction(bitbuffer.position());
+ extract = true;
+ }
+
+
+ //start decodong
if (hasExtensionMarker) {
extensionPresent = bitbuffer.get();
UperEncoder.logger.debug(String.format("with extension marker, extension %s", extensionPresent ? "present!" : "absent"));
@@ -175,7 +186,7 @@ class SequenceCoder implements Decoder, Encoder {
(UperEncoder.isOptional(f) && optionalFieldsMask.pop()))) {
UperEncoder.logger.debug(String.format("Field : %s", f.getName()));
try {
- f.set(result, UperEncoder.decodeAny(bitbuffer,f.getType(),f, f.getAnnotations()));
+ f.set(result, UperEncoder.decodeAny(bitbuffer,f.getType(),f, f.getAnnotations(),extractor));
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("can't access 'set method' for field " + f + " of class " + classOfT + " " + e, e);
}
@@ -196,6 +207,11 @@ class SequenceCoder implements Decoder, Encoder {
if (!hasExtensionMarker) {
//done
sorter.revertAccess();
+
+ if (extract) {
+ extractor.endExtraction(bitbuffer.position());
+ }
+
return result;
}
@@ -222,7 +238,7 @@ class SequenceCoder implements Decoder, Encoder {
Class<?> classOfElement = field != null ? field.getType() : null;
if (field != null) {
try {
- Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations());
+ Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations(),extractor);
if (field != null) {
field.set(result, decodedValue);
}
@@ -269,6 +285,11 @@ class SequenceCoder implements Decoder, Encoder {
} // end of extension handling
}
sorter.revertAccess();
+
+ if (extract) {
+ extractor.endExtraction(bitbuffer.position());
+ }
+
return result;
}
diff --git a/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java b/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java
index 349e988..a504096 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java
@@ -150,7 +150,7 @@ class StringCoder implements Decoder, Encoder {
@Override public <T> T decode(BitBuffer bitbuffer,
Class<T> classOfT, Field field,
- Annotation[] extraAnnotations) {
+ Annotation[] extraAnnotations, AsnExtractor extractor) {
UperEncoder.logger.debug("decode String");
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations);
RestrictedString restrictionAnnotation = annotations.getAnnotation(RestrictedString.class);
diff --git a/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java b/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java
index d5c5d1e..c256b4f 100644
--- a/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java
+++ b/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java
@@ -66,7 +66,7 @@ public final class UperEncoder {
public static <T> T decode(byte[] bytes, Class<T> classOfT) throws IllegalArgumentException,
UnsupportedOperationException {
BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes));
- T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {});
+ T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}, null);
if (bitQueue.remaining() > 7) {
throw new IllegalArgumentException("Can't fully decode "
+ classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result
@@ -74,11 +74,43 @@ public final class UperEncoder {
}
return result;
}
+
+ public static <T> T decode(byte[] bytes, Class<T> classOfT,AsnExtractor extractor) throws IllegalArgumentException,
+ UnsupportedOperationException {
+ BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes));
+ T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}, extractor);
+ if (bitQueue.remaining() > 7) {
+ throw new IllegalArgumentException("Can't fully decode "
+ + classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result
+ + "; remaining " + bitQueue.remaining() + " bits: " + bitQueue);
+ }
+ return result;
+ }
+
+
+ public static <T> byte[] extract(byte[] bytes,String path,Class<T> classOfT) throws IllegalArgumentException, UnsupportedOperationException {
+
+ BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes));
+
+ AsnExtractor extractor = new AsnExtractor(path,bitQueue);
+
+ T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}, extractor);
+ if (bitQueue.remaining() > 7) {
+ throw new IllegalArgumentException("Can't fully decode "
+ + classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result
+ + "; remaining " + bitQueue.remaining() + " bits: " + bitQueue);
+ }
+ return extractor.getResult();
+ }
+
+
+
+
- public static <T> T decode(byte[] bytes, Class<T> classOfT, Field f) throws IllegalArgumentException,
+ public static <T> T decode(byte[] bytes, Class<T> classOfT, Field f,AsnExtractor extractor) throws IllegalArgumentException,
UnsupportedOperationException {
BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes));
- T result = decodeAny(bitQueue, classOfT, f, new Annotation[] {});
+ T result = decodeAny(bitQueue, classOfT, f, new Annotation[] {}, extractor);
if (bitQueue.remaining() > 7) {
throw new IllegalArgumentException("Can't fully decode "
+ classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result
@@ -108,13 +140,13 @@ public final class UperEncoder {
+ " with extra annotations " + Arrays.asList(extraAnnotations));
}
- static <T> T decodeAny(BitBuffer bitbuffer,Class<T> classOfT, Field f, Annotation[] extraAnnotations) {
+ static <T> T decodeAny(BitBuffer bitbuffer,Class<T> classOfT, Field f, Annotation[] extraAnnotations, AsnExtractor extractor) {
logger.debug(String.format(String.format("Decoding classOfT : %s",classOfT.getCanonicalName())));
for (Decoder e : decoders) {
if (e.canDecode(classOfT, extraAnnotations)) {
- return e.decode(bitbuffer, classOfT,f, extraAnnotations);
+ return e.decode(bitbuffer, classOfT,f, extraAnnotations,extractor);
}
}
@@ -216,7 +248,7 @@ public final class UperEncoder {
}
- static <T> T decodeAsOpenType(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations) {
+ static <T> T decodeAsOpenType(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations,AsnExtractor extractor) {
logger.debug(String.format("OPEN TYPE for %s. Encoding preceedes length determinant", classOfT != null ? classOfT.getName() : "null"));
long numBytes = decodeLengthDeterminant(bitbuffer);
BitBuffer openTypeBitBuffer = ByteBitBuffer.allocate((int)numBytes * 8);
@@ -225,7 +257,7 @@ public final class UperEncoder {
}
openTypeBitBuffer.flip();
if (classOfT != null) {
- T result = decodeAny(openTypeBitBuffer, classOfT, f, extraAnnotations);
+ T result = decodeAny(openTypeBitBuffer, classOfT, f, extraAnnotations, extractor);
// Assert that padding bits are all 0.
logger.debug(String.format("open type had padding bits"));
for (int i = 0; i < openTypeBitBuffer.remaining(); i++) {
diff --git a/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java b/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java
new file mode 100644
index 0000000..34406e0
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java
@@ -0,0 +1,213 @@
+package org.uic.barcode.dynamicContent.api;
+
+import java.util.Date;
+import java.util.List;
+
+import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateType;
+import org.uic.barcode.dynamicContent.fdc1.SequenceOfExtension;
+import org.uic.barcode.dynamicContent.fdc1.TimeStamp;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicContent.fdc1.ExtensionData;
+import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateSystemType;
+import org.uic.barcode.dynamicContent.fdc1.GeoUnitType;
+import org.uic.barcode.dynamicContent.fdc1.HemisphereLatitudeType;
+import org.uic.barcode.dynamicContent.fdc1.HemisphereLongitudeType;
+import org.uic.barcode.ticket.api.impl.SimpleExtension;
+import org.uic.barcode.ticket.api.impl.SimpleGeoCoordinate;
+import org.uic.barcode.ticket.api.spec.IExtension;
+import org.uic.barcode.ticket.api.spec.IGeoCoordinate;
+import org.uic.barcode.ticket.api.spec.IGeoCoordinateSystemType;
+import org.uic.barcode.ticket.api.spec.IGeoUnitType;
+import org.uic.barcode.ticket.api.spec.IHemisphereLatitudeType;
+import org.uic.barcode.ticket.api.spec.IHemisphereLongitudeType;
+import org.uic.barcode.ticket.api.utils.UicEncoderUtils;
+
+public class DynamicContentCoder {
+
+ public static String dynamicContentDataFDC1 = "FDC1";
+
+ public static byte[] encode(IUicDynamicContent content, String format) throws EncodingFormatException {
+
+ if (format != null && !format.equals(dynamicContentDataFDC1)) {
+ throw new EncodingFormatException("Format of dynamic content not supported!");
+ }
+
+ UicDynamicContentDataFDC1 asn = new UicDynamicContentDataFDC1();
+
+ asn.setAppId(content.getAppId());
+
+ if (content.getChallengeString() != null && content.getChallengeString().length() > 0) {
+ asn.setChallengeString(content.getChallengeString());
+ }
+
+ asn.setDynamicContentExtension(getAsnExtension(content.getExtension()));
+
+ asn.setGeoCoordinate(getAsnGeoCoordinate(content.getGeoCoordinate()));
+
+ asn.setTimeStamp(getAsnTimeStamp(content.getTimeStamp()));
+
+ asn.setExtensions(getAsnContentExtensions(asn, content.getDynamicContentResponseList()));
+
+ return UperEncoder.encode(asn);
+
+ }
+
+
+
+ private static SequenceOfExtension getAsnContentExtensions(UicDynamicContentDataFDC1 asn, List<IExtension> dynamicContentResponseList) throws EncodingFormatException {
+ if (dynamicContentResponseList != null && !dynamicContentResponseList.isEmpty()){
+
+ SequenceOfExtension asnList = asn.getExtensions();
+ if (asnList == null) asnList = new SequenceOfExtension();
+ for (IExtension extension : dynamicContentResponseList){
+ ExtensionData asnExtension = getAsnExtension(extension);
+ if (asnExtension!= null) {
+ asnList.add(asnExtension);
+ }
+ }
+ if (!asnList.isEmpty()){
+ return asnList;
+ }
+ }
+
+ return null;
+ }
+
+ private static TimeStamp getAsnTimeStamp(Date date) {
+
+ if (date == null) return null;
+
+ TimeStamp asnTimeStamp = new TimeStamp();
+ asnTimeStamp.setDateTime(date);
+
+ return asnTimeStamp;
+
+ }
+
+ private static GeoCoordinateType getAsnGeoCoordinate(IGeoCoordinate point) {
+
+ if (point == null) return null;
+
+ GeoCoordinateType asnPoint = new GeoCoordinateType();
+
+ asnPoint.setLatitude(point.getLatitude());
+ asnPoint.setLongitude(point.getLongitude());
+
+ if (point.getUnit() != IGeoUnitType.milliDegree && point.getUnit() != null){
+ asnPoint.setGeoUnit(GeoUnitType.valueOf(point.getUnit().name()));
+ }
+
+ if (point.getAccuracy() != null) {
+ asnPoint.setAccuracy(GeoUnitType.valueOf(point.getAccuracy().name()));
+ }
+
+ if (point.getHemisphereLatitude() != IHemisphereLatitudeType.east && point.getHemisphereLatitude() != null) {
+ asnPoint.setHemisphereLatitude(HemisphereLatitudeType.valueOf(point.getHemisphereLatitude().name()));
+ }
+
+ if (point.getHemisphereLongitude() != IHemisphereLongitudeType.north && point.getHemisphereLongitude() != null) {
+ asnPoint.setHemisphereLongitude(HemisphereLongitudeType.valueOf(point.getHemisphereLongitude().name()));
+ }
+
+ if (point.getSystem() != IGeoCoordinateSystemType.wgs84 && point.getSystem() != null){
+ asnPoint.setCoordinateSystem(GeoCoordinateSystemType.valueOf(point.getSystem().name()));
+ }
+
+
+ return asnPoint;
+ }
+
+ private static ExtensionData getAsnExtension(IExtension extension) throws EncodingFormatException {
+ if (extension==null) return null;
+
+ if (extension.getBinarydata() == null || extension.getBinarydata().length == 0) {
+ throw new EncodingFormatException("Extension does not include data");
+ }
+
+ if (extension.getId() == null || extension.getId().length() == 0) {
+ throw new EncodingFormatException("Extension does not include id");
+ }
+
+ ExtensionData asnExtension = new ExtensionData();
+
+ asnExtension.setExtensionData(extension.getBinarydata());
+ asnExtension.setExtensionId(UicEncoderUtils.getIA5(extension.getId()));
+
+ return asnExtension;
+ }
+
+ public static IUicDynamicContent decode(byte[] bytes) {
+
+ UicDynamicContentDataFDC1 asn = UperEncoder.decode(bytes, UicDynamicContentDataFDC1.class);
+
+ IUicDynamicContent content = new SimpleUicDynamicContent();
+
+ content.setAppId(asn.getAppId());
+
+ content.setChallengeString(asn.getChallengeString());
+
+ content.setExtension(getExtension(asn.getDynamicContentExtension()));
+
+ if (asn.getExtensions() != null && !asn.getExtensions().isEmpty()) {
+ for (ExtensionData e : asn.getExtensions()) {
+ content.addDynamicContentResponse(getExtension(e));
+ }
+ }
+
+ content.setGeoCoordinate(getGeoCoordinate(asn.getGeoCoordinate()));
+
+ content.setTimeStamp(asn.getTimeStamp().getTimeAsDate());
+
+
+ return content;
+
+ }
+
+ private static IGeoCoordinate getGeoCoordinate(GeoCoordinateType asnCoordinate) {
+
+ IGeoCoordinate g = new SimpleGeoCoordinate();
+
+ g.setLatitude(asnCoordinate.getLatitude());
+ g.setLongitude(asnCoordinate.getLongitude());
+
+ if (asnCoordinate.getCoordinateSystem() != null) {
+ g.setSystem(IGeoCoordinateSystemType.valueOf(asnCoordinate.getCoordinateSystem().name()));
+ }
+
+ if (asnCoordinate.getAccuracy() != null) {
+ g.setAccuracy(IGeoUnitType.valueOf(asnCoordinate.getAccuracy().name()));
+ }
+
+ if (asnCoordinate.getGeoUnit() != null) {
+ g.setUnit(IGeoUnitType.valueOf(asnCoordinate.getGeoUnit().name()));
+ }
+
+ if (asnCoordinate.getHemisphereLatitude() != null) {
+ g.setHemisphereLatitude(IHemisphereLatitudeType.valueOf(asnCoordinate.getHemisphereLatitude().name()));
+ }
+
+ if (asnCoordinate.getHemisphereLongitude() != null) {
+ g.setHemisphereLongitude(IHemisphereLongitudeType.valueOf(asnCoordinate.getHemisphereLongitude().name()));
+ }
+
+
+ return g;
+ }
+
+
+
+ private static IExtension getExtension(ExtensionData asnExtension) {
+
+ if (asnExtension == null) return null;
+
+ SimpleExtension e = new SimpleExtension();
+ e.setBinarydata(asnExtension.getExtensionData());
+ e.setId(asnExtension.getExtensionId());
+
+ return e;
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java b/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java
new file mode 100644
index 0000000..3b0afde
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java
@@ -0,0 +1,129 @@
+package org.uic.barcode.dynamicContent.api;
+
+import java.util.Date;
+import java.util.List;
+
+import org.uic.barcode.ticket.api.spec.IExtension;
+import org.uic.barcode.ticket.api.spec.IGeoCoordinate;
+
+/**
+ * The Interface IUicDynamicContent.
+ */
+public interface IUicDynamicContent {
+
+ /**
+ * Gets the app id.
+ *
+ * @return the app id
+ */
+ public String getAppId();
+
+ /**
+ * Sets the app id.
+ * @param string
+ *
+ * @return the string
+ */
+ public void setAppId(String string);
+
+ /**
+ * Gets the time stamp.
+ *
+ * @return the time stamp
+ */
+ public Date getTimeStamp();
+
+ /**
+ * Sets the time stamp.
+ *
+ * @param date the new time stamp
+ */
+ public void setTimeStamp(Date date);
+
+ /**
+ * Gets the geo coordinate.
+ *
+ * @return the geo coordinate
+ */
+ public IGeoCoordinate getGeoCoordinate();
+
+ /**
+ * Sets the geo coordinate.
+ *
+ * @param geoCoordinate the new geo coordinate
+ */
+ public void setGeoCoordinate(IGeoCoordinate geoCoordinate);
+
+
+ /**
+ * Gets the extension.
+ *
+ * @return the extension
+ */
+ public IExtension getExtension();
+
+ /**
+ * Sets the extension.
+ *
+ * @param extension the new extension
+ */
+ public void setExtension(IExtension extension);
+
+ /**
+ * Gets the challenge string.
+ *
+ * @return the challenge string
+ */
+ public String getChallengeString();
+
+ /**
+ * Sets the challenge string.
+ *
+ * @param challenge the new challenge string
+ */
+ public void setChallengeString(String challenge);
+
+ /**
+ * Gets the phone id hash.
+ *
+ * @return the phone id hash
+ */
+ public byte[] getPhoneIdHash();
+
+ /**
+ * Sets the phone id hash.
+ *
+ * @param phoneIdHash the new phone id hash
+ */
+ public void setPhoneIdHash(byte[] phoneIdHash);
+
+ /**
+ * Gets the pass id hash.
+ *
+ * @return the pass id hash
+ */
+ public byte[] getPassIdHash();
+
+ /**
+ * Sets the pass id hash.
+ *
+ * @param passIdHash the new pass id hash
+ */
+ public void setPassIdHash(byte[] passIdHash);
+
+ /**
+ * Gets the dynamic content response list.
+ *
+ * @return the dynamic content response list
+ */
+ public List<IExtension> getDynamicContentResponseList();
+
+ /**
+ * Adds the dynamic content response.
+ *
+ * @param challenge the challenge
+ */
+ public void addDynamicContentResponse(IExtension challenge);
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicContent/api/SimpleUicDynamicContent.java b/src/main/java/org/uic/barcode/dynamicContent/api/SimpleUicDynamicContent.java
new file mode 100644
index 0000000..ca5880d
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicContent/api/SimpleUicDynamicContent.java
@@ -0,0 +1,150 @@
+package org.uic.barcode.dynamicContent.api;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.uic.barcode.ticket.api.impl.SimpleExtension;
+import org.uic.barcode.ticket.api.spec.IExtension;
+import org.uic.barcode.ticket.api.spec.IGeoCoordinate;
+
+public class SimpleUicDynamicContent implements IUicDynamicContent {
+
+
+ protected String appId;
+
+ protected Date timeStamp;
+
+ protected String challenge;
+
+ protected IGeoCoordinate geoCoordinate;
+
+ protected IExtension dynamicContentExtension;
+
+ protected List<IExtension> dynamicContentResponseList;
+
+
+
+ public String getAppId() {
+ return appId;
+ }
+
+ public void setAppId(String appId) {
+ this.appId = appId;
+ }
+
+
+ public IGeoCoordinate getGeoCoordinate() {
+ return geoCoordinate;
+ }
+
+ public void setGeoCoordinate(IGeoCoordinate geoCoordinate) {
+ this.geoCoordinate = geoCoordinate;
+ }
+
+ public IExtension getDynamicContentExtension() {
+ return dynamicContentExtension;
+ }
+
+ public void setDynamicContentExtension(IExtension dynamicContentExtension) {
+ this.dynamicContentExtension = dynamicContentExtension;
+ }
+
+
+ @Override
+ public Date getTimeStamp() {
+ return timeStamp;
+ }
+
+ @Override
+ public void setTimeStamp(Date date) {
+ timeStamp = date;
+
+ }
+
+ @Override
+ public IExtension getExtension() {
+ return dynamicContentExtension;
+ }
+
+ @Override
+ public void setExtension(IExtension extension) {
+ dynamicContentExtension = extension;
+ }
+
+ @Override
+ public String getChallengeString() {
+ return challenge;
+ }
+
+ @Override
+ public void setChallengeString(String challenge) {
+ this.challenge = challenge;
+ }
+
+ @Override
+ public byte[] getPhoneIdHash() {
+ return getExtensionData("phone");
+ }
+
+ @Override
+ public void setPhoneIdHash(byte[] phoneIdHash) {
+ if (dynamicContentResponseList == null) {
+ dynamicContentResponseList = new ArrayList<IExtension>();
+ }
+
+ IExtension e = new SimpleExtension();
+ e.setBinarydata(phoneIdHash);
+ e.setId("phone");
+ getDynamicContentResponseList().add(e);
+ }
+
+ @Override
+ public byte[] getPassIdHash() {
+ return getExtensionData("pass");
+ }
+
+ private byte[] getExtensionData(String name) {
+ if (dynamicContentResponseList == null) return null;
+ for (IExtension e : dynamicContentResponseList) {
+ if (e.getId().equals(name)){
+ return e.getBinarydata();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void setPassIdHash(byte[] passIdHash) {
+ if (dynamicContentResponseList == null) {
+ dynamicContentResponseList = new ArrayList<IExtension>();
+ }
+
+ IExtension e = new SimpleExtension();
+ e.setBinarydata(passIdHash);
+ e.setId("pass");
+ getDynamicContentResponseList().add(e);
+ }
+
+ @Override
+ public List<IExtension> getDynamicContentResponseList() {
+ if (dynamicContentResponseList == null) {
+ dynamicContentResponseList = new ArrayList<IExtension>();
+ }
+
+ return dynamicContentResponseList;
+ }
+
+ @Override
+ public void addDynamicContentResponse(IExtension challenge) {
+
+ if (this.dynamicContentResponseList == null) {
+ this.dynamicContentResponseList = new ArrayList<IExtension>();
+ }
+
+ this.dynamicContentResponseList.add(challenge);
+
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoCoordinateSystemType.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoCoordinateSystemType.java
index b25ad1a..700c542 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoCoordinateSystemType.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoCoordinateSystemType.java
@@ -20,7 +20,6 @@
package org.uic.barcode.dynamicContent.fdc1;
-// TODO: Auto-generated Javadoc
/**
* The Enum GeoCoordinateSystemType.
*/
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoUnitType.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoUnitType.java
index 4eaa8c9..591e28a 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoUnitType.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/GeoUnitType.java
@@ -19,7 +19,6 @@
*/
package org.uic.barcode.dynamicContent.fdc1;
-// TODO: Auto-generated Javadoc
/**
* The Enum GeoUnitType.
*/
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLatitudeType.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLatitudeType.java
index 5157b0e..b39e599 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLatitudeType.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLatitudeType.java
@@ -19,7 +19,6 @@
*/
package org.uic.barcode.dynamicContent.fdc1;
-// TODO: Auto-generated Javadoc
/**
* The Enum HemisphereLatitudeType.
*/
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLongitudeType.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLongitudeType.java
index c0e33e6..e1e39f0 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLongitudeType.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/HemisphereLongitudeType.java
@@ -19,7 +19,6 @@
*/
package org.uic.barcode.dynamicContent.fdc1;
-// TODO: Auto-generated Javadoc
/**
* The Enum HemisphereLongitudeType.
*/
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
index ecbb226..c2cd8fa 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
@@ -91,8 +91,11 @@ public class TimeStamp {
this.secondOfDay = time;
}
+
+
+
/**
- * Gets the time.
+ * Gets the current date and time in UTC
*
* @return the date and time of content creation in UTC
*/
@@ -102,17 +105,18 @@ public class TimeStamp {
int dayOfYear = now.getDayOfYear();
if (dayOfYear - day.intValue() > 250) {
- now = now.plusDays(1);
+ now = now.plusYears(1);
}
if (day.intValue() - dayOfYear > 250) {
- now = now.minusDays(1);
+ now = now.minusYears(1);
}
now = now.withDayOfYear(1);
now = now.withSecond(0);
now = now.withHour(0);
now = now.withMinute(0);
- now = now.withDayOfYear(dayOfYear);
+ now = now.withNano(0);
+ now = now.withDayOfYear(day.intValue());
now = now.plusSeconds(secondOfDay);
return Date.from(now.toInstant());
@@ -136,4 +140,6 @@ public class TimeStamp {
}
+
+
}
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
index e8f3695..9957ede 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
@@ -11,7 +11,9 @@ import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.uper.UperEncoder;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.v1.DataType;
/**
@@ -94,6 +96,14 @@ public class UicDynamicContentDataFDC1 {
return "FDC1";
}
+ public IData getApiDataType() {
+ IData data = new SimpleData();
+ data.setFormat(getFormat());
+ data.setData(UperEncoder.encode(this));
+ return data;
+ }
+
+
public DataType getDataType() {
DataType data = new DataType();
data.setFormat(getFormat());
@@ -181,6 +191,8 @@ public class UicDynamicContentDataFDC1 {
this.timeStamp = timeStamp;
}
+
+
public SequenceOfExtension getExtensions() {
return dynamicContentResponseToChallenge;
}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
index 8f47986..3623817 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
@@ -36,4 +36,9 @@ public class Constants {
public static int LEVEL1_VALIDATION_KEY_ALG_NOT_IMPLEMENTED = 5;
public static int LEVEL1_VALIDATION_ENCODING_ERROR = 6;
+ public static String DYNAMIC_BARCODE_FORMAT_VERSION_1 = "U1";
+ public static String DYNAMIC_BARCODE_FORMAT_VERSION_2 = "U2";
+
+ public static String DYNAMIC_BARCODE_FORMAT_VERSION_1_BIN = "10101010110001";
+ public static String DYNAMIC_BARCODE_FORMAT_VERSION_2_BIN = "10101010110010";
}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
deleted file mode 100644
index c74215d..0000000
--- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
+++ /dev/null
@@ -1,337 +0,0 @@
-package org.uic.barcode.dynamicFrame;
-
-import java.security.InvalidKeyException;
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.Provider;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.SignatureException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
-
-import org.uic.barcode.asn1.datatypes.Asn1Optional;
-import org.uic.barcode.asn1.datatypes.CharacterRestriction;
-import org.uic.barcode.asn1.datatypes.FieldOrder;
-import org.uic.barcode.asn1.datatypes.RestrictedString;
-import org.uic.barcode.asn1.datatypes.Sequence;
-import org.uic.barcode.asn1.datatypesimpl.OctetString;
-import org.uic.barcode.asn1.uper.UperEncoder;
-import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
-import org.uic.barcode.utils.AlgorithmNameResolver;
-
-
-/**
- * The DynamicHeader for bar codes
- *
- * Implementation of the Draft under discussion, not final.
- */
-@Sequence
-public class DynamicFrame extends Object{
-
- public DynamicFrame() {}
-
- /** The format. */
- @FieldOrder(order = 0)
- @RestrictedString(CharacterRestriction.IA5String)
- public String format;
-
- /*level 2 data*/
- @FieldOrder(order = 1)
- Level2DataType level2SignedData;
-
-
- /** The signature of level 2 data*/
- @FieldOrder(order = 2)
- @Asn1Optional public OctetString level2Signature;
-
- /**
- * Gets the format.
- *
- * @return the format
- */
- public String getFormat() {
- return format;
- }
-
- /**
- * Sets the format.
- *
- * @param format the new format
- */
- public void setFormat(String format) {
- this.format = format;
- }
-
- public Level2DataType getLevel2SignedData() {
- return level2SignedData;
- }
-
- public void setLevel2SignedData(Level2DataType level2SignedData) {
- this.level2SignedData = level2SignedData;
- }
-
- public OctetString getLevel2Signature() {
- return level2Signature;
- }
-
- public void setLevel2Signature(OctetString level2Signature) {
- this.level2Signature = level2Signature;
- }
-
- /**
- * Encode.
- *
- * Encode the header as ASN.1 PER UNALIGNED byte array
- *
- * @return the byte[]
- */
- public byte[] encode() {
- return UperEncoder.encode(this);
- }
-
- /**
- * Decode.
- *
- * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
- *
- * @param bytes the bytes
- * @return the dynamic header
- */
- public static DynamicFrame decode(byte[] bytes) {
- return UperEncoder.decode(bytes, DynamicFrame.class);
- }
-
- /**
- * Verify the level 2 signature
- *
- * Note: an appropriate security provider (e.g. BC) must be registered before
- *
- */
- public int validateLevel2() {
-
- return validateLevel2(null);
-
- }
-
- /**
- * Verify the level 2 signature
- *
- * Note: an appropriate security provider (e.g. BC) must be registered before
- *
- */
- public int validateLevel2(Provider prov) {
-
-
- String level2KeyAlg = this.getLevel2SignedData().getLevel1Data().level2KeyAlg;
-
-
- if (level2KeyAlg == null || level2KeyAlg.length() == 0) {
- return Constants.LEVEL2_VALIDATION_NO_KEY;
- }
-
- if (this.level2Signature.toByteArray() == null || this.level2Signature.toByteArray().length == 0) {
- return Constants.LEVEL2_VALIDATION_NO_SIGNATURE;
- }
-
- String keyAlgName = null;
- try {
- keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg);
- } catch (Exception e1) {
- return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
- }
- if (keyAlgName == null || keyAlgName.length() == 0) {
- return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
- }
-
- PublicKey key = null;
- try {
- byte[] keyBytes = this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray();
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
- key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
- } catch (InvalidKeySpecException e1) {
- return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
- } catch (NoSuchAlgorithmException e1) {
- return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
- }
-
- //find the algorithm name for the signature OID
- String level2SigAlg = this.getLevel2SignedData().getLevel1Data().level2SigningAlg;
-
- String sigAlgName = null;
- try {
- sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg);
- } catch (Exception e1) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
- if (sigAlgName == null) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
-
- Signature sig;
- try {
- if (prov == null) {
- sig = Signature.getInstance(sigAlgName);
- } else {
- sig = Signature.getInstance(sigAlgName, prov);
- }
- } catch (NoSuchAlgorithmException e) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
- try {
- sig.initVerify(key);
- } catch (InvalidKeyException e) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
-
- try {
- byte[] data = UperEncoder.encode(level2SignedData);
- sig.update(data);
- } catch (SignatureException e) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- } catch (IllegalArgumentException e) {
- return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
- } catch (UnsupportedOperationException e) {
- return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
- }
-
- byte[] signature = level2Signature.toByteArray();
- try {
- if (sig.verify(signature)){
- return Constants.LEVEL2_VALIDATION_OK;
- } else {
- return Constants.LEVEL2_VALIDATION_FRAUD;
- }
- } catch (SignatureException e) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
- }
-
- /**
- * Verify the level 1 signature
- *
- * Note: an appropriate security provider (e.g. BC) must be registered before
- *
- */
- public int validateLevel1(PublicKey key, Provider prov) {
-
- if (this.level2SignedData == null) {
- return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
- }
-
-
- if (this.level2SignedData.level1Signature == null || this.level2SignedData.level1Signature.toByteArray().length == 0) {
- return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
- }
-
- byte[] signature = this.getLevel2SignedData().level1Signature.toByteArray();
-
- //find the algorithm name for the signature OID
- String algo = null;
- try {
- algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2SignedData().getLevel1Data().level1SigningAlg);
- } catch (Exception e1) {
- return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
- if (algo == null) {
- return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
-
- Signature sig;
- try {
- if (prov != null) {
- sig = Signature.getInstance(algo, prov);
- } else {
- sig = Signature.getInstance(algo);
-
- }
- } catch (NoSuchAlgorithmException e) {
- return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
- try {
- sig.initVerify(key);
- } catch (InvalidKeyException e) {
- return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
-
- try {
- sig.update(this.level2SignedData.level1Data.encode());
- } catch (SignatureException e) {
- return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- } catch (IllegalArgumentException e) {
- return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
- } catch (UnsupportedOperationException e) {
- return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
- }
-
-
- try {
- if (sig.verify(signature)){
- return Constants.LEVEL2_VALIDATION_OK;
- } else {
- return Constants.LEVEL2_VALIDATION_FRAUD;
- }
- } catch (SignatureException e) {
- return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
- }
- }
-
- /**
- * Verify the level 1 signature
- *
- * Note: an appropriate security provider (e.g. BC) must be registered before
- *
- */
- public int validateLevel1(PublicKey key) {
-
- return validateLevel1(key, null);
-
- }
-
- public void signLevel2(PrivateKey key) throws Exception {
-
- //find the algorithm name for the signature OID
- String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
- Signature sig = Signature.getInstance(algo);
- sig.initSign(key);
- byte[] data = level2SignedData.encode();
- sig.update(data);
- byte[] signature = sig.sign();
- this.level2Signature = new OctetString(signature);
-
- }
-
- public void signLevel2(PrivateKey key, Provider prov) throws Exception {
-
- //find the algorithm name for the signature OID
- String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
- Signature sig = Signature.getInstance(algo,prov);
- sig.initSign(key);
- byte[] data = level2SignedData.encode();
- sig.update(data);
- this.level2Signature = new OctetString(sig.sign());
-
- }
-
-
- public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
- this.getLevel2SignedData().setLevel2Data( dynamicData.getDataType());
- }
-
- public UicDynamicContentDataFDC1 getDynamicDataFDC1() {
-
- if (this.getLevel2SignedData() == null ||
- this.getLevel2SignedData().getLevel2Data() == null){
- return null;
- }
-
- if ( UicDynamicContentDataFDC1.getFormat().equals(this.getLevel2SignedData().getLevel2Data().getFormat())) {
- return UperEncoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData(), UicDynamicContentDataFDC1.class);
- }
- return null;
-
- }
-
-
-}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/DynamicFrameCoder.java b/src/main/java/org/uic/barcode/dynamicFrame/api/DynamicFrameCoder.java
new file mode 100644
index 0000000..53efb3e
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/DynamicFrameCoder.java
@@ -0,0 +1,107 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrameCoderV1;
+import org.uic.barcode.dynamicFrame.v2.DynamicFrameCoderV2;
+import org.uic.barcode.ticket.EncodingFormatException;
+
+public class DynamicFrameCoder {
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ * @throws EncodingFormatException
+ */
+ public static byte[] encode(IDynamicFrame frame) throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(frame.getFormat())) {
+
+ return DynamicFrameCoderV1.encode(frame);
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(frame.getFormat())) {
+
+ return DynamicFrameCoderV2.encode(frame);
+
+ }
+
+ throw new EncodingFormatException("Frame version not supported for encoding");
+ }
+
+
+ /**
+ * Decode.
+ *
+ * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
+ *
+ * @param bytes the bytes
+ * @return the dynamic header
+ * @throws EncodingFormatException
+ */
+ public static IDynamicFrame decode(byte[] bytes) throws EncodingFormatException {
+
+ IDynamicFrame frame = new SimpleDynamicFrame();
+
+ try {
+ DynamicFrameCoderV1.decode(frame,bytes);
+
+ if (frame.getFormat() != null && frame.getFormat().equals(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1)) {
+ return frame;
+ }
+ } catch(Exception e1) {
+ frame = null;
+ // failed, try next
+ }
+
+ frame = new SimpleDynamicFrame();
+ try {
+ DynamicFrameCoderV2.decode(frame,bytes);
+
+ if (frame.getFormat() != null && frame.getFormat().equals(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2)) {
+ return frame;
+ }
+ } catch(Exception e1) {
+ throw new EncodingFormatException("Dynamic Header Version not supported");
+ // failed
+ }
+
+ throw new EncodingFormatException("Dynamic Header Version not supported");
+
+ }
+
+
+ public static byte[] encodeLevel1(IDynamicFrame frame) throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(frame.getFormat())) {
+
+ return DynamicFrameCoderV1.encodeLevel1(frame);
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(frame.getFormat())) {
+
+ return DynamicFrameCoderV2.encodeLevel1(frame);
+
+ }
+
+ throw new EncodingFormatException("Frame version not supported for encoding");
+
+ }
+
+
+ public static byte[] encodeLevel2Data(IDynamicFrame frame) throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(frame.getFormat())) {
+
+ return DynamicFrameCoderV1.encodeLevel2Data(frame.getLevel2Data());
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(frame.getFormat())) {
+
+ return DynamicFrameCoderV2.encodeLevel2Data(frame.getLevel2Data());
+
+ }
+
+ throw new EncodingFormatException("Dynamic Header Version not supported: " + frame.getFormat());
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/IData.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IData.java
new file mode 100644
index 0000000..51f9c7b
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IData.java
@@ -0,0 +1,39 @@
+package org.uic.barcode.dynamicFrame.api;
+
+/**
+ * The Class DataType.
+ */
+public interface IData {
+
+
+
+
+ /**
+ * Gets the data format.
+ *
+ * @return the data format
+ */
+ public String getFormat();
+
+ /**
+ * Sets the data format.
+ *
+ * @param dataFormat the new data format
+ */
+ public void setFormat(String format);
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public byte[] getData();
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(byte[] data);
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java
new file mode 100644
index 0000000..4b2d1f4
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java
@@ -0,0 +1,225 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.ticket.EncodingFormatException;
+
+
+
+/**
+ * The DynamicHeader for bar codes .
+ */
+public interface IDynamicFrame{
+
+
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ public String getFormat();
+
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ public void setFormat(String format);
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ public ILevel2Data getLevel2Data();
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2Data the new level 2 data
+ */
+ public void setLevel2Data(ILevel2Data level2Data);
+
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ public byte[] getLevel2Signature();
+
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ public void setLevel2Signature(byte[] level2Signature);
+
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ * @return the return error code
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel2() throws EncodingFormatException;
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param prov the registered security provider
+ * @return the return error code
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel2(Provider prov) throws EncodingFormatException;
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param data the data content
+ * @return the return error code
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel1(PublicKey key) throws EncodingFormatException;
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param signatureAlgorithmOid the signature algorithmOid to be used in case it is not contained in the barcode
+ * @return the return error code
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel1(PublicKey key,String signatureAlgorithmOid) throws EncodingFormatException;
+
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param prov the registered security provider
+ * @return the return error code
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException;
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param prov the registered security provider
+ * @return the return error code
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public int validateLevel1(PublicKey key, Provider prov, String signatureAlgorithmOid) throws EncodingFormatException;
+
+ /**
+ * Sign level 2 data without a specific security provider.
+ *
+ * @param key the key
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key) throws Exception;
+
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the security Provider
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key, Provider prov) throws Exception;
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException;
+
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData);
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ public IUicDynamicContent getDynamicContent();
+
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the private key
+ * @return the signature
+ * @throws Exception the exception
+ */
+ public void signLevel1(PrivateKey key) throws Exception;
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the private key
+ * @param prov the security provider providing the signature implementation
+ * @return the byte[]
+ * @throws Exception the exception
+ */
+ public void signLevel1(PrivateKey key, Provider prov) throws Exception;
+
+
+ /**
+ * Gets the signature of the level 1 data.
+ *
+ * @return the level 1 signature
+ */
+ public byte[] getLevel1Signature();
+
+ /**
+ * Gets the level 1 data in binary as they are signed by the level 1 signature.
+ *
+ * @return the level 1 data binary
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public byte[] getLevel1DataBin() throws EncodingFormatException;
+
+ /**
+ * Gets the level 2 data in binary as they are signed by the level 1 signature.
+ *
+ * @return the level 2 data binary
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public byte[] getLevel2DataBin() throws EncodingFormatException;
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java
new file mode 100644
index 0000000..e23fc88
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java
@@ -0,0 +1,202 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.util.Collection;
+import java.util.Date;
+
+/**
+ * The Class SignedDataType.
+ */
+public interface ILevel1Data {
+
+
+
+ /**
+ * Sets the security provider .
+ *
+ * @param securityProvider the new security provider
+ */
+ public void setSecurityProvider(String securityProvider);
+
+
+ /**
+ * Gets the security provider.
+ *
+ * @return the security provider
+ */
+ public String getSecurityProvider();
+
+
+
+
+
+
+ /**
+ * Gets the key id.
+ *
+ * @return the key id
+ */
+ public Long getKeyId();
+
+
+ /**
+ * Sets the key id.
+ *
+ * @param keyId the new key id
+ */
+ public void setKeyId(Long keyId);
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public Collection<IData> getData();
+
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(Collection<IData> data);
+
+ /**
+ * Adds data.
+ *
+ * @param data the new data
+ */
+ public void addData(IData data);
+
+ /**
+ * Gets the level 2 key algorithm OID.
+ *
+ * @return the level 2 key alg
+ */
+ public String getLevel2KeyAlg();
+
+
+ /**
+ * Sets the level 2 key algorithm OID.
+ *
+ * @param level2KeyAlg the new level 2 key alg
+ */
+ public void setLevel2KeyAlg(String level2KeyAlg);
+
+
+ /**
+ * Gets the level 1 signing alg.
+ *
+ * @return the level 1 signing alg
+ */
+ public String getLevel1SigningAlg();
+
+
+ /**
+ * Sets the level 1 signing algorithm OID.
+ *
+ * @param level1SigningAlg the new level 1 signing alg
+ */
+ public void setLevel1SigningAlg(String level1SigningAlg);
+
+
+ /**
+ * Gets the level 2 signing algorithm OID.
+ *
+ * @return the level 2 signing alg
+ */
+ public String getLevel2SigningAlg();
+
+
+ /**
+ * Sets the level 2 signing algorithm OID.
+ *
+ * @param level2SigningAlg the new level 2 signing alg
+ */
+ public void setLevel2SigningAlg(String level2SigningAlg);
+
+
+ /**
+ * Gets the level 2 public key.
+ *
+ * @return the level 2 public key
+ */
+ public byte[] getLevel2publicKey();
+
+
+ /**
+ * Sets the level 2 public key.
+ *
+ * @param level2publicKey the new level 2 public key
+ */
+ public void setLevel2publicKey(byte[] level2publicKey);
+
+
+
+ /**
+ * Gets the level 1 key algorithm OID.
+ *
+ * @return the level 1 key alg
+ */
+ public String getLevel1KeyAlg();
+
+ /**
+ * Sets the level 1 key algorithm OID.
+ *
+ * @param level1KeyAlg the new level 1 key alg
+ */
+ public void setLevel1KeyAlg(String level1KeyAlg);
+
+
+ /**
+ * Sets the end of validity date. The validity date has to be provided in UTC.
+ *
+ * -- end of the validity of the bar code, after this date and time the bar code needs to be regenerated
+ * -- by the provider of the ticket
+ * -- if end of validity is provided year day and time must be provided.
+ * -- year, day, time are in UTC
+ * -- the provider of the bar code should ensure that the endOfValidity given here does not exceed
+ * -- the validity of the key pair used on level 2.
+ *
+ * @param date the new end of validity date
+ */
+ public void setEndOfBarcodeValidity(Date date);
+
+
+ /**
+ * Gets the end of validity date and time.
+ *
+ * -- end of the validity of the bar code, after this date and time the bar code needs to be regenerated
+ * -- by the provider of the ticket
+ * -- if end of validity is provided year day and time must be provided.
+ * -- year, day, time are in UTC
+ * -- the provider of the bar code should ensure that the endOfValidity given here does not exceed
+ * -- the validity of the key pair used on level 2.
+ *
+ * @return the end of validity date
+ */
+ public Date getEndOfBarcodeValidity();
+
+
+ /**
+ * Gets the validity duration of the bar code in seconds.
+ *
+ * -- validity duration in seconds of the bar code shown with reference to the time stamp dynamicContentTimeStamp
+ * -- in the dynamic data included in the level2Data
+ *
+ * @return the validity duration
+ */
+ public Long getValidityDuration();
+
+
+ /**
+ * Sets the validity validity duration of the bar code in seconds.
+ *
+ * -- validity duration in seconds of the bar code shown with reference to the time stamp dynamicContentTimeStamp
+ * -- in the dynamic data included in the level2Data
+ *
+ * @param validityDuration the new validity duration
+ */
+ public void setValidityDuration(Long validityDuration);
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java
new file mode 100644
index 0000000..cc28422
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java
@@ -0,0 +1,25 @@
+package org.uic.barcode.dynamicFrame.api;
+
+/**
+ * The Level 2 data.
+ */
+
+public interface ILevel2Data {
+
+
+
+ public ILevel1Data getLevel1Data();
+
+ public void setLevel1Data(ILevel1Data level1Data);
+
+ public byte[] getLevel1Signature();
+
+ public byte[] getLevel1SignatureBytes();
+
+ public void setLevel1Signature(byte[] level1Signature);
+
+ public IData getLevel2Data();
+
+ public void setLevel2Data(IData level2Data);
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java
new file mode 100644
index 0000000..d6e1410
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java
@@ -0,0 +1,52 @@
+package org.uic.barcode.dynamicFrame.api;
+
+/**
+ * The Class DataType.
+ */
+public class SimpleData implements IData{
+
+
+ /** The data format.
+ *
+ * -- FCB1 FCB version 1
+ * -- FCB2 FCB version 2
+ * -- RICS company code + ...
+ **/
+ public String format;
+
+ /** The data. */
+ public byte[] data;
+
+ /**
+ * Gets the data format.
+ *
+ * @return the data format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the data format.
+ *
+ * @param dataFormat the new data format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public byte[] getData() {
+ return data;
+ }
+
+ @Override
+ public void setData(byte[] data) {
+ this.data = data;
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java
new file mode 100644
index 0000000..a05a936
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java
@@ -0,0 +1,499 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Date;
+
+import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrameCoderV1;
+import org.uic.barcode.dynamicFrame.v2.DynamicFrameCoderV2;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.utils.AlgorithmNameResolver;
+
+
+
+/**
+ * The DynamicHeader for bar codes
+ *
+ */
+public class SimpleDynamicFrame implements IDynamicFrame {
+
+ /**
+ * Instantiates a new dynamic frame.
+ */
+ public SimpleDynamicFrame() {}
+
+ public SimpleDynamicFrame(String format) {
+ this.format = format;
+ }
+
+ /** The format. */
+ public String format = null;
+
+ /** The level 2 signed data. */
+ /*level 2 data*/
+ public ILevel2Data level2Data;
+
+
+ /** The signature of level 2 data. */
+ public byte[] level2Signature;
+
+ public Date endOfValidity = null;
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ @Override
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ @Override
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ @Override
+ public ILevel2Data getLevel2Data() {
+ return level2Data;
+ }
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2SignedData the new level 2 signed data
+ */
+ @Override
+ public void setLevel2Data(ILevel2Data level2SignedData) {
+ this.level2Data = level2SignedData;
+ }
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ @Override
+ public byte[] getLevel2Signature() {
+ return level2Signature;
+ }
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ @Override
+ public void setLevel2Signature(byte[] level2Signature) {
+ this.level2Signature = level2Signature;
+ }
+
+
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ @Override
+ public int validateLevel2() throws EncodingFormatException {
+ return validateLevel2(null);
+
+ }
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param prov the registered security provider
+ * @return the return error code
+ * @throws EncodingFormatException
+ */
+ @Override
+ public int validateLevel2(Provider prov) throws EncodingFormatException {
+
+ if (getLevel2Data() == null
+ || getLevel2Data().getLevel1Data() == null
+ || getLevel2Data().getLevel1Data().getLevel2KeyAlg() == null
+ || getLevel2Data().getLevel1Data().getLevel2KeyAlg().length() == 0) {
+ return Constants.LEVEL2_VALIDATION_NO_KEY;
+ }
+
+ String level2KeyAlg = getLevel2Data().getLevel1Data().getLevel2KeyAlg();
+
+
+ if (level2KeyAlg == null || level2KeyAlg.length() == 0) {
+ return Constants.LEVEL2_VALIDATION_NO_KEY;
+ }
+
+ if (level2Signature == null || level2Signature.length == 0) {
+ return Constants.LEVEL2_VALIDATION_NO_SIGNATURE;
+ }
+
+ String keyAlgName = null;
+ try {
+ keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg,prov);
+ } catch (Exception e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+ if (keyAlgName == null || keyAlgName.length() == 0) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+
+ PublicKey key = null;
+ try {
+ byte[] keyBytes = this.getLevel2Data().getLevel1Data().getLevel2publicKey();
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+ key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
+ } catch (InvalidKeySpecException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ } catch (NoSuchAlgorithmException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+
+ //find the algorithm name for the signature OID
+ String level2SigAlg = this.getLevel2Data().getLevel1Data().getLevel2SigningAlg();
+
+ String sigAlgName = null;
+ try {
+ sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg,prov);
+ } catch (Exception e1) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ if (sigAlgName == null) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ Signature sig;
+ try {
+ if (prov == null) {
+ sig = Signature.getInstance(sigAlgName);
+ } else {
+ sig = Signature.getInstance(sigAlgName, prov);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ try {
+ sig.initVerify(key);
+ } catch (InvalidKeyException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ try {
+ byte[] signedData2 = getLevel2DataBin();
+ sig.update(signedData2);
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } catch (IllegalArgumentException e) {
+ return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
+ } catch (UnsupportedOperationException e) {
+ return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
+ }
+
+ byte[] signature = level2Signature;
+ try {
+ if (sig.verify(signature)){
+ return Constants.LEVEL2_VALIDATION_OK;
+ } else {
+ return Constants.LEVEL2_VALIDATION_FRAUD;
+ }
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ }
+
+ @Override
+ public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException {
+ return validateLevel1(key, prov, null);
+
+ }
+
+ @Override
+ public int validateLevel1(PublicKey key) throws EncodingFormatException {
+ return validateLevel1(key, null, null);
+ }
+
+ @Override
+ public int validateLevel1(PublicKey key, String signatureAlgorithmOid) throws EncodingFormatException {
+ return validateLevel1(key, null, signatureAlgorithmOid);
+ }
+
+ @Override
+ public int validateLevel1(PublicKey key, Provider prov, String signatureAlgorithmOid) throws EncodingFormatException {
+
+ if (getLevel2Data() == null
+ || getLevel2Data().getLevel1Signature() == null
+ || getLevel2Data().getLevel1Signature() == null
+ || getLevel2Data().getLevel1Signature().length == 0) {
+ return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
+ }
+
+ byte[] signature = this.getLevel2Data().getLevel1Signature();
+
+
+ //find the algorithm name for the signature OID
+ String signingAlgorithmOid = null;
+ if (getLevel2Data() != null
+ && getLevel2Data().getLevel1Data() != null
+ && getLevel2Data().getLevel1Data().getLevel1SigningAlg() != null
+ && getLevel2Data().getLevel1Data().getLevel1SigningAlg().length() > 0) {
+ signingAlgorithmOid = getLevel2Data().getLevel1Data().getLevel1SigningAlg();
+ } else {
+ signingAlgorithmOid = signatureAlgorithmOid;
+ }
+
+ if (signingAlgorithmOid == null || signingAlgorithmOid.length() == 0) {
+ return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
+ }
+ //find the algorithm name for the signature OID
+ String algo = null;
+ try {
+ algo = AlgorithmNameResolver.getSignatureAlgorithmName(signingAlgorithmOid, prov);
+ } catch (Exception e1) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ if (algo == null) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ Signature sig;
+ try {
+ if (prov != null) {
+ sig = Signature.getInstance(algo, prov);
+ } else {
+ sig = Signature.getInstance(algo);
+
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ try {
+ sig.initVerify(key);
+ } catch (InvalidKeyException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ try {
+
+ byte[] encodedData = getLevel1DataBin();
+
+ sig.update(encodedData);
+
+ } catch (SignatureException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } catch (IllegalArgumentException e) {
+ return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
+ } catch (UnsupportedOperationException e) {
+ return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
+ }
+
+ try {
+ if (sig.verify(signature)){
+ return Constants.LEVEL1_VALIDATION_OK;
+ } else {
+ return Constants.LEVEL1_VALIDATION_FRAUD;
+ }
+ } catch (SignatureException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ }
+
+ @Override
+ public void signLevel2(PrivateKey key) throws Exception {
+ signLevel2(key, null);
+ }
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the registered security provider
+ * @throws Exception the exception
+ */
+ @Override
+ public void signLevel2(PrivateKey key, Provider prov) throws Exception {
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2Data().getLevel1Data().getLevel2SigningAlg(), prov);
+ Signature sig = null;
+ if (prov != null) {
+ sig = Signature.getInstance(algo,prov);
+ } else {
+ sig = Signature.getInstance(algo);
+ }
+ sig.initSign(key);
+ byte[] signedData = DynamicFrameCoder.encodeLevel2Data(this);
+ sig.update(signedData);
+ level2Signature = sig.sign();
+
+ }
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ @Override
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException {
+
+ level2Data.setLevel2Data(new SimpleData());
+
+ level2Data.getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1);
+
+ level2Data.getLevel2Data().setData(DynamicContentCoder.encode(content, DynamicContentCoder.dynamicContentDataFDC1));
+
+ }
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ @Override
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
+ this.getLevel2Data().setLevel2Data(dynamicData.getApiDataType());
+ }
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ @Override
+ public IUicDynamicContent getDynamicContent() {
+
+ if (this.getLevel2Data() == null ||
+ this.getLevel2Data().getLevel2Data() == null){
+ return null;
+ }
+
+ return DynamicContentCoder.decode(level2Data.getLevel2Data().getData());
+
+ }
+
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @return
+ * @return the byte[]
+ * @throws Exception
+ */
+ @Override
+ public void signLevel1(PrivateKey key) throws Exception {
+
+ signLevel1(key, null);
+
+ }
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param security provider - security provider that must be sued to create the signature
+ * @return
+ * @return the byte[]
+ * @throws Exception
+ */
+ @Override
+ public void signLevel1(PrivateKey key, Provider prov) throws Exception {
+
+ if (level2Data == null) return;
+
+ ILevel1Data level1Data = level2Data.getLevel1Data();
+
+ if (level1Data == null) return;
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg());
+ Signature sig = null;
+ if (prov != null) {
+ sig = Signature.getInstance(algo, prov);
+ } else {
+ sig = Signature.getInstance(algo);
+ }
+ sig.initSign(key);
+
+ byte[] data = DynamicFrameCoder.encodeLevel1(this);
+ sig.update(data);
+ level2Data.setLevel1Signature(sig.sign());
+ }
+
+ @Override
+ public byte[] getLevel1Signature() {
+ return getLevel2Data().getLevel1Signature();
+ }
+
+ @Override
+ public byte[] getLevel1DataBin() throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV1.encode(getLevel2Data().getLevel1Data());
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) {
+
+ return DynamicFrameCoderV2.encode(getLevel2Data().getLevel1Data());
+
+ }
+
+ throw new EncodingFormatException("Dynamic Header Version not supported");
+
+ }
+
+ @Override
+ public byte[] getLevel2DataBin() throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV1.encodeLevel2Data(getLevel2Data());
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) {
+
+ return DynamicFrameCoderV2.encodeLevel2Data(getLevel2Data());
+
+ }
+
+ throw new EncodingFormatException("Dynamic Header Version not supported");
+
+ }
+
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java
new file mode 100644
index 0000000..f42ff98
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java
@@ -0,0 +1,264 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+
+/**
+ * The Class SignedDataType.
+ */
+
+public class SimpleLevel1Data implements ILevel1Data {
+
+ /** The security provider */
+ public String securityProvider;
+
+
+ /** The key id. */
+ public Long keyId;
+
+
+ /** The data. */
+ public Collection<IData> dataList;
+
+ /**
+ * The key generator algorithms
+ * Object Identifier of the Algorithm
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ public String level1KeyAlg;
+
+ /** The level 2 key alg. */
+ public String level2KeyAlg;
+
+ /**
+ * The signing algorithm
+ * Object Identifier of the Algorithms
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ public String level1SigningAlg;
+
+ /** The level 2 signing alg. */
+ public String level2SigningAlg;
+
+
+ /** The level 2 public key. */
+ public byte[] level2publicKey;
+
+
+ public Date endOfBarcodeValidity = null;
+
+
+ public Long validityDuration = null;
+
+
+
+ /**
+ * Gets the security provider .
+ *
+ * @return the security provider
+ */
+ public String getSecurityProvider() {
+ return securityProvider;
+ }
+
+ /**
+ * Sets the security provider.
+ *
+ * in case the security provider code is encoded in IA5 this will return null
+ *
+ * @param securityProviderNum the new security provider
+ */
+ public void setSecurityProvider(String securityProvider) {
+ this.securityProvider = securityProvider;
+ }
+
+
+
+
+
+ /**
+ * Gets the key id.
+ *
+ * @return the key id
+ */
+ public Long getKeyId() {
+ return keyId;
+ }
+
+ /**
+ * Sets the key id.
+ *
+ * @param keyId the new key id
+ */
+ public void setKeyId(Long keyId) {
+ this.keyId = keyId;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public Collection<IData> getData() {
+ return dataList;
+ }
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(Collection<IData> data) {
+ this.dataList = data;
+ }
+
+ /**
+ * Gets the level 2 key alg.
+ *
+ * @return the level 2 key alg
+ */
+ public String getLevel2KeyAlg() {
+ return level2KeyAlg;
+ }
+
+ /**
+ * Sets the level 2 key alg.
+ *
+ * @param level2KeyAlg the new level 2 key alg
+ */
+ public void setLevel2KeyAlg(String level2KeyAlg) {
+ this.level2KeyAlg = level2KeyAlg;
+ }
+
+ /**
+ * Gets the level 1 signing alg.
+ *
+ * @return the level 1 signing alg
+ */
+ public String getLevel1SigningAlg() {
+ return level1SigningAlg;
+ }
+
+ /**
+ * Sets the level 1 signing alg.
+ *
+ * @param level1SigningAlg the new level 1 signing alg
+ */
+ public void setLevel1SigningAlg(String level1SigningAlg) {
+ this.level1SigningAlg = level1SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 signing alg.
+ *
+ * @return the level 2 signing alg
+ */
+ public String getLevel2SigningAlg() {
+ return level2SigningAlg;
+ }
+
+ /**
+ * Sets the level 2 signing alg.
+ *
+ * @param level2SigningAlg the new level 2 signing alg
+ */
+ public void setLevel2SigningAlg(String level2SigningAlg) {
+ this.level2SigningAlg = level2SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 public key.
+ *
+ * @return the level 2 public key
+ */
+ public byte[] getLevel2publicKey() {
+ return level2publicKey;
+ }
+
+ /**
+ * Sets the level 2 public key.
+ *
+ * @param level2publicKey the new level 2 public key
+ */
+ public void setLevel2publicKey(byte[] level2publicKey) {
+ this.level2publicKey = level2publicKey;
+ }
+
+
+
+ /**
+ * Gets the level 1 key alg.
+ *
+ * @return the level 1 key alg
+ */
+ public String getLevel1KeyAlg() {
+ return level1KeyAlg;
+ }
+
+ /**
+ * Sets the level 1 key alg.
+ *
+ * @param level1KeyAlg the new level 1 key alg
+ */
+ public void setLevel1KeyAlg(String level1KeyAlg) {
+ this.level1KeyAlg = level1KeyAlg;
+ }
+
+ /**
+ * Sets the end of validity date. The validity date has to be provided in UTC.
+ *
+ * @param date the new end of validity date
+ */
+ public void setEndOfBarcodeValidity(Date date){
+
+ endOfBarcodeValidity = date;
+
+
+ }
+
+ /**
+ * Gets the end of validity date.
+ *
+ * @return the end of validity date
+ */
+ public Date getEndOfBarcodeValidity() {
+
+ return endOfBarcodeValidity;
+ }
+
+ @Override
+ public void addData(IData data) {
+
+ if (dataList == null) {
+ dataList = new ArrayList<IData>();
+ }
+
+ dataList.add(data);
+
+ }
+
+ public Long getValidityDuration() {
+ return validityDuration;
+ }
+
+ public void setValidityDuration(Long validityDuration) {
+ this.validityDuration = validityDuration;
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java
new file mode 100644
index 0000000..17e71db
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java
@@ -0,0 +1,56 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+
+/**
+ * The Class DataType.
+ */
+public class SimpleLevel2Data implements ILevel2Data {
+
+ @FieldOrder(order = 0)
+ ILevel1Data level1Data;
+
+ /** The data. */
+ @FieldOrder(order = 1)
+ @Asn1Optional public byte[] level1Signature;
+
+ @FieldOrder(order = 2)
+ @Asn1Optional IData level2Data;
+
+
+ public ILevel1Data getLevel1Data() {
+ return level1Data;
+ }
+
+
+ public void setLevel1Data(ILevel1Data level1Data) {
+ this.level1Data = level1Data;
+ }
+
+
+ public byte[] getLevel1Signature() {
+ return level1Signature;
+ }
+
+ public byte[] getLevel1SignatureBytes() {
+ return level1Signature;
+ }
+
+
+ public void setLevel1Signature(byte[] level1Signature) {
+ this.level1Signature = level1Signature;
+ }
+
+
+ public IData getLevel2Data() {
+ return level2Data;
+ }
+
+
+ public void setLevel2Data(IData level2Data) {
+ this.level2Data = level2Data;
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/package.html b/src/main/java/org/uic/barcode/dynamicFrame/package.html
deleted file mode 100644
index dbe6c06..0000000
--- a/src/main/java/org/uic/barcode/dynamicFrame/package.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head></head>
-<body>
-
-<h1>drafted new header for dynamic content </h1>
-<p>Provides a decoding and encoding of the header data frame. (Draft for UIC IRS 90918-9).</p>
-</body>
-</html> \ No newline at end of file
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java
index 2ea63ca..e8cfc50 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java
@@ -1,6 +1,7 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v1;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.OctetString;
@@ -19,10 +20,12 @@ public class DataType {
* -- FCB2 FCB version 2
* -- RICS company code + ...
**/
+ @FieldOrder(order = 0)
@RestrictedString(CharacterRestriction.IA5String)
public String format;
/** The data. */
+ @FieldOrder(order = 1)
public OctetString data;
/**
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java
new file mode 100644
index 0000000..3bfcbf5
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java
@@ -0,0 +1,229 @@
+package org.uic.barcode.dynamicFrame.v1;
+
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.Signature;
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.utils.AlgorithmNameResolver;
+
+
+/**
+ * The DynamicHeader for bar codes
+ *
+ * Implementation of the Draft under discussion, not final.
+ */
+@Sequence
+public class DynamicFrame extends Object{
+
+ /**
+ * Instantiates a new dynamic frame.
+ */
+ public DynamicFrame() {}
+
+ /** The format. */
+ @FieldOrder(order = 0)
+ @RestrictedString(CharacterRestriction.IA5String)
+ public String format;
+
+ /** The level 2 signed data. */
+ /*level 2 data*/
+ @FieldOrder(order = 1)
+ Level2DataType level2SignedData;
+
+
+ /** The signature of level 2 data. */
+ @FieldOrder(order = 2)
+ @Asn1Optional public OctetString level2Signature;
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ public Level2DataType getLevel2SignedData() {
+ return level2SignedData;
+ }
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2SignedData the new level 2 signed data
+ */
+ public void setLevel2SignedData(Level2DataType level2SignedData) {
+ this.level2SignedData = level2SignedData;
+ }
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ public OctetString getLevel2Signature() {
+ return level2Signature;
+ }
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ public void setLevel2Signature(OctetString level2Signature) {
+ this.level2Signature = level2Signature;
+ }
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+ /**
+ * Decode.
+ *
+ * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
+ *
+ * @param bytes the bytes
+ * @return the dynamic header
+ */
+ public static DynamicFrame decode(byte[] bytes) {
+ return UperEncoder.decode(bytes, DynamicFrame.class);
+ }
+
+ /**
+ * Sign level 2 data without a specific security provider.
+ *
+ * @param key the key
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key) throws Exception {
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ Signature sig = Signature.getInstance(algo);
+ sig.initSign(key);
+ byte[] data = level2SignedData.encode();
+ sig.update(data);
+ byte[] signature = sig.sign();
+ this.level2Signature = new OctetString(signature);
+
+ }
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the security Provider
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key, Provider prov) throws Exception {
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ Signature sig = Signature.getInstance(algo,prov);
+ sig.initSign(key);
+ byte[] data = level2SignedData.encode();
+ sig.update(data);
+ this.level2Signature = new OctetString(sig.sign());
+
+ }
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException {
+
+
+ level2SignedData.setLevel2Data(new DataType());
+
+ level2SignedData.getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1);
+
+ level2SignedData.getLevel2Data().setByteData(DynamicContentCoder.encode(content, DynamicContentCoder.dynamicContentDataFDC1));
+
+ }
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
+ DataType dt = new DataType();
+ dt.setByteData(dynamicData.getDataType().getByteData());
+ dt.setFormat(dynamicData.getDataType().getFormat());
+ level2SignedData.setLevel2Data(dt);
+ }
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ public IUicDynamicContent getDynamicContent() {
+
+ if (level2SignedData == null ||
+ level2SignedData.getLevel2Data() == null){
+ return null;
+ }
+
+ return DynamicContentCoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData());
+
+ }
+
+ /**
+ * Gets the dynamic data FDC 1.
+ *
+ * @return the dynamic data FDC 1
+ */
+ public UicDynamicContentDataFDC1 getDynamicDataFDC1() {
+
+ if (level2SignedData == null ||
+ level2SignedData.getLevel2Data() == null){
+ return null;
+ }
+
+ if ( UicDynamicContentDataFDC1.getFormat().equals(this.getLevel2SignedData().getLevel2Data().getFormat())) {
+ return UperEncoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData(), UicDynamicContentDataFDC1.class);
+ }
+ return null;
+
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java
new file mode 100644
index 0000000..71de58e
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java
@@ -0,0 +1,221 @@
+package org.uic.barcode.dynamicFrame.v1;
+
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrame;
+import org.uic.barcode.dynamicFrame.v1.Level1DataType;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.ILevel2Data;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel2Data;
+
+public class DynamicFrameCoderV1 {
+
+ public static void decode(IDynamicFrame frame, byte[] bytes) {
+
+ DynamicFrame asnFrame = UperEncoder.decode(bytes,DynamicFrame.class);
+
+ frame.setFormat(asnFrame.getFormat());
+
+ if (asnFrame.getLevel2Signature() != null) {
+ frame.setLevel2Signature(asnFrame.getLevel2Signature().toByteArray());
+ }
+
+ if (asnFrame.getLevel2SignedData() != null) {
+ frame.setLevel2Data(new SimpleLevel2Data());
+ populateApi(frame.getLevel2Data(), asnFrame.getLevel2SignedData());
+ }
+
+ }
+
+ public static ILevel1Data decodeLevel1(byte[] bytes) {
+
+ Level1DataType asnData = UperEncoder.decode(bytes,Level1DataType.class);
+
+ return populateApi(asnData);
+
+ }
+
+ private static void populateApi(ILevel2Data level2, Level2DataType asnLevel2) {
+
+ if (asnLevel2 == null) return;
+
+
+ level2.setLevel1Signature(asnLevel2.getLevel1SignatureBytes());
+
+ if (asnLevel2.getLevel1Data() != null) {
+ level2.setLevel1Data(new SimpleLevel1Data());
+ level2.setLevel1Data(populateApi(asnLevel2.getLevel1Data()));
+ }
+
+ if (asnLevel2.getLevel2Data() != null) {
+ level2.setLevel2Data(new SimpleData());
+ level2.setLevel2Data(populateApi(asnLevel2.getLevel2Data()));
+ }
+ }
+
+ private static IData populateApi(DataType asnData) {
+
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ return data;
+ }
+
+ private static ILevel1Data populateApi(Level1DataType asnLevel1) {
+
+ ILevel1Data level1 = new SimpleLevel1Data();
+
+ level1.setKeyId(asnLevel1.getKeyId());
+ level1.setSecurityProvider(asnLevel1.getSecurityProvider());
+ level1.setLevel1KeyAlg(asnLevel1.getLevel1KeyAlg());
+ level1.setLevel1SigningAlg(asnLevel1.getLevel1SigningAlg());
+ level1.setLevel2KeyAlg(asnLevel1.getLevel2KeyAlg());
+ level1.setLevel2SigningAlg(asnLevel1.getLevel2SigningAlg());
+ if (asnLevel1.getLevel2publicKey() != null) {
+ level1.setLevel2publicKey(asnLevel1.getLevel2publicKey().toByteArray());
+ }
+
+ if (asnLevel1.getData() != null && !asnLevel1.getData().isEmpty()) {
+
+ for (DataType asnData : asnLevel1.getData()) {
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ level1.addData(data);
+ }
+ }
+
+ return level1;
+ }
+
+ public static byte[] encode(IDynamicFrame dynamicFrame) throws EncodingFormatException {
+
+ DynamicFrame asnDynamicFrame = populateAsn(dynamicFrame);
+
+ return UperEncoder.encode(asnDynamicFrame);
+
+ }
+
+
+ public static byte[] encode(ILevel1Data level1Data) throws EncodingFormatException {
+
+ Level1DataType asn = populateAsn(level1Data);
+
+ return UperEncoder.encode(asn);
+ }
+
+
+ public static byte[] getEncoded(String path, byte[] data) {
+
+ if (path.endsWith("Level1Data")){
+ return UperEncoder.extract(data, "Level1DataType" ,DynamicFrame.class );
+ } else if (path.endsWith("Level2Data")){
+ return UperEncoder.extract(data, "Level2DataType" ,DynamicFrame.class );
+ }
+
+ return null;
+ }
+
+
+ public static byte[] encodeLevel2Data(ILevel2Data level2Data) throws EncodingFormatException {
+
+ Level2DataType asn = populateAsn(level2Data);
+
+ return UperEncoder.encode(asn);
+ }
+
+ private static DynamicFrame populateAsn(IDynamicFrame frame) throws EncodingFormatException {
+
+ DynamicFrame asnFrame = new DynamicFrame();
+
+ asnFrame.setFormat(frame.getFormat());
+
+ if (frame.getLevel2Signature() != null && frame.getLevel2Signature().length > 0) {
+ asnFrame.setLevel2Signature(new OctetString(frame.getLevel2Signature()));
+ }
+
+ Level2DataType asnLevel2 = populateAsn(frame.getLevel2Data());
+ if (asnLevel2 != null) {
+ asnFrame.setLevel2SignedData(asnLevel2);
+ }
+
+ return asnFrame;
+ }
+
+
+ private static Level2DataType populateAsn(ILevel2Data level2) throws EncodingFormatException {
+
+ Level2DataType asnLevel2 = new Level2DataType();
+
+ asnLevel2.setLevel1Signature(level2.getLevel1Signature());
+
+ Level1DataType asnLevel1 = populateAsn(level2.getLevel1Data());
+
+ asnLevel2.setLevel1Data(asnLevel1);
+
+ if (level2.getLevel2Data() != null) {
+ DataType asnData = new DataType();
+ asnData.setFormat(level2.getLevel2Data().getFormat());
+ asnData.setData(new OctetString(level2.getLevel2Data().getData()));
+ asnLevel2.setLevel2Data(asnData);
+ }
+
+ return asnLevel2;
+ }
+
+ private static Level1DataType populateAsn(ILevel1Data level1) throws EncodingFormatException {
+
+ Level1DataType asnLevel1 = new Level1DataType();
+
+ asnLevel1.setSecurityProvider(level1.getSecurityProvider());
+
+ asnLevel1.setKeyId(level1.getKeyId());
+
+ asnLevel1.setLevel1KeyAlg(level1.getLevel1KeyAlg());
+
+ asnLevel1.setLevel1SigningAlg(level1.getLevel1SigningAlg());
+
+ asnLevel1.setLevel2KeyAlg(level1.getLevel2KeyAlg());
+
+ if (level1.getLevel2publicKey() != null && level1.getLevel2publicKey().length > 0) {
+ asnLevel1.setLevel2publicKey(new OctetString(level1.getLevel2publicKey()));
+ }
+
+ asnLevel1.setLevel2SigningAlg(level1.getLevel2SigningAlg());
+
+ if (level1.getData() != null && !level1.getData().isEmpty()) {
+
+ asnLevel1.setData(new SequenceOfDataType());
+
+ for (IData data : level1.getData()) {
+
+ DataType asnData = new DataType();
+ asnData.setByteData(data.getData());
+ asnData.setFormat(data.getFormat());
+ asnLevel1.getData().add(asnData);
+
+ }
+
+ }
+
+ return asnLevel1;
+ }
+
+
+ public static byte[] encodeLevel1(IDynamicFrame frame) throws EncodingFormatException {
+
+ Level1DataType asnLevel1Data = populateAsn(frame.getLevel2Data().getLevel1Data());
+
+ return UperEncoder.encode(asnLevel1Data);
+
+ }
+
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java
index 958cafc..5104c50 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v1;
import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java
new file mode 100644
index 0000000..7813cf2
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java
@@ -0,0 +1,74 @@
+package org.uic.barcode.dynamicFrame.v1;
+
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class DataType.
+ */
+@Sequence
+public class Level2DataType {
+
+ @FieldOrder(order = 0)
+ Level1DataType level1Data;
+
+ /** The data. */
+ @FieldOrder(order = 1)
+ @Asn1Optional public OctetString level1Signature;
+
+ @FieldOrder(order = 2)
+ @Asn1Optional DataType level2Data;
+
+
+ public Level1DataType getLevel1Data() {
+ return level1Data;
+ }
+
+
+ public void setLevel1Data(Level1DataType level1Data) {
+ this.level1Data = level1Data;
+ }
+
+
+ public OctetString getLevel1Signature() {
+ return level1Signature;
+ }
+
+ public byte[] getLevel1SignatureBytes() {
+ return level1Signature.toByteArray();
+ }
+
+ public void setLevel1Signature(OctetString level1Signature) {
+ this.level1Signature = level1Signature;
+ }
+
+ public void setLevel1Signature(byte[] level1Signature) {
+ this.level1Signature = new OctetString(level1Signature);
+ }
+
+
+ public DataType getLevel2Data() {
+ return level2Data;
+ }
+
+
+ public void setLevel2Data(DataType level2Data) {
+ this.level2Data = level2Data;
+ }
+
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java
index b5c130e..be0bf95 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v1;
import java.util.Collection;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java
new file mode 100644
index 0000000..beceda9
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java
@@ -0,0 +1,96 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class DataType.
+ */
+@Sequence
+public class DataType {
+
+
+ /** The data format.
+ *
+ * -- FCB1 FCB version 1
+ * -- FCB2 FCB version 2
+ * -- RICS company code + ...
+ **/
+ @RestrictedString(CharacterRestriction.IA5String)
+ @FieldOrder(order = 0)
+ public String format;
+
+ /** The data. */
+ @FieldOrder(order = 1)
+ public OctetString data;
+
+ /**
+ * Gets the data format.
+ *
+ * @return the data format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the data format.
+ *
+ * @param dataFormat the new data format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public OctetString getData() {
+ return data;
+ }
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(OctetString data) {
+ this.data = data;
+ }
+
+ /**
+ * Gets the data as byte array.
+ *
+ * @return the data
+ */
+ public byte[] getByteData() {
+ return data.toByteArray();
+ }
+
+ /**
+ * Sets the data from a byte array.
+ *
+ * @param data the new data
+ */
+ public void setByteData(byte[] data) {
+ this.data = new OctetString(data);
+ }
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java
new file mode 100644
index 0000000..55af066
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java
@@ -0,0 +1,230 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.Signature;
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.utils.AlgorithmNameResolver;
+
+
+/**
+ * The DynamicHeader for bar codes
+ *
+ * Implementation of the Draft under discussion, not final.
+ */
+@Sequence
+public class DynamicFrame extends Object{
+
+ /**
+ * Instantiates a new dynamic frame.
+ */
+ public DynamicFrame() {}
+
+ /** The format. */
+ @FieldOrder(order = 0)
+ @RestrictedString(CharacterRestriction.IA5String)
+ public String format;
+
+ /** The level 2 signed data. */
+ /*level 2 data*/
+ @FieldOrder(order = 1)
+ Level2DataType level2SignedData;
+
+
+ /** The signature of level 2 data. */
+ @FieldOrder(order = 2)
+ @Asn1Optional public OctetString level2Signature;
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ public Level2DataType getLevel2SignedData() {
+ return level2SignedData;
+ }
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2SignedData the new level 2 signed data
+ */
+ public void setLevel2SignedData(Level2DataType level2SignedData) {
+ this.level2SignedData = level2SignedData;
+ }
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ public OctetString getLevel2Signature() {
+ return level2Signature;
+ }
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ public void setLevel2Signature(OctetString level2Signature) {
+ this.level2Signature = level2Signature;
+ }
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+ /**
+ * Decode.
+ *
+ * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
+ *
+ * @param bytes the bytes
+ * @return the dynamic header
+ */
+ public static DynamicFrame decode(byte[] bytes) {
+ return UperEncoder.decode(bytes, DynamicFrame.class);
+ }
+
+
+ /**
+ * Sign level 2 data without a specific security provider.
+ *
+ * @param key the key
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key) throws Exception {
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ Signature sig = Signature.getInstance(algo);
+ sig.initSign(key);
+ byte[] data = level2SignedData.encode();
+ sig.update(data);
+ byte[] signature = sig.sign();
+ this.level2Signature = new OctetString(signature);
+
+ }
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the security Provider
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key, Provider prov) throws Exception {
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ Signature sig = Signature.getInstance(algo,prov);
+ sig.initSign(key);
+ byte[] data = level2SignedData.encode();
+ sig.update(data);
+ this.level2Signature = new OctetString(sig.sign());
+
+ }
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException {
+
+
+ this.getLevel2SignedData().setLevel2Data(new DataType());
+
+ this.getLevel2SignedData().getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1);
+
+ this.getLevel2SignedData().getLevel2Data().setByteData(DynamicContentCoder.encode(content, DynamicContentCoder.dynamicContentDataFDC1));
+
+ }
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
+ DataType dt = new DataType();
+ dt.setByteData(dynamicData.getDataType().getByteData());
+ dt.setFormat(dynamicData.getDataType().getFormat());
+ level2SignedData.setLevel2Data(dt);
+ }
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ public IUicDynamicContent getDynamicContent() {
+
+ if (this.getLevel2SignedData() == null ||
+ this.getLevel2SignedData().getLevel2Data() == null){
+ return null;
+ }
+
+ return DynamicContentCoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData());
+
+ }
+
+ /**
+ * Gets the dynamic data FDC 1.
+ *
+ * @return the dynamic data FDC 1
+ */
+ public UicDynamicContentDataFDC1 getDynamicDataFDC1() {
+
+ if (this.getLevel2SignedData() == null ||
+ this.getLevel2SignedData().getLevel2Data() == null){
+ return null;
+ }
+
+ if ( UicDynamicContentDataFDC1.getFormat().equals(this.getLevel2SignedData().getLevel2Data().getFormat())) {
+ return UperEncoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData(), UicDynamicContentDataFDC1.class);
+ }
+ return null;
+
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java
new file mode 100644
index 0000000..5d980dd
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java
@@ -0,0 +1,235 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicFrame.v2.DynamicFrame;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.ILevel2Data;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel2Data;
+import org.uic.barcode.dynamicFrame.v2.Level2DataType;
+import org.uic.barcode.dynamicFrame.v2.DataType;
+import org.uic.barcode.dynamicFrame.v2.Level1DataType;
+import org.uic.barcode.dynamicFrame.v2.SequenceOfDataType;
+import org.uic.barcode.ticket.EncodingFormatException;
+
+public class DynamicFrameCoderV2 {
+
+ public static void decode(IDynamicFrame frame, byte[] bytes) {
+
+ DynamicFrame asnFrame = UperEncoder.decode(bytes,DynamicFrame.class);
+
+ frame.setFormat(asnFrame.getFormat());
+
+ if (asnFrame.getLevel2Signature() != null) {
+ frame.setLevel2Signature(asnFrame.getLevel2Signature().toByteArray());
+ }
+
+ if (asnFrame.getLevel2SignedData() != null) {
+ frame.setLevel2Data(new SimpleLevel2Data());
+ populateApi(frame.getLevel2Data(), asnFrame.getLevel2SignedData());
+ }
+
+ }
+
+ public static ILevel1Data decodeLevel1(byte[] bytes) {
+
+ Level1DataType asnData = UperEncoder.decode(bytes,Level1DataType.class);
+
+ return populateApi(asnData);
+
+ }
+
+
+ private static void populateApi(ILevel2Data level2, Level2DataType asnLevel2) {
+
+ if (asnLevel2 == null) return;
+
+ level2.setLevel1Signature(asnLevel2.getLevel1SignatureBytes());
+
+ if (asnLevel2.getLevel1Data() != null) {
+ level2.setLevel1Data(new SimpleLevel1Data());
+ level2.setLevel1Data(populateApi(asnLevel2.getLevel1Data()));
+ }
+
+ if (asnLevel2.getLevel2Data() != null) {
+ level2.setLevel2Data(new SimpleData());
+ level2.setLevel2Data(populateApi(asnLevel2.getLevel2Data()));
+ }
+
+ }
+
+ private static IData populateApi(DataType asnData) {
+
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ return data;
+ }
+
+ private static ILevel1Data populateApi(Level1DataType asnLevel1) {
+
+ ILevel1Data level1 = new SimpleLevel1Data();
+
+ level1.setKeyId(asnLevel1.getKeyId());
+ level1.setSecurityProvider(asnLevel1.getSecurityProvider());
+ level1.setLevel1KeyAlg(asnLevel1.getLevel1KeyAlg());
+ level1.setLevel1SigningAlg(asnLevel1.getLevel1SigningAlg());
+ level1.setLevel2KeyAlg(asnLevel1.getLevel2KeyAlg());
+ level1.setLevel2SigningAlg(asnLevel1.getLevel2SigningAlg());
+ if (asnLevel1.getLevel2publicKey() != null) {
+ level1.setLevel2publicKey(asnLevel1.getLevel2publicKey().toByteArray());
+ }
+
+ if (asnLevel1.getData() != null && !asnLevel1.getData().isEmpty()) {
+
+ for (DataType asnData : asnLevel1.getData()) {
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ level1.addData(data);
+ }
+ }
+
+ if (asnLevel1.getEndOfValidityDate() != null) {
+ level1.setEndOfBarcodeValidity(asnLevel1.getEndOfValidityDate());
+ }
+
+ level1.setValidityDuration(asnLevel1.getValidityDuration());
+
+ return level1;
+ }
+
+ public static byte[] encode(IDynamicFrame dynamicFrame) throws EncodingFormatException {
+
+ DynamicFrame asnDynamicFrame = populateAsn(dynamicFrame);
+
+ return UperEncoder.encode(asnDynamicFrame);
+
+ }
+
+
+
+ public static byte[] encode(ILevel1Data level1Data) throws EncodingFormatException {
+
+ Level1DataType asn = populateAsn(level1Data);
+
+ return UperEncoder.encode(asn);
+ }
+
+ public static byte[] encodeLevel2Data(ILevel2Data level2SignedData) throws EncodingFormatException {
+
+ Level2DataType asn = populateAsn(level2SignedData);
+
+ return UperEncoder.encode(asn);
+ }
+
+ private static DynamicFrame populateAsn(IDynamicFrame frame) throws EncodingFormatException {
+
+ DynamicFrame asnFrame = new DynamicFrame();
+
+ asnFrame.setFormat(frame.getFormat());
+
+ if (frame.getLevel2Signature() != null && frame.getLevel2Signature().length > 0) {
+ asnFrame.setLevel2Signature(new OctetString(frame.getLevel2Signature()));
+ }
+
+ Level2DataType asnLevel2 = populateAsn(frame.getLevel2Data());
+ if (asnLevel2 != null) {
+ asnFrame.setLevel2SignedData(asnLevel2);
+ }
+
+ return asnFrame;
+ }
+
+
+ private static Level2DataType populateAsn(ILevel2Data level2) throws EncodingFormatException {
+
+ Level2DataType asnLevel2 = new Level2DataType();
+
+ asnLevel2.setLevel1Signature(level2.getLevel1Signature());
+
+ Level1DataType asnLevel1 = populateAsn(level2.getLevel1Data());
+
+ asnLevel2.setLevel1Data(asnLevel1);
+
+ if (level2.getLevel2Data() != null) {
+ DataType data2 = new DataType();
+ data2.setFormat(level2.getLevel2Data().getFormat());
+ data2.setData(new OctetString(level2.getLevel2Data().getData()));
+ asnLevel2.setLevel2Data(data2);
+ }
+
+
+
+ return asnLevel2;
+ }
+
+ private static Level1DataType populateAsn(ILevel1Data level1) throws EncodingFormatException {
+
+ Level1DataType asnLevel1 = new Level1DataType();
+
+ asnLevel1.setSecurityProvider(level1.getSecurityProvider());
+
+ asnLevel1.setKeyId(level1.getKeyId());
+
+ asnLevel1.setLevel1KeyAlg(level1.getLevel1KeyAlg());
+
+ asnLevel1.setLevel1SigningAlg(level1.getLevel1SigningAlg());
+
+ asnLevel1.setLevel2KeyAlg(level1.getLevel2KeyAlg());
+
+ if (level1.getLevel2publicKey() != null && level1.getLevel2publicKey().length > 0) {
+ asnLevel1.setLevel2publicKey(new OctetString(level1.getLevel2publicKey()));
+ }
+
+ asnLevel1.setLevel2SigningAlg(level1.getLevel2SigningAlg());
+
+ if (level1.getData() != null && !level1.getData().isEmpty()) {
+
+ asnLevel1.setData(new SequenceOfDataType());
+
+ for (IData data : level1.getData()) {
+
+ DataType asnData = new DataType();
+ asnData.setByteData(data.getData());
+ asnData.setFormat(data.getFormat());
+ asnLevel1.getData().add(asnData);
+
+ }
+
+ }
+
+ asnLevel1.setEndOfValidityDate(level1.getEndOfBarcodeValidity());
+
+ asnLevel1.setValidityDuration(level1.getValidityDuration());
+
+
+ return asnLevel1;
+ }
+
+ public static byte[] getEncoded(String path, byte[] data) {
+
+ if (path.endsWith("Level1Data")){
+ return UperEncoder.extract(data, "Level1DataType" ,DynamicFrame.class );
+ } else if (path.endsWith("Level2Data")){
+ return UperEncoder.extract(data, "Level2DataType" ,DynamicFrame.class );
+ }
+
+ return null;
+ }
+
+ public static byte[] encodeLevel1(IDynamicFrame frame) throws EncodingFormatException {
+
+ Level1DataType asnLevel1Data = populateAsn(frame.getLevel2Data().getLevel1Data());
+
+ return UperEncoder.encode(asnLevel1Data);
+
+ }
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java
new file mode 100644
index 0000000..b42e9dc
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java
@@ -0,0 +1,392 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.IntRange;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.utils.UicEncoderUtils;
+
+/**
+ * The Class SignedDataType.
+ */
+@Sequence
+public class Level1DataType {
+
+ /**
+ * The security provider
+ * numeric codes 1 ...32000
+ *
+ * */
+ @FieldOrder(order = 0)
+ @IntRange(minValue=1,maxValue=32000)
+ @Asn1Optional public Long securityProviderNum;
+
+ /** The security provider alphanumeric codes. */
+ @FieldOrder(order = 1)
+ @RestrictedString(CharacterRestriction.IA5String)
+ @Asn1Optional public String securityProviderIA5;
+
+
+ /** The key id. */
+ @FieldOrder(order = 2)
+ @IntRange(minValue=0,maxValue=99999)
+ @Asn1Optional public Long keyId;
+
+
+ /** The data. */
+ @FieldOrder(order = 3)
+ public SequenceOfDataType data;
+
+ /**
+ * The key generator algorithms
+ * Object Identifier of the Algorithm
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ @FieldOrder(order = 4)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level1KeyAlg;
+
+ /** The level 2 key alg. */
+ @FieldOrder(order = 5)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level2KeyAlg;
+
+ /**
+ * The signing algorithm
+ * Object Identifier of the Algorithms
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ @FieldOrder(order = 6)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level1SigningAlg;
+
+ /** The level 2 signing alg. */
+ @FieldOrder(order = 7)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level2SigningAlg;
+
+
+ /** The level 2 public key. */
+ @FieldOrder(order = 8)
+ @Asn1Optional public OctetString level2publicKey;
+
+
+ /** The End of validity year. */
+ @FieldOrder(order = 9)
+ @IntRange(minValue=2016,maxValue=2269)
+ @Asn1Optional public Long endOfValidityYear;
+
+ /** The End of validity day. */
+ @FieldOrder(order = 10)
+ @IntRange(minValue=1,maxValue=366)
+ @Asn1Optional public Long endOfValidityDay;
+
+ /** The End of validity time. */
+ @FieldOrder(order = 11)
+ @IntRange(minValue=0,maxValue=1439)
+ @Asn1Optional public Long endOfValidityTime;
+
+ /** The validity duration in seconds. */
+ @FieldOrder(order = 12)
+ @IntRange(minValue=1,maxValue=3600)
+ @Asn1Optional public Long validityDuration;
+
+
+
+
+ /**
+ * Gets the security provider num.
+ *
+ * @return the security provider num
+ */
+ public Long getSecurityProviderNum() {
+ return securityProviderNum;
+ }
+
+ /**
+ * Sets the security provider num.
+ *
+ * in case the security provider code is encoded in IA5 this will return null
+ *
+ * @param securityProviderNum the new security provider num
+ */
+ public void setSecurityProviderNum(Long securityProviderNum) {
+ this.securityProviderNum = securityProviderNum;
+ }
+
+ /**
+ * Gets the security provider IA5.
+ *
+ * in case the security provider code is encoded numerically this will return null
+ *
+ * @return the security provider IA5
+ */
+ public String getSecurityProviderIA5() {
+ return securityProviderIA5;
+ }
+
+ /**
+ * Sets the security provider
+ *
+ * The security provider code must use the IA5 Alphabet .
+ *
+ * @param securityProvider the new security provider
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void setSecurityProvider(String securityProvider) throws EncodingFormatException {
+ this.securityProviderNum = UicEncoderUtils.getNum(securityProvider);
+ this.securityProviderIA5 = UicEncoderUtils.getIA5NonNum(securityProvider);
+ }
+
+
+ /**
+ * Gets the security provider.
+ *
+ * @return the security provider
+ */
+ public String getSecurityProvider() {
+ return UicEncoderUtils.mapToString(this.securityProviderNum, this.securityProviderIA5);
+ }
+
+
+ /**
+ * Sets the security provider IA 5.
+ *
+ * @param securityProviderIA5 the new security provider IA 5
+ */
+ public void setSecurityProviderIA5(String securityProviderIA5) {
+ this.securityProviderIA5 = securityProviderIA5;
+ }
+
+ /**
+ * Gets the key id.
+ *
+ * @return the key id
+ */
+ public Long getKeyId() {
+ return keyId;
+ }
+
+ /**
+ * Sets the key id.
+ *
+ * @param keyId the new key id
+ */
+ public void setKeyId(Long keyId) {
+ this.keyId = keyId;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public SequenceOfDataType getData() {
+ return data;
+ }
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(SequenceOfDataType data) {
+ this.data = data;
+ }
+
+ /**
+ * Gets the level 2 key alg.
+ *
+ * @return the level 2 key alg
+ */
+ public String getLevel2KeyAlg() {
+ return level2KeyAlg;
+ }
+
+ /**
+ * Sets the level 2 key alg.
+ *
+ * @param level2KeyAlg the new level 2 key alg
+ */
+ public void setLevel2KeyAlg(String level2KeyAlg) {
+ this.level2KeyAlg = level2KeyAlg;
+ }
+
+ /**
+ * Gets the level 1 signing alg.
+ *
+ * @return the level 1 signing alg
+ */
+ public String getLevel1SigningAlg() {
+ return level1SigningAlg;
+ }
+
+ /**
+ * Sets the level 1 signing alg.
+ *
+ * @param level1SigningAlg the new level 1 signing alg
+ */
+ public void setLevel1SigningAlg(String level1SigningAlg) {
+ this.level1SigningAlg = level1SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 signing alg.
+ *
+ * @return the level 2 signing alg
+ */
+ public String getLevel2SigningAlg() {
+ return level2SigningAlg;
+ }
+
+ /**
+ * Sets the level 2 signing alg.
+ *
+ * @param level2SigningAlg the new level 2 signing alg
+ */
+ public void setLevel2SigningAlg(String level2SigningAlg) {
+ this.level2SigningAlg = level2SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 public key.
+ *
+ * @return the level 2 public key
+ */
+ public OctetString getLevel2publicKey() {
+ return level2publicKey;
+ }
+
+ /**
+ * Sets the level 2 public key.
+ *
+ * @param level2publicKey the new level 2 public key
+ */
+ public void setLevel2publicKey(OctetString level2publicKey) {
+ this.level2publicKey = level2publicKey;
+ }
+
+
+
+ /**
+ * Gets the level 1 key alg.
+ *
+ * @return the level 1 key alg
+ */
+ public String getLevel1KeyAlg() {
+ return level1KeyAlg;
+ }
+
+ /**
+ * Sets the level 1 key alg.
+ *
+ * @param level1KeyAlg the new level 1 key alg
+ */
+ public void setLevel1KeyAlg(String level1KeyAlg) {
+ this.level1KeyAlg = level1KeyAlg;
+ }
+
+ /**
+ * Sets the end of validity date.
+ * @param date the new end of validity date
+ */
+ public void setEndOfValidityDate(Date date){
+
+ if (date == null) return;
+
+ TimeZone local = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+
+ this.endOfValidityYear = new Long( cal.get(Calendar.YEAR));
+ this.endOfValidityDay = new Long (cal.get(Calendar.DAY_OF_YEAR));
+ int time = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE);
+ if (time >= 0) {
+ this.endOfValidityTime = new Long (time );
+ }
+ TimeZone.setDefault(local);
+
+ }
+
+ /**
+ * Gets the end of validity date.
+ *
+ * @return the end of validity date
+ */
+ public Date getEndOfValidityDate() {
+
+ if (this.endOfValidityYear == null || this.endOfValidityDay == null) return null;
+
+ TimeZone local = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.setTimeZone(TimeZone.getTimeZone("UTC"));
+ cal.set(Calendar.YEAR, this.endOfValidityYear.intValue());
+ cal.set(Calendar.DAY_OF_YEAR, this.endOfValidityDay.intValue());
+
+ if (this.endOfValidityTime != null) {
+
+ int hours = this.endOfValidityTime.intValue() / 60;
+ int minutes = this.endOfValidityTime.intValue() % 60;
+ cal.set(Calendar.HOUR_OF_DAY, hours);
+ cal.set(Calendar.MINUTE,minutes);
+
+ }
+
+ Date d = cal.getTime();
+
+ TimeZone.setDefault(local);
+
+ return d;
+ }
+
+
+
+ public Long getValidityDuration() {
+ return validityDuration;
+ }
+
+ public void setValidityDuration(Long validityDuration) {
+ this.validityDuration = validityDuration;
+ }
+
+ /**
+ * Gets the data for signature.
+ *
+ * The byte array containing the ASN.1 PER UNALIGNED encoded data of the DataBlock
+ *
+ *
+ * @return the data for signature
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+
+ }
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java
index 8c3cd60..cd0800e 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v2;
import java.security.PrivateKey;
import java.security.Provider;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java
new file mode 100644
index 0000000..fc76776
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java
@@ -0,0 +1,25 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+
+import java.util.Collection;
+
+import org.uic.barcode.asn1.datatypes.Asn1SequenceOf;
+
+/**
+ * The Class SequenceOfDataType.
+ */
+public class SequenceOfDataType extends Asn1SequenceOf<DataType>{
+
+ /**
+ * Instantiates a new sequence of data type.
+ */
+ public SequenceOfDataType() { super(); }
+
+ /**
+ * Instantiates a new sequence of data type.
+ *
+ * @param coll the coll
+ */
+ public SequenceOfDataType(Collection<DataType> coll) { super(coll); }
+
+}
diff --git a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java
index 4491358..a3154f3 100644
--- a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java
+++ b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java
@@ -24,6 +24,26 @@ public class AlgorithmNameResolver {
}
+ public static String getSignatureAlgorithmName (String oid, Provider provider) throws Exception {
+
+ if (provider != null) {
+ Service service = provider.getService(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,oid);
+ return service.getAlgorithm();
+ }
+
+
+ Provider[] provs = Security.getProviders();
+ for (Provider prov : provs) {
+ Service service = prov.getService(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,oid);
+ if (service != null) {
+ return service.getAlgorithm();
+ }
+ }
+ return null;
+
+ }
+
+
public static String getName (String type, String oid) throws Exception {
Provider[] provs = Security.getProviders();
@@ -45,9 +65,22 @@ public class AlgorithmNameResolver {
}
- public static String getName(String type, String oid, Provider prov) throws Exception {
+ public static String getName(String type, String oid, Provider provider) throws Exception {
+
+ Service service = null;
+ if (provider == null) {
+
+ Provider[] provs = Security.getProviders();
+ for (Provider prov : provs) {
+ service = prov.getService(type,oid);
+ }
+
+ } else {
+ service = provider.getService(type,oid);
+ }
+
- Service service = prov.getService(type,oid);
+
if (service != null) {
return service.getAlgorithm();
}
diff --git a/src/test/java/org/uic/barcode/asn1/test/UperEncodeFieldOrderTest.java b/src/test/java/org/uic/barcode/asn1/test/UperEncodeFieldOrderTest.java
index 5a23f24..d86b4cd 100644
--- a/src/test/java/org/uic/barcode/asn1/test/UperEncodeFieldOrderTest.java
+++ b/src/test/java/org/uic/barcode/asn1/test/UperEncodeFieldOrderTest.java
@@ -2,8 +2,6 @@ package org.uic.barcode.asn1.test;
import static org.junit.Assert.assertEquals;
-import java.util.logging.Level;
-
import org.junit.Test;
import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
diff --git a/src/test/java/org/uic/barcode/asn1/test/UperEncodeIntegerExtensionTest.java b/src/test/java/org/uic/barcode/asn1/test/UperEncodeIntegerExtensionTest.java
index d0acd20..acec756 100644
--- a/src/test/java/org/uic/barcode/asn1/test/UperEncodeIntegerExtensionTest.java
+++ b/src/test/java/org/uic/barcode/asn1/test/UperEncodeIntegerExtensionTest.java
@@ -2,8 +2,6 @@ package org.uic.barcode.asn1.test;
import static org.junit.Assert.assertEquals;
-import java.util.logging.Level;
-
import org.junit.Test;
import org.uic.barcode.asn1.datatypes.Asn1BigInteger;
import org.uic.barcode.asn1.datatypes.FieldOrder;
diff --git a/src/test/java/org/uic/barcode/asn1/test/UperEncodeSequenceOfStringTest.java b/src/test/java/org/uic/barcode/asn1/test/UperEncodeSequenceOfStringTest.java
index f8eccc6..f3bff6d 100644
--- a/src/test/java/org/uic/barcode/asn1/test/UperEncodeSequenceOfStringTest.java
+++ b/src/test/java/org/uic/barcode/asn1/test/UperEncodeSequenceOfStringTest.java
@@ -5,9 +5,7 @@ import static org.junit.Assert.assertEquals;
import java.util.logging.Level;
import org.junit.Test;
-import org.uic.barcode.asn1.datatypes.CharacterRestriction;
import org.uic.barcode.asn1.datatypes.FieldOrder;
-import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5;
import org.uic.barcode.asn1.uper.UperEncoder;
diff --git a/src/test/java/org/uic/barcode/test/AsnLevelDynamicContentTest.java b/src/test/java/org/uic/barcode/test/AsnLevelDynamicContentTest.java
new file mode 100644
index 0000000..955066d
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/AsnLevelDynamicContentTest.java
@@ -0,0 +1,112 @@
+package org.uic.barcode.test;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicContent.fdc1.ExtensionData;
+import org.uic.barcode.dynamicContent.fdc1.TimeStamp;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateType;
+
+public class AsnLevelDynamicContentTest {
+
+ UicDynamicContentDataFDC1 asn = null;
+
+ @Before public void initialize() {
+
+
+ asn = new UicDynamicContentDataFDC1();
+
+ asn.setAppId("appID");
+
+ asn.setChallengeString("challenge string");
+
+ ExtensionData asnE1 = new ExtensionData();
+ asnE1.setExtensionData(UperEncoder.bytesFromHexString("82DA"));
+ asnE1.setExtensionId("challenge_extension_id1");
+ asn.setDynamicContentExtension(asnE1);
+
+
+ asn.getExtensions().add(asnE1);
+
+ ExtensionData asnE2 = new ExtensionData();
+ asnE2.setExtensionData(UperEncoder.bytesFromHexString("83DA"));
+ asnE2.setExtensionId("phone");
+ asn.getExtensions().add(asnE2);
+
+ ExtensionData asnE3 = new ExtensionData();
+ asnE3.setExtensionData(UperEncoder.bytesFromHexString("84DA"));
+ asnE3.setExtensionId("pass");
+ asn.getExtensions().add(asnE3);
+
+
+
+ asn.setGeoCoordinate(new GeoCoordinateType());
+ asn.getGeoCoordinate().setLongitude( 12345L);
+ asn.getGeoCoordinate().setLatitude( 56789L);
+
+ TimeStamp t = new TimeStamp();
+ t.setTime(100L);
+ t.setDay(20L);
+ asn.setTimeStamp(t);
+
+
+
+ }
+
+ @Test public void testDynamicContentEncoding() {
+
+ byte[] encodedBytes = UperEncoder.encode(asn);
+
+ String encoding = UperEncoder.hexStringFromBytes(encodedBytes);
+
+ String expectedEncoding = "7C170F0E126204C00C800230390300DDD504017A20C6D0C2D8D8CADCCECA40E6E8E4D2DCCE2F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA05E1A37EECA0507B409C30F3E60509B42F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA";
+
+ assert(expectedEncoding.equals(encoding));
+
+ }
+
+ @Test public void testDynamicContentDecoding() {
+
+ String encoding = "7C170F0E126204C00C800230390300DDD504017A20C6D0C2D8D8CADCCECA40E6E8E4D2DCCE2F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA05E1A37EECA0507B409C30F3E60509B42F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA";
+
+ UicDynamicContentDataFDC1 asn = UperEncoder.decode(UperEncoder.bytesFromHexString(encoding), UicDynamicContentDataFDC1.class);
+
+
+ assert("appID".equals(asn.getAppId()));
+
+ assert("challenge string".equals(asn.getChallengeString()));
+
+ ExtensionData asnE1 = asn.getDynamicContentExtension();
+ assert(UperEncoder.hexStringFromBytes(asnE1.getExtensionData()).equals("82DA"));
+ assert(asnE1.getExtensionId().equals("challenge_extension_id1"));
+
+
+ assert(asn.getExtensions().size() == 4);
+
+ assert(UperEncoder.hexStringFromBytes(asn.getExtensions().get(0).getExtensionData()).equals("6368616C6C656E676520737472696E67"));
+ assert(asn.getExtensions().get(0).getExtensionId().equals("="));
+
+ assert(UperEncoder.hexStringFromBytes(asn.getExtensions().get(1).getExtensionData()).equals("82DA"));
+ assert(asn.getExtensions().get(1).getExtensionId().equals("challenge_extension_id1"));
+
+ assert(UperEncoder.hexStringFromBytes(asn.getExtensions().get(2).getExtensionData()).equals("83DA"));
+ assert(asn.getExtensions().get(2).getExtensionId().equals("phone"));
+
+ assert(UperEncoder.hexStringFromBytes(asn.getExtensions().get(3).getExtensionData()).equals("84DA"));
+ assert(asn.getExtensions().get(3).getExtensionId().equals("pass"));
+
+
+ assert(asn.getGeoCoordinate() != null);
+ assert(asn.getGeoCoordinate().getLongitude() == 12345L);
+ assert(asn.getGeoCoordinate().getLatitude() == 56789L);
+
+ assert(asn.getTimeStamp() != null);
+ assert(asn.getTimeStamp().getDay() == 20L);
+ assert(asn.getTimeStamp().getTime() == 100L);
+
+ }
+
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/BinaryStringTest.java b/src/test/java/org/uic/barcode/test/BinaryStringTest.java
new file mode 100644
index 0000000..d5533fa
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/BinaryStringTest.java
@@ -0,0 +1,61 @@
+package org.uic.barcode.test;
+
+import java.io.IOException;
+import org.junit.Test;
+import org.uic.barcode.asn1.uper.AsnUtils;
+import org.uic.barcode.ticket.EncodingFormatException;
+
+public class BinaryStringTest {
+
+
+
+
+ @Test public void testBinaryString() throws IOException, EncodingFormatException{
+
+ String bs1 = "01000000";
+ String ms1 = "1000000001000000001000000001000000001000000001000000001000000001";
+ String ms2 = "10000000010000000010000000010000";
+
+
+ //String bs1 = "1011111100001000011011100000000000000001000000010000010010000000";
+
+ byte[] bytes = AsnUtils.fromBooleanString(bs1);
+
+ String bs2 = AsnUtils.toBooleanString(bytes);
+
+
+
+ byte[] mask = new byte[] {
+ (byte) 0b1000_0000,
+ 0b0100_0000,
+ 0b0010_0000,
+ 0b0001_0000,
+ 0b0000_1000,
+ 0b0000_0100,
+ 0b0000_0010,
+ 0b0000_0001,
+ };
+ String bs3 = AsnUtils.toBooleanString(mask);
+ byte[] bytes2 = AsnUtils.fromBooleanString(bs3);
+
+
+ byte[] mask2 = new byte[] {
+ (byte) 0b1000_0000,
+ 0b0100_0000,
+ 0b0010_0000,
+ 0b0001_0000,
+ };
+ String bs4 = AsnUtils.toBooleanString(mask2);
+ byte[] bytes3 = AsnUtils.fromBooleanString(bs4);
+
+
+ assert(bs4.equals(ms2));
+
+ assert(bs3.equals(ms1));
+
+ assert(bs1.equals(bs2));
+
+ }
+
+
+} \ No newline at end of file
diff --git a/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java
new file mode 100644
index 0000000..5355d5d
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java
@@ -0,0 +1,118 @@
+package org.uic.barcode.test;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.api.SimpleUicDynamicContent;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.impl.SimpleExtension;
+import org.uic.barcode.ticket.api.impl.SimpleGeoCoordinate;
+import org.uic.barcode.ticket.api.spec.IExtension;
+import org.uic.barcode.ticket.api.spec.IGeoCoordinate;
+
+public class DynamicContentCoderTest {
+
+ IUicDynamicContent content = null;
+
+ @Before public void initialize() {
+
+ content = new SimpleUicDynamicContent();
+
+ content.setAppId("appID");
+
+ content.setChallengeString("challenge string");
+
+ IExtension e = new SimpleExtension();
+ e.setId("challenge_extension_id1");
+ e.setBinarydata(UperEncoder.bytesFromHexString("82DA"));
+ content.setExtension(e);
+
+ IExtension e1 = new SimpleExtension();
+ e1.setId("challenge_extension_id1");
+ e1.setBinarydata(UperEncoder.bytesFromHexString("82DA"));
+ content.addDynamicContentResponse(e1);
+
+ content.setPhoneIdHash(UperEncoder.bytesFromHexString("83DA"));
+
+ content.setPassIdHash(UperEncoder.bytesFromHexString("84DA"));
+
+ IGeoCoordinate g = new SimpleGeoCoordinate();
+ g.setLongitude( 12345L);
+ g.setLatitude( 56789L);
+ content.setGeoCoordinate(g);
+
+ try {
+ content.setTimeStamp(new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).parse( "2021.03.04-12:30" ));
+ } catch (ParseException e2) {
+ //
+ }
+
+ }
+
+ @Test public void testDynamicContentEncoding() {
+
+
+ byte[] encodedBytes = null;
+ try {
+ encodedBytes = DynamicContentCoder.encode(content, null);
+ } catch (EncodingFormatException e) {
+ assert(false);
+ }
+
+ String encoding = UperEncoder.hexStringFromBytes(encodedBytes);
+
+ String expectedEncoding = "7C170F0E12620F9437000230390300DDD504017A20C6D0C2D8D8CADCCECA40E6E8E4D2DCCE2F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA05E1A37EECA0507B409C30F3E60509B42F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA";
+
+ assert(expectedEncoding.equals(encoding));
+
+ }
+
+ @Test public void testDynamicContentDecoding() {
+
+ String encoding = "7C170F0E12620F9437000230390300DDD504017A20C6D0C2D8D8CADCCECA40E6E8E4D2DCCE2F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA05E1A37EECA0507B409C30F3E60509B42F8F461D9B32EECF96FE5F1D32EEE7A77EEBFA72310282DA";
+
+ IUicDynamicContent content = DynamicContentCoder.decode(UperEncoder.bytesFromHexString(encoding));
+
+
+ assert("appID".equals(content.getAppId()));
+
+ assert("challenge string".equals(content.getChallengeString()));
+
+ IExtension e1 = content.getExtension();
+ assert(UperEncoder.hexStringFromBytes(e1.getBinarydata()).equals("82DA"));
+ assert(e1.getId().equals("challenge_extension_id1"));
+
+
+ assert(content.getChallengeString().equals("challenge string"));
+
+ byte[] ce = null;
+ for (IExtension e : content.getDynamicContentResponseList()) {
+ if (e.getId().equals("challenge_extension_id1")) {
+ ce = e.getBinarydata();
+ }
+ }
+ assert(UperEncoder.hexStringFromBytes(ce).equals("82DA"));
+
+ assert(UperEncoder.hexStringFromBytes(content.getPhoneIdHash()).equals("83DA"));
+
+ assert(UperEncoder.hexStringFromBytes(content.getPassIdHash()).equals("84DA"));
+
+ assert(content.getGeoCoordinate() != null);
+ assert(content.getGeoCoordinate().getLongitude() == 12345L);
+ assert(content.getGeoCoordinate().getLatitude() == 56789L);
+
+ assert(content.getTimeStamp() != null);
+
+ assert(content.getTimeStamp().toString().contains("04 12:30:00 CET"));
+
+
+ }
+
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
index 84f7795..0730e69 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
@@ -22,7 +22,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.Level2TestDataFactory;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
@@ -93,7 +93,7 @@ public class DynamicFrameDoubleSignatureProviderSelectionTest {
assert(enc != null);
- DataType level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
+ IData level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
try {
enc.setLevel2Data(level2Data);
enc.signLevel2(keyPairLevel2.getPrivate(),prov);
@@ -135,15 +135,15 @@ public class DynamicFrameDoubleSignatureProviderSelectionTest {
signatureCheck = 0;
try {
signatureCheck = dec.validateLevel2(prov);
- } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ } catch (Exception e) {
assert(false);
}
assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK);
- DataType level2DataDec = dec.getLevel2Data();
+ IData level2DataDec = dec.getLevel2Data();
assert(level2Data.getFormat().equals(level2DataDec.getFormat()));
- assert(Arrays.equals(level2Data.getData().toByteArray(),level2DataDec.getData().toByteArray()));
+ assert(Arrays.equals(level2Data.getData(),level2DataDec.getData()));
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java
index a316cfc..787ebae 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java
@@ -21,7 +21,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.Level2TestDataFactory;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
@@ -89,7 +89,7 @@ public class DynamicFrameDoubleSignatureTest {
assert(enc != null);
- DataType level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
+ IData level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
try {
enc.setLevel2Data(level2Data);
enc.signLevel2(keyPairLevel2.getPrivate());
@@ -131,15 +131,15 @@ public class DynamicFrameDoubleSignatureTest {
signatureCheck = 0;
try {
signatureCheck = dec.validateLevel2();
- } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ } catch (Exception e) {
assert(false);
}
assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK);
- DataType level2DataDec = dec.getLevel2Data();
+ IData level2DataDec = dec.getLevel2Data();
assert(level2Data.getFormat().equals(level2DataDec.getFormat()));
- assert(Arrays.equals(level2Data.getData().toByteArray(),level2DataDec.getData().toByteArray()));
+ assert(Arrays.equals(level2Data.getData(),level2DataDec.getData()));
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java
new file mode 100644
index 0000000..4d34c1b
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java
@@ -0,0 +1,228 @@
+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.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.Date;
+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.dynamicContent.api.IUicDynamicContent;
+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 DynamicFrameDynamicContentApiTest {
+
+ 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;
+
+
+ @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 testDynamicContentEncoding() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 13);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID, keyPairLevel2.getPublic());
+
+ try {
+ enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ try {
+ enc.setDynamicData(DynamicTestContent.createDynamicTestContent());
+ enc.signLevel2(keyPairLevel2.getPrivate());
+
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+
+
+ }
+
+ @Test public void testDynamicContentDecoding() {
+
+ IUicRailTicket ticket = testFCBticket;
+
+ Encoder enc = null;
+
+ try {
+ enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 1, 13);
+ } catch (IOException | EncodingFormatException e1) {
+ assert(false);
+ }
+
+ assert(enc != null);
+
+ enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID, keyPairLevel2.getPublic());
+
+ try {
+ enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ try {
+ enc.setDynamicData(DynamicTestContent.createDynamicTestContent());
+ enc.signLevel2(keyPairLevel2.getPrivate());
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ 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);
+
+ 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);
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+ int level2check = 0;
+ try {
+ level2check = dec.validateLevel2();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(level2check == Constants.LEVEL2_VALIDATION_OK);
+
+ IUicDynamicContent dynamicData = dec.getDynamicContent();
+
+ assert(dynamicData.getChallengeString().equals("CHALLENGE"));
+
+ assert(dynamicData.getAppId().equals("MyApp"));
+
+ assert(Arrays.equals(dynamicData.getPassIdHash(),passIdHash));
+
+ assert(Arrays.equals(dynamicData.getPhoneIdHash(),phoneIdHash));
+
+ assert(dynamicData.getGeoCoordinate().getLatitude() == 123456L);
+ assert(dynamicData.getGeoCoordinate().getLongitude() == 23456L);
+
+ Date timeStamp = dynamicData.getTimeStamp();
+ ZonedDateTime retrievedTimeStamp = timeStamp.toInstant().atZone(ZoneId.of("UTC"));
+ ZonedDateTime originalTimeStamp = ZonedDateTime.now(ZoneId.of("UTC"));
+ long diff = ChronoUnit.SECONDS.between(originalTimeStamp, retrievedTimeStamp);
+
+ assert(diff > -50 && diff < 50);
+ }
+
+ 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();
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
index f3e4f54..d26ab77 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
@@ -24,7 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
-import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateSystemType;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateType;
import org.uic.barcode.dynamicContent.fdc1.TimeStamp;
import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
@@ -218,7 +218,7 @@ public class DynamicFrameDynamicContentTest {
assert(level2check == Constants.LEVEL2_VALIDATION_OK);
- UicDynamicContentDataFDC1 dynamicData = dec.getDynamicHeader().getDynamicDataFDC1();
+ IUicDynamicContent dynamicData = dec.getDynamicFrame().getDynamicContent();
assert(dynamicData.getChallengeString().equals("CHALLENGE"));
@@ -229,9 +229,9 @@ public class DynamicFrameDynamicContentTest {
assert(Arrays.equals(dynamicData.getPhoneIdHash(),phoneIdHash));
assert(dynamicData.getGeoCoordinate().getLatitude() == 123456L);
- assert(dynamicData.getGeoCoordinate().getLongitude() == 823456L);
+ assert(dynamicData.getGeoCoordinate().getLongitude() == 103456L);
- Date timeStamp = dynamicData.getTimeStamp().getTimeAsDate();
+ Date timeStamp = dynamicData.getTimeStamp();
ZonedDateTime retrievedTimeStamp = timeStamp.toInstant().atZone(ZoneId.of("UTC"));
long diff = ChronoUnit.SECONDS.between(originalTimeStamp, retrievedTimeStamp);
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
index 63ba68e..ea95a88 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
@@ -20,6 +20,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.ticket.api.spec.IUicRailTicket;
@@ -142,11 +143,12 @@ public class DynamicFrameFcbVersion1Test {
assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
- assert(dec.getDynamicHeader().getFormat().equals("U1"));
+ assert(dec.getDynamicFrame().getFormat().equals("U1"));
- assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB1"));
-
-
+ for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) {
+ assert(data.getFormat().equals("FCB1") );
+ }
+
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
index 4f0897e..199a32d 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
@@ -20,6 +20,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.ticket.api.spec.IUicRailTicket;
@@ -134,7 +135,7 @@ public class DynamicFrameFcbVersion3Test {
int signatureCheck = 0;
try {
- signatureCheck = dec.validateLevel1(keyPair.getPublic(),null);
+ signatureCheck = dec.validateLevel1(keyPair.getPublic());
} catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
| UnsupportedOperationException | IOException | EncodingFormatException e) {
assert(false);
@@ -142,10 +143,11 @@ public class DynamicFrameFcbVersion3Test {
assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
- assert(dec.getDynamicHeader().getFormat().equals("U1"));
-
- assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB3"));
+ assert(dec.getDynamicFrame().getFormat().equals("U1"));
+ for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) {
+ assert(data.getFormat().equals("FCB3") );
+ }
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java
index 5dd9668..b8a851b 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java
@@ -21,7 +21,7 @@ import org.junit.Before;
import org.junit.Test;
import org.uic.barcode.asn1.uper.UperEncoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrame;
import org.uic.barcode.test.utils.SimpleDynamicFrameTestBarcode;
public class DynamicFrameLOwLevelTest {
@@ -84,17 +84,13 @@ public class DynamicFrameLOwLevelTest {
}
- @Test public void testDynamicHeaderBarcodeDecoding() {
+ @Test public void testDynamicHeaderBarcodeDecodingV1() {
DynamicFrame barcode1 = SimpleDynamicFrameTestBarcode.getSimpleDynamicHeaderBarcode(algorithmOID, keyPair);
byte[] encoded = barcode1.encode();
DynamicFrame barcode = DynamicFrame.decode(encoded);
-
- int signatureCheck = barcode.validateLevel1(keyPair.getPublic());
-
- assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
SimpleDynamicFrameTestBarcode.compareFrame(barcode1, barcode);
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java
new file mode 100644
index 0000000..17bccd6
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java
@@ -0,0 +1,176 @@
+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.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.dynamicFrame.api.IData;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public class DynamicFrameV2FcbVersion3Test {
+
+ public String signatureAlgorithmOID = null;
+ public String elipticCurve = null;
+ public String keyPairAlgorithmOID = null;
+
+ public KeyPair keyPair = null;
+
+ public IUicRailTicket testFCBticket = null;
+
+
+ @Before public void initialize() {
+
+ signatureAlgorithmOID = Constants.ECDSA_SHA256;
+ keyPairAlgorithmOID = Constants.KG_EC_256;
+ elipticCurve = "secp256k1";
+
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ try {
+ keyPair = generateECKeys(Constants.KG_EC, elipticCurve);
+ //keyPair = generateECDSAKeys("ECDSA", "B-571");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(keyPair != null);
+
+ }
+
+
+ @Test public void testDynamicHeaderBarcodeEncodingFCB3() {
+
+ 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);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+
+ }
+
+ @Test public void testDynamicHeaderBarcodeDecodingFCB3() {
+
+ 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);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ 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);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPair.getPublic(),null);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ assert(dec.getDynamicFrame().getFormat().equals("U2"));
+
+ for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) {
+ assert(data.getFormat().equals("FCB3") );
+ }
+
+ SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
+
+
+
+
+ }
+
+ 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();
+ }
+
+
+}
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;
+
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsertTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsertTest.java
new file mode 100644
index 0000000..8f97574
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsertTest.java
@@ -0,0 +1,289 @@
+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 DynamicFrameV2SignatureInsertTest {
+
+ 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 encoded level 1 data
+ // add level 2 data and signature
+
+
+ byte[] signatureLevel1Data = enc.getDynamicFrame().getLevel2Data().getLevel1Signature();
+ byte[] encodedLevel1Data = null;
+ try {
+ encodedLevel1Data = enc.getEncodedLevel1Data();
+ } catch (IOException e2) {
+ assert(false);
+ } catch (EncodingFormatException e2) {
+ assert(false);
+ }
+
+
+
+ //dynamic barcode creation
+
+ //-------------------------------------------------------------------------------
+ //add the signed level 1 data for encoding of level 2
+ try {
+ enc = new Encoder(encodedLevel1Data,signatureLevel1Data , 2);
+ } catch (IOException | EncodingFormatException 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;
+
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java
new file mode 100644
index 0000000..9bbd736
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java
@@ -0,0 +1,212 @@
+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.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.dynamicFrame.api.IData;
+import org.uic.barcode.test.utils.SimpleUICTestTicket;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.spec.IUicRailTicket;
+
+public class DynamicFrameV2ValidityDateTest {
+
+ public String signatureAlgorithmOID = null;
+ public String elipticCurve = null;
+ public String keyPairAlgorithmOID = null;
+
+ public KeyPair keyPair = null;
+
+ public IUicRailTicket testFCBticket = null;
+
+
+ @Before public void initialize() {
+
+ signatureAlgorithmOID = Constants.ECDSA_SHA256;
+ keyPairAlgorithmOID = Constants.KG_EC_256;
+ elipticCurve = "secp256k1";
+
+ testFCBticket = SimpleUICTestTicket.getUicTestTicket();
+
+ Security.addProvider(new BouncyCastleProvider());
+
+ try {
+ keyPair = generateECKeys(Constants.KG_EC, elipticCurve);
+ //keyPair = generateECDSAKeys("ECDSA", "B-571");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(keyPair != null);
+
+ }
+
+
+ @Test public void testDynamicHeaderBarcodeEncodingFCB3() {
+
+ 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);
+
+ TimeZone local = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ Date endDate = null;
+ try {
+ endDate = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).parse( "2021.03.04-12:30" );
+ } catch (ParseException e1) {
+ assert(false);
+ }
+ TimeZone.setDefault(local);
+
+ enc.getDynamicFrame().getLevel2Data().getLevel1Data().setEndOfBarcodeValidity(endDate);
+ enc.getDynamicFrame().getLevel2Data().getLevel1Data().setValidityDuration(100L);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+
+ }
+
+ @Test public void testDynamicHeaderBarcodeDecodingFCB3() {
+
+ 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);
+
+ TimeZone local = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ Date endDate = null;
+ try {
+ endDate = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).parse( "2021.03.04-12:30" );
+ } catch (ParseException e1) {
+ assert(false);
+ }
+ TimeZone.setDefault(local);
+
+ enc.getDynamicFrame().getLevel2Data().getLevel1Data().setEndOfBarcodeValidity(endDate);
+ enc.getDynamicFrame().getLevel2Data().getLevel1Data().setValidityDuration(100L);
+
+ try {
+ enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1");
+ } catch (Exception e) {
+ assert(false);
+ }
+
+
+ byte[] encoded = null;
+ try {
+ encoded = enc.encode();
+ } catch (Exception e) {
+ assert(false);
+ }
+
+ assert(encoded != null);
+
+ 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);
+
+ int signatureCheck = 0;
+ try {
+ signatureCheck = dec.validateLevel1(keyPair.getPublic(),null);
+ } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException
+ | UnsupportedOperationException | IOException | EncodingFormatException e) {
+ assert(false);
+ }
+
+ assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK);
+
+ assert(dec.getDynamicFrame().getFormat().equals("U2"));
+
+ for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) {
+ assert(data.getFormat().equals("FCB3") );
+ }
+
+ Date endDate2 = dec.getDynamicFrame().getLevel2Data().getLevel1Data().getEndOfBarcodeValidity();
+
+
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ String date2 = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).format(endDate2);
+ TimeZone.setDefault(local);
+
+ assert("2021.03.04-12:30".equals(date2));
+
+ assert(100L == dec.getDynamicFrame().getLevel2Data().getLevel1Data().getValidityDuration());
+
+ }
+
+ 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();
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/TimeStampTest.java b/src/test/java/org/uic/barcode/test/TimeStampTest.java
new file mode 100644
index 0000000..b2e3ab1
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/TimeStampTest.java
@@ -0,0 +1,36 @@
+package org.uic.barcode.test;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.junit.Test;
+import org.uic.barcode.dynamicContent.fdc1.TimeStamp;
+
+public class TimeStampTest {
+
+
+
+ @Test public void testDateConversion() {
+
+
+ TimeStamp ts = new TimeStamp();
+
+ ts.setDay(10L);
+ ts.setTime(6000L);
+
+ Date date = ts.getTimeAsDate();
+
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ cal.setTime(date);
+ long seconds = cal.get(Calendar.SECOND);
+ seconds = seconds + cal.get(Calendar.MINUTE) * 60;
+ seconds = seconds + cal.get(Calendar.HOUR_OF_DAY) * 60 * 60;
+
+ assert(seconds == 6000L);
+
+
+ }
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java b/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java
new file mode 100644
index 0000000..9380372
--- /dev/null
+++ b/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java
@@ -0,0 +1,40 @@
+package org.uic.barcode.test.utils;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.api.SimpleUicDynamicContent;
+import org.uic.barcode.ticket.api.impl.SimpleGeoCoordinate;
+import org.uic.barcode.ticket.api.spec.IGeoCoordinate;
+
+public class DynamicTestContent {
+
+ public static byte[] passIdHash = "PassId".getBytes();
+ public static byte[] phoneIdHash = "myPhone".getBytes();
+
+
+ public static IUicDynamicContent createDynamicTestContent() {
+
+ IUicDynamicContent dc = new SimpleUicDynamicContent();
+ dc.setChallengeString("CHALLENGE");
+ dc.setAppId("MyApp");
+ dc.setPhoneIdHash(phoneIdHash);
+ dc.setPassIdHash(passIdHash);
+
+ ZonedDateTime timeStamp = ZonedDateTime.now(ZoneId.of("UTC"));
+
+ dc.setTimeStamp(Date.from(timeStamp.toInstant()));
+
+ IGeoCoordinate geo = new SimpleGeoCoordinate();
+ geo.setLatitude(123456L);
+ geo.setLongitude(23456L);
+ dc.setGeoCoordinate(geo);
+
+ return dc;
+ }
+
+
+
+}
diff --git a/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java b/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java
index b1eb0f5..bdabdc6 100644
--- a/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java
+++ b/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java
@@ -1,17 +1,17 @@
package org.uic.barcode.test.utils;
-import org.uic.barcode.asn1.datatypesimpl.OctetString;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
public class Level2TestDataFactory {
- public static DataType getLevel2SimpleTestData() {
+ public static IData getLevel2SimpleTestData() {
String testContent = "2020.10.01T12:12.20";
- DataType level2Data = new DataType();
+ IData level2Data = new SimpleData();
level2Data.setFormat("TEST");
- level2Data.setData(new OctetString(testContent.getBytes()));
+ level2Data.setData(testContent.getBytes());
return level2Data;
}
diff --git a/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java b/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java
index 0060fcd..f2ef0f3 100644
--- a/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java
+++ b/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java
@@ -1,28 +1,27 @@
package org.uic.barcode.test.utils;
import java.security.KeyPair;
+import java.security.Signature;
+import org.uic.barcode.asn1.uper.UperEncoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
-import org.uic.barcode.dynamicFrame.Level1DataType;
-import org.uic.barcode.dynamicFrame.Level2DataType;
-import org.uic.barcode.dynamicFrame.SequenceOfDataType;
+import org.uic.barcode.dynamicFrame.v1.DataType;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrame;
+import org.uic.barcode.dynamicFrame.v1.Level1DataType;
+import org.uic.barcode.dynamicFrame.v1.Level2DataType;
+import org.uic.barcode.dynamicFrame.v1.SequenceOfDataType;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.ticket.api.asn.omv1.UicRailTicketData;
import org.uic.barcode.ticket.api.test.testtickets.SimpleUicTestTicket;
+import org.uic.barcode.utils.AlgorithmNameResolver;
public class SimpleDynamicFrameTestBarcode {
public static DynamicFrame getSimpleDynamicHeaderBarcode(String algorithm, KeyPair keyPair) {
-
-
DynamicFrame barcode = null;
-
-
try {
barcode = new DynamicFrame();
barcode.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_DEFAULT);
@@ -47,7 +46,12 @@ public class SimpleDynamicFrameTestBarcode {
level1Data.getData().add(data);
try {
- level2Data.signLevel1(keyPair.getPrivate());
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg());
+ Signature sig = Signature.getInstance(algo);
+ sig.initSign(keyPair.getPrivate());
+ byte[] data2 = UperEncoder.encode(level1Data);
+ sig.update(data2);
+ level2Data.setLevel1Signature(sig.sign());
} catch (Exception e) {
assert(false);
}