From 12b733b1062430ce4bad08c077148a7d235439f3 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Wed, 15 Dec 2021 16:36:47 +0100 Subject: - unit test for the dynamic content in DOSIPAS - api layoer for the dynamic content in DOSIPAS --- .../org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java | 2 ++ src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) 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..3ced173 100644 --- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java +++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java @@ -181,6 +181,8 @@ public class UicDynamicContentDataFDC1 { this.timeStamp = timeStamp; } + + public SequenceOfExtension getExtensions() { return dynamicContentResponseToChallenge; } diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java index f3e4f54..a5f91ca 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java @@ -24,7 +24,6 @@ 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.fdc1.GeoCoordinateType; import org.uic.barcode.dynamicContent.fdc1.TimeStamp; import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; -- cgit v1.2.3 From fbbc6349283bc8958cad51534da9cb82c46210c9 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Wed, 15 Dec 2021 16:37:37 +0100 Subject: api layer for dynamic content --- .../dynamicContent/api/DynamicContentCoder.java | 211 +++++++++++++++++++++ .../dynamicContent/api/IUicDynamicContent.java | 130 +++++++++++++ .../api/SimpleUicDynamicContent.java | 150 +++++++++++++++ .../barcode/test/AsnLevelDynamicContentTest.java | 112 +++++++++++ .../uic/barcode/test/DynamicContentCoderTest.java | 118 ++++++++++++ 5 files changed, 721 insertions(+) create mode 100644 src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java create mode 100644 src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java create mode 100644 src/main/java/org/uic/barcode/dynamicContent/api/SimpleUicDynamicContent.java create mode 100644 src/test/java/org/uic/barcode/test/AsnLevelDynamicContentTest.java create mode 100644 src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java 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..d8bf3b4 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java @@ -0,0 +1,211 @@ +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 byte[] encode(IUicDynamicContent content, String format) throws EncodingFormatException { + + if (format != null && !format.equals("FDC1")) { + 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 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..718d013 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java @@ -0,0 +1,130 @@ +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; + +// TODO: Auto-generated Javadoc +/** + * 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 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 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 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 e = new SimpleExtension(); + e.setBinarydata(passIdHash); + e.setId("pass"); + getDynamicContentResponseList().add(e); + } + + @Override + public List getDynamicContentResponseList() { + if (dynamicContentResponseList == null) { + dynamicContentResponseList = new ArrayList(); + } + + return dynamicContentResponseList; + } + + @Override + public void addDynamicContentResponse(IExtension challenge) { + + if (this.dynamicContentResponseList == null) { + this.dynamicContentResponseList = new ArrayList(); + } + + this.dynamicContentResponseList.add(challenge); + + } + + +} 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/DynamicContentCoderTest.java b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java new file mode 100644 index 0000000..10963c5 --- /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().equals("Wed Dec 15 12:30:00 CET 2021" )); + + + } + + + +} -- cgit v1.2.3 From bdb54c653eda54b003e50460928cfd8bbc80bc44 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Thu, 16 Dec 2021 16:13:13 +0100 Subject: extended api for dynamic content additional tests --- src/main/java/org/uic/barcode/Decoder.java | 12 ++ src/main/java/org/uic/barcode/Encoder.java | 18 ++ .../dynamicContent/api/DynamicContentCoder.java | 4 +- .../uic/barcode/dynamicContent/fdc1/TimeStamp.java | 7 +- .../org/uic/barcode/dynamicFrame/DynamicFrame.java | 94 ++++++++- .../test/DynamicFrameDynamicContentApiTest.java | 230 +++++++++++++++++++++ .../java/org/uic/barcode/test/TimeStampTest.java | 36 ++++ .../uic/barcode/test/utils/DynamicTestContent.java | 38 ++++ 8 files changed, 436 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java create mode 100644 src/test/java/org/uic/barcode/test/TimeStampTest.java create mode 100644 src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index 9f102d3..4c8b044 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -8,6 +8,7 @@ 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; @@ -237,6 +238,17 @@ public class Decoder { 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. * diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java index f0f8d14..3b30e8a 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -6,6 +6,7 @@ import java.security.Provider; import java.security.PublicKey; 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; @@ -178,6 +179,15 @@ public class Encoder { } } + public void setDynamicData(IUicDynamicContent content) throws EncodingFormatException { + if (dynamicFrame != null) { + if (dynamicFrame.getLevel2SignedData() == null) { + dynamicFrame.setLevel2SignedData(new Level2DataType()); + } + dynamicFrame.addDynamicContent(content); + } + } + public void setLevel2Data(DataType level2data) { if (dynamicFrame != null) { if (dynamicFrame.getLevel2SignedData() == null) { @@ -203,6 +213,14 @@ public class Encoder { return null; } + + public IUicDynamicContent getDynamicContent() { + if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) { + return dynamicFrame.getDynamicContent(); + } + return null; + } + public UicDynamicContentDataFDC1 getDynamicContentDataUIC1() { if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) { return dynamicFrame.getDynamicDataFDC1(); diff --git a/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java b/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java index d8bf3b4..34406e0 100644 --- a/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java +++ b/src/main/java/org/uic/barcode/dynamicContent/api/DynamicContentCoder.java @@ -26,9 +26,11 @@ 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("FDC1")) { + if (format != null && !format.equals(dynamicContentDataFDC1)) { throw new EncodingFormatException("Format of dynamic content not supported!"); } 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..a1b9581 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 */ @@ -136,4 +139,6 @@ public class TimeStamp { } + + } diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java index c74215d..eb26729 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java @@ -18,10 +18,14 @@ 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; +// TODO: Auto-generated Javadoc /** * The DynamicHeader for bar codes * @@ -30,6 +34,9 @@ import org.uic.barcode.utils.AlgorithmNameResolver; @Sequence public class DynamicFrame extends Object{ + /** + * Instantiates a new dynamic frame. + */ public DynamicFrame() {} /** The format. */ @@ -37,12 +44,13 @@ public class DynamicFrame extends Object{ @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*/ + /** The signature of level 2 data. */ @FieldOrder(order = 2) @Asn1Optional public OctetString level2Signature; @@ -64,18 +72,38 @@ public class DynamicFrame extends Object{ 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; } @@ -108,6 +136,7 @@ public class DynamicFrame extends Object{ * * Note: an appropriate security provider (e.g. BC) must be registered before * + * @return the int */ public int validateLevel2() { @@ -120,6 +149,8 @@ public class DynamicFrame extends Object{ * * Note: an appropriate security provider (e.g. BC) must be registered before * + * @param prov the prov + * @return the int */ public int validateLevel2(Provider prov) { @@ -213,6 +244,9 @@ public class DynamicFrame extends Object{ * * Note: an appropriate security provider (e.g. BC) must be registered before * + * @param key the key + * @param prov the prov + * @return the int */ public int validateLevel1(PublicKey key, Provider prov) { @@ -282,6 +316,8 @@ public class DynamicFrame extends Object{ * * Note: an appropriate security provider (e.g. BC) must be registered before * + * @param key the key + * @return the int */ public int validateLevel1(PublicKey key) { @@ -289,6 +325,12 @@ public class DynamicFrame extends Object{ } + /** + * 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 @@ -302,6 +344,13 @@ public class DynamicFrame extends Object{ } + /** + * 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 @@ -315,10 +364,53 @@ public class DynamicFrame extends Object{ } + /** + * 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) { this.getLevel2SignedData().setLevel2Data( dynamicData.getDataType()); } + /** + * 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 || 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..5a70841 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java @@ -0,0 +1,230 @@ +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.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/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..a39b270 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java @@ -0,0 +1,38 @@ +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; + } + +} -- cgit v1.2.3 From 17f05b763d70f350bad482df9378c571c2ebddf6 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Fri, 21 Jan 2022 18:19:36 +0100 Subject: new dynamic header version 2.0.0 --- misc/uicBarcodeHeader_v2.0.0.asn | 126 ++++ misc/uicRailTicketData_v1.3.1.data | 793 +++++++++++++++++++++ misc/uicRailTicketData_v1.3.1_a.data | 245 +++++++ pom.xml | 2 +- src/main/java/org/uic/barcode/Decoder.java | 44 +- src/main/java/org/uic/barcode/Encoder.java | 102 ++- .../uic/barcode/dynamicContent/fdc1/TimeStamp.java | 7 +- .../fdc1/UicDynamicContentDataFDC1.java | 12 +- .../org/uic/barcode/dynamicFrame/Constants.java | 2 + .../org/uic/barcode/dynamicFrame/DataType.java | 93 --- .../org/uic/barcode/dynamicFrame/DynamicFrame.java | 429 ----------- .../uic/barcode/dynamicFrame/Level1DataType.java | 226 ------ .../uic/barcode/dynamicFrame/Level2DataType.java | 121 ---- .../barcode/dynamicFrame/SequenceOfDataType.java | 25 - .../org/uic/barcode/dynamicFrame/api/IData.java | 39 + .../barcode/dynamicFrame/api/IDynamicFrame.java | 202 ++++++ .../uic/barcode/dynamicFrame/api/ILevel1Data.java | 164 +++++ .../uic/barcode/dynamicFrame/api/ILevel2Data.java | 25 + .../uic/barcode/dynamicFrame/api/SimpleData.java | 59 ++ .../dynamicFrame/api/SimpleDynamicFrame.java | 553 ++++++++++++++ .../barcode/dynamicFrame/api/SimpleLevel1Data.java | 254 +++++++ .../barcode/dynamicFrame/api/SimpleLevel2Data.java | 75 ++ .../java/org/uic/barcode/dynamicFrame/package.html | 9 - .../org/uic/barcode/dynamicFrame/v1/DataType.java | 93 +++ .../uic/barcode/dynamicFrame/v1/DynamicFrame.java | 432 +++++++++++ .../dynamicFrame/v1/DynamicFrameCoderV1.java | 189 +++++ .../barcode/dynamicFrame/v1/Level1DataType.java | 226 ++++++ .../barcode/dynamicFrame/v1/Level2DataType.java | 74 ++ .../dynamicFrame/v1/SequenceOfDataType.java | 25 + .../org/uic/barcode/dynamicFrame/v2/DataType.java | 95 +++ .../uic/barcode/dynamicFrame/v2/DynamicFrame.java | 434 +++++++++++ .../dynamicFrame/v2/DynamicFrameCoderV2.java | 203 ++++++ .../barcode/dynamicFrame/v2/Level1DataType.java | 374 ++++++++++ .../barcode/dynamicFrame/v2/Level2DataType.java | 123 ++++ .../dynamicFrame/v2/SequenceOfDataType.java | 25 + .../uic/barcode/test/DynamicContentCoderTest.java | 2 +- ...cFrameDoubleSignatureProviderSelectionTest.java | 10 +- .../test/DynamicFrameDoubleSignatureTest.java | 10 +- .../test/DynamicFrameDynamicContentTest.java | 7 +- .../barcode/test/DynamicFrameFcbVersion1Test.java | 8 +- .../barcode/test/DynamicFrameFcbVersion3Test.java | 6 +- .../uic/barcode/test/DynamicFrameLOwLevelTest.java | 2 +- .../barcode/test/utils/Level2TestDataFactory.java | 10 +- .../test/utils/SimpleDynamicFrameTestBarcode.java | 24 +- 44 files changed, 4962 insertions(+), 1017 deletions(-) create mode 100644 misc/uicBarcodeHeader_v2.0.0.asn create mode 100644 misc/uicRailTicketData_v1.3.1.data create mode 100644 misc/uicRailTicketData_v1.3.1_a.data delete mode 100644 src/main/java/org/uic/barcode/dynamicFrame/DataType.java delete mode 100644 src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java delete mode 100644 src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java delete mode 100644 src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java delete mode 100644 src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/IData.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java delete mode 100644 src/main/java/org/uic/barcode/dynamicFrame/package.html create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java diff --git a/misc/uicBarcodeHeader_v2.0.0.asn b/misc/uicBarcodeHeader_v2.0.0.asn new file mode 100644 index 0000000..79d104d --- /dev/null +++ b/misc/uicBarcodeHeader_v2.0.0.asn @@ -0,0 +1,126 @@ +-- Author: ClemensGantert +-- Created: Thu Jun 04 17:19:28 CEST 2020 +ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN + +-- imports and exports +-- EXPORTS ALL; + + +-- ############################################################################################## +-- # +-- # UIC barcode header - version 2.0.0 +-- # +-- ############################################################################################## + + +-- ############################################################################################## +-- # +-- # Naming and encoding conventions +-- # +-- # - A bar code which is only static (printed on a paper), and for which the security is in the system, +-- # does not need any of these elements. +-- # - A bar code which is only static, and includes its own security, needs: +-- # level1Signature +-- # level1KeyAlg if the associated key does not include the complete certificate in keys.xml but only the public key +-- # (but level1SigningAlg is not necessary as it is in keys.xml) +-- # - A dynamic bar code including static and dynamic signatures needs: +-- # The same elements as a static bar code above, +-- # level2SigningAlg, level2keyAlg, level2PublicKey, and level2Signature. +-- # +-- # Changes to Version 1: +-- # +-- # - endOfValidity added in Level1Data +-- # - extension option added on all structures +-- # +-- ######################################################################################### + + +-- ############################################################################################ + + +-- type assignments + + -- ######################################################################################### + -- the basic entry point of the data structure + -- ########################################################################################## + UicBarcodeHeader ::= SEQUENCE { + -- barcode format type + format IA5String, + -- "U2" = UIC ticket + + + level2SignedData Level2DataType, + + -- signature is calculated on the PER unaligned encoding of level2 signature data + level2Signature OCTET STRING OPTIONAL, + ... + + + } + + Level2DataType ::= SEQUENCE { + + level1Data Level1DataType, + + -- signature is calculated on the PER unaligned encoding of level1 signature data + level1Signature OCTET STRING OPTIONAL, + + level2Data DataType OPTIONAL, + ... + + } + + + Level1DataType ::= SEQUENCE { + + -- provider of the level1 signature (RICS code) + securityProviderNum INTEGER (1..32000) OPTIONAL, + securityProviderIA5 IA5String OPTIONAL, + + keyId INTEGER(0..99999) OPTIONAL, + + dataSequence SEQUENCE OF DataType, + + + -- object identifier of the key algorithms + -- e.g. + -- ECC P-256 1.2.840.10045.3.1.7 + level1KeyAlg OBJECT IDENTIFIER OPTIONAL, + level2KeyAlg OBJECT IDENTIFIER OPTIONAL, + + -- object identifier of the signing algorithm + -- e.g. + -- DSA SHA224 2.16.840.1.101.3.4.3.1 + -- DSA SHA256 2.16.840.1.101.3.4.3.2 + -- ECDSA-256 1.2.840.10045.4.3.2 + -- algorithm used for signing + level1SigningAlg OBJECT IDENTIFIER OPTIONAL, + level2SigningAlg OBJECT IDENTIFIER OPTIONAL, + level2PublicKey OCTET STRING OPTIONAL, + + -- end of the validity of the bar code, after this date and time the bar code needs to be regenerated + -- 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 must ensure that the end of validity of the bar code is + -- before the end of validity of the key pair used on level 2 + endOfValidityYear INTEGER (2016..2269) OPTIONAL, + -- number of the day in the year (1.1. = 1) + endOfValidityDay INTEGER (1..366) OPTIONAL, + -- The number of the minutes of the day + endOfValidityTime INTEGER (0..1439) OPTIONAL, + ... + } + + DataType ::= SEQUENCE { + -- Content of data format: + -- FCBn (FCB1 = FCB version 1, FCB2 = FCB version 2) + -- FDCn dynamic content + -- or proprietary: + -- _RICS company code + addon + dataFormat IA5String, + data OCTET STRING, + ... + } + + +END \ No newline at end of file diff --git a/misc/uicRailTicketData_v1.3.1.data b/misc/uicRailTicketData_v1.3.1.data new file mode 100644 index 0000000..e0ee943 --- /dev/null +++ b/misc/uicRailTicketData_v1.3.1.data @@ -0,0 +1,793 @@ +value UicRailTicketData ::= { + issuingDetail { + securityProviderNum 1, + securityProviderIA5 "1", + issuerNum 32000, + issuerIA5 "1", + issuingYear 2018, + issuingDay 1, + issuingTime 600, + issuerName "name", + specimen TRUE, + securePaperTicket FALSE, + activated TRUE, + currency "SRF", + currencyFract 3, + issuerPNR "issuerTestPNR", + extension { extensionId "1", extensionData '82DA'H }, + issuedOnTrainNum 123, + issuedOnTrainIA5 "123", + issuedOnLine 12, + pointOfSale { + geoUnit microDegree, + coordinateSystem wgs84 + hemisphereLongitude north, + hemisphereLatitude east, + longitude 12345, + latitude 56789, + accuracy microDegree + } + }, + travelerDetail{ + traveler { + { + firstName "John", + secondName "Little", + lastName "Dow", + idCard "12345", + passportId "JDTS", + title "PhD", + gender male, + customerIdIA5 "DZE5gT", + customerIdNum 12345, + yearOfBirth 1901, + monthOfBirth 12, + dayOfBirthInMonth 31, + ticketHolder TRUE, + passengerType senior, + passengerWithReducedMobility FALSE, + countryOfResidence 101, + countryOfPassport 102, + countryOfIdCard 103, + status { + {customerStatus 1, customerStatusDescr "senior" } + } + } + }, + preferredLanguage "EN", + groupName "myGroup" + }, + transportDocument { + { + ticket reservation : { + trainNum 12345, + trainIA5 "12345", + departureDate 2, + referenceIA5 "810123456789", + referenceNum 80123456789, + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + serviceBrand 12, + serviceBrandAbrUTF8 "TGV", + serviceBrandNameUTF8 "Lyria", + service couchette, + stationCodeTable stationUIC, + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + departureTime 1439, + departureUTCOffset -60, + arrivalDate 20, + arrivalTime 0, + arrivalUTCOffset 10, + carrierNum {1080, 1181}, + carrierIA5 {"1080", "1181"}, + classCode first, + serviceLevel "A", + places { + coach "31A", + placeString "31-47", + placeDescription "Window", + placeIA5 {"31A", "31B"}, + placeNum {31, 32} + }, + additionalPlaces { + coach "31A", + placeString "31-47", + placeDescription "Window", + placeIA5 {"31A", "31B"}, + placeNum {31, 32} + }, + bicyclePlaces { + coach "31A", + placeString "31-47", + placeDescription "Window", + placeIA5 {"31A", "31B"}, + placeNum {31, 32} + }, + compartmentDetails { + coachType 1, + compartmentType 99, + specialAllocation 50, + coachTypeDescr "xwz", + compartmentTypeDescr "xwz", + specialAllocationDescr "xwz", + position upperLevel + }, + numberOfOverbooked 200, + berth { + { + berthType single, + numberOfBerths 999, + gender female + } + }, + tariff { + { + numberOfPassengers 1, + passengerType senior, + ageBelow 64, + ageAbove 60, + travelerid { 1 }, + restrictedToCountryOfResidence FALSE, + restrictedToRouteSection { + stationCodeTable stationERA, + fromStationNum 123, + fromStationIA5 "123", + toStationNum 234, + toStationIA5 "234", + fromStationNameUTF8 "A", + toStationNameUTF8 "B" + }, + seriesDataDetails { + supplyingCarrier 12345, + offerIdentification 99, + series 23456 + }, + tariffIdNum 72, + tariffIdIA5 "72", + tariffDesc "Leasure Fare", + reductionCard { + { + cardIssuerNum 1234, + cardIssuerIA5 "1234", + cardIdNum 5678, + cardIdIA5 "5678", + cardName "testcard", + cardType 123, + leadingCardIdNum 3456, + leadingCardIdIA5 "3456", + trailingCardIdNum 100, + trailingCardIdIA5 "100" + } + } + } + }, + priceType travelPrice, + price 12345, + vatDetail { + { + country 80, + percentage 70, + amount 10, + vatId "IUDGTE" + } + }, + typeOfSupplement 9, + numberOfSupplements 2, + luggage { + maxHandLuggagePieces 2, + maxNonHandLuggagePieces 1, + registeredLuggage { + { + registrationId "IODHUV", + maxWeight 20, + maxSize 100 + }, + { + registrationId "XXDHUV", + maxWeight 21, + maxSize 101 + } + } + }, + infoText "reservation", + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + token { + tokenProviderNum 123, + tokenProviderIA5 "VDV", + tokenSpecification "TEST", + token '82DA'H }, + ticket carCarriageReservation : { + trainNum 123, + trainIA5 "123", + beginLoadingDate 10, + beginLoadingTime 0, + endLoadingTime 500, + loadingUTCOffset 30, + referenceIA5 "810123456789", + referenceNum 810123456789, + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + serviceBrand 100, + serviceBrandAbrUTF8 "AZ", + serviceBrandNameUTF8 "special train", + stationCodeTable stationERA, + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + coach "21", + place "41", + compartmentDetails { + coachType 1, + compartmentType 99, + specialAllocation 50, + coachTypeDescr "xwz", + compartmentTypeDescr "xwz", + specialAllocationDescr "xwz", + position upperLevel + }, + numberPlate "AD-DE-123", + trailerPlate "DX-AB-123", + carCategory 3, + boatCategory 5, + textileRoof FALSE, + roofRackType bicycleRack, + roofRackHeight 20, + attachedBoats 2, + attachedBicycles 1, + attachedSurfboards 2, + loadingListEntry 421, + loadingDeck upper, + carrierNum { 1080, 1181 }, + carrierIA5 { "1080", "1181" }, + tariff { + numberOfPassengers 1, + restrictedToCountryOfResidence FALSE, + tariffIdNum 72, + tariffDesc "Large Car Full Fare" + }, + priceType travelPrice, + price 12345, + vatDetail { + { + country 80, + percentage 70, + amount 10, + vatId "IUDGTE" + } + }, + infoText "car carriage", + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket openTicket : { + referenceNum 810123456789, + referenceIA5 "810123456789", + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + extIssuerId 12, + issuerAutorizationId 13, + returnIncluded FALSE, + stationCodeTable stationERA, + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + validRegionDesc "From A to B via C", + validRegion + { + viaStations { + route { + { + stationNum 123455, + stationIA5 "123455", + border FALSE + }, + { stationNum 123456, border FALSE }, + { alternativeRoutes { + { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE }, + { route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE } + }, + border FALSE + }, + { stationNum 123457, border FALSE } + }, + border FALSE, + seriesId 999, + routeId 21, + includedServiceBrands { 108, 118 }, + excludedServiceBrands { 108, 118 } + }, + zones { + carrierNum 1080, + carrierIA5 "1080", + stationCodeTable stationERA, + entryStationNum 1234, + entryStationIA5 "1234", + terminatingStationNum 2345, + terminatingStationIA5 "2345", + city 123456, + zoneId {100,200}, + binaryZoneId '82DA'H, + nutsCode "DE4711" + }, + lines { + carrierNum 1080, + carrierIA5 "1080", + lineId {100,200}, + stationCodeTable stationERA, + entryStationNum 1234, + entryStationIA5 "1234", + terminatingStationNum 2345, + terminatingStationIA5 "2345", + city 123456 + }, + trainLink { + trainNum 12345, + trainIA5 "12345", + travelDate 2, + departureTime 1439, + departureUTCOffset -60, + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION" + }, + polygone { + firstEdge { + longitude 12345, + latitude 56789 + } + edges { + {longitude 12345, latitude 56789 }, + {longitude 12345, latitude 56789 } + } + } + }, + returnDescription { + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + validReturnRegionDesc "return", + validReturnRegion + { + zones { + carrierNum 1080, + carrierIA5 "1080", + stationCodeTable stationERA, + zoneId {100,200} + } + } + }, + validFromDay 700, + validFromTime 0, + validFromUTCOffset 60, + validUntilDay 370, + validUntilTime 1439, + validUntilUTCOffset 10, + activatedDay { 1 , 2 }, + classCode first + serviceLevel "A", + carrierNum { 1080, 1181 }, + carrierIA5 { "1080", "1181" }, + includedServiceBrands { 108, 118 }, + excludedServiceBrands { 108, 118 }, + tariffs { + { + numberOfPassengers 1, + restrictedToCountryOfResidence FALSE, + tariffIdNum 72, + tariffDesc "Large Car Full Fare" + } + }, + price 12345, + vatDetail {{ country 80, percentage 70 }}, + infoText "openTicketInfo" + includedAddOns { + { + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + externalIssuerId 12, + issuerAutorizationId 13, + stationCodeTable stationERA, + validRegion { zones { zoneId { 100 } } }, + validFromDay 0, + validFromTime 1000, + validUntilDay 1, + validUntilTime 1000, + classCode second, + serviceLevel "A", + carrierNum { 1080, 1181 }, + carrierIA5 { "1080", "1181" }, + includedServiceBrands { 108, 118 }, + excludedServiceBrands { 108, 118 }, + tariffs { + { + numberOfPassengers 1, + restrictedToCountryOfResidence FALSE, + tariffIdNum 72, + tariffDesc "Large Car Full Fare" + } + }, + infoText "included ticket", + includedTransportType { 10, 11 }, + excludedTransportType { 10, 18 }, + extension {extensionId "1", extensionData '82DA'H} + } + }, + luggage { maxHandLuggagePieces 2, maxNonHandLuggagePieces 1}, + includedTransportType { 10, 11 }, + excludedTransportType { 10, 18 }, + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket pass : { + referenceNum 810123456789, + referenceIA5 "810123456789", + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + passType 2, + passDescription "Eurail FlexPass", + classCode first, + validFromDay 0, + validFromTime 1000, + validFromUTCOffset 1, + validUntilDay 1, + validUntilTime 1000, + validUntilUTCOffset 1, + validityPeriodDetails { + validityPeriod { + { + validFromDay 0, + validFromTime 1000, + validFromUTCOffset 1, + validUntilDay 1, + validUntilTime 1000, + validUntilUTCOffset 1 + } + }, + excludedTimeRange { + { + fromTime 6, + untilTime 9 + } + } + }, + numberOfValidityDays 5, + numberOfPossibleTrips 3, + numberOfDaysOfTravel 10, + activatedDay {200, 201}, + countries {10, 20}, + includedCarrierNum { 1080, 1181 }, + includedCarrierIA5 { "1080", "1181" }, + excludedCarrierNum { 1080, 1181 }, + excludedCarrierIA5 { "1080", "1181" }, + includedServiceBrands { 108, 118 }, + excludedServiceBrands { 108, 118 }, + validRegion { zones { zoneId { 100 } } }, + tariffs { + { + numberOfPassengers 1, + restrictedToCountryOfResidence FALSE, + tariffIdNum 72, + tariffDesc "Large Car Full Fare" + } + }, + price 10000, + vatDetail { + { country 80, + percentage 70, + amount 10, + vatId "IUDGTE" + } + }, + infoText "pass info", + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket voucher : { + referenceIA5 "810123456789", + referenceNum 810123456789, + productOwnerNum 23456, + productOwnerIA5 "COFFEEMACHINE", + productIdNum 32000, + productIdIA5 "123456", + validFromYear 2022, + validFromDay 1, + validUntilYear 2022, + validUntilDay 1, + value 500, + type 123, + infoText "coffee voucher", + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket customerCard : { + customer { + customerIdIA5 "1234", + ticketHolder FALSE, + passengerType senior + }, + cardIdIA5 "2345", + cardIdNum 123456, + validFromYear 2269, + validFromDay 2, + validUntilYear 1, + validUntilDay 5, + classCode second, + cardType 15, + cardTypeDescr "RAILPLUS", + customerStatus 1, + customerStatusDescr "gold", + includedServices { 1 , 2 }, + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket counterMark : { + referenceIA5 "810123456789", + referenceNum 810123456789, + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + ticketReferenceIA5 "810123456789", + ticketReferenceNum 810123456789, + numberOfCountermark 12, + totalOfCountermarks 24, + groupName "groupName", + stationCodeTable stationERA, + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + validRegionDesc "From A to B via C", + validRegion { + viaStations { + route { + { + stationNum 123455, + stationIA5 "123455", + border FALSE + }, + { stationNum 123456, border FALSE }, + { alternativeRoutes { + { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE }, + { route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE } + }, + border FALSE + }, + { stationNum 123457, border FALSE } + }, + border FALSE, + carrierNum { 1080, 1181 }, + carrierIA5 { "1080", "1181" }, + seriesId 999, + routeId 21 + } + }, + returnIncluded FALSE, + returnDescription { + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + validReturnRegionDesc "return", + validReturnRegion { + zones { + carrierNum 1080, + carrierIA5 "1181", + stationCodeTable stationERA, + zoneId {100,200} + } + } + }, + validFromDay 700, + validFromTime 0, + validFromUTCOffset 60, + validUntilDay 370, + validUntilTime 1439, + validUntilUTCOffset 10, + classCode first + carrierNum { 1080, 1181 }, + carrierIA5 { "1080", "1181" }, + includedServiceBrands { 108, 118 }, + excludedServiceBrands { 108, 118 }, + infoText "counterMark", + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket parkingGround : { + referenceIA5 "810123456789", + referenceNum 810123456789, + parkingGroundId "IA5", + fromParkingDate 370, + untilParkingDate 370, + + + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + accessCode "4ga" + location "Parking Frankfurt Main West", + stationCodeTable stationUIC, + stationNum 8000001, + stationIA5 "8000001", + specialInformation "outdoor parking", + entryTrack "left", + numberPlate "AA-DE-12345", + price 500, + vatDetail { + { country 80, + percentage 70, + amount 10, + vatId "IUDGTE" + } + }, + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket fipTicket : { + referenceIA5 "810123456789", + referenceNum 810123456789, + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + validFromDay -367, + validUntilDay -1, + activatedDay {1,13,14,15}, + carrierNum { 1080, 1181 }, + carrierIA5 { "1080", "1181" }, + numberOfTravelDays 8, + includesSupplements TRUE, + classCode first, + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket stationPassage : { + referenceIA5 "810123456789", + referenceNum 810123456789, + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + productName "passage", + stationCodeTable stationUIC, + stationNum {8200001}, + stationIA5 {"AMS"}, + stationNameUTF8 {"Amsterdam"}, + areaCodeNum {8200001}, + areaCodeIA5 {"AMS"}, + areaNameUTF8 {"Amsterdam"}, + validFromDay 5, + validFromTime 0, + validFromUTCOffset 1, + validUntilDay 5, + validUntilTime 1000, + validUntilUTCOffset 1, + numberOfDaysValid 5 + extension {extensionId "1", extensionData '82DA'H} + } + }, + { + ticket extension : { + extensionId "1", + extensionData '82DA'H + } + }, + { + ticket delayConfirmation : { + referenceIA5 "ABDJ12345", + referenceNum 12345, + trainNum 100, + trainIA5 "100", + departureYear 2022, + departureDay 12, + departureTime 1000, + departureUTCOffset 30, + stationCodeTable stationUIC, + stationNum 8000001, + stationIA5 "DJE" + delay 31, + trainCancelled FALSE, + confirmationType travelerDelayConfirmation, + affectedTickets { + { + referenceIA5 "KDJET", + referenceNum 801234567890, + issuerName "XYZ", + issuerPNR "LDWDUR45", + productOwnerNum 1080, + productOwnerIA5 "IEFHU", + ticketType openTicket, + linkMode issuedTogether + } + }, + infoText "delay confirmation", + extension {extensionId "1", extensionData '82DA'H} + } + } + }, + controlDetail { + identificationByCardReference { + { + cardIssuerNum 1234, + cardIssuerIA5 "1234", + cardIdNum 5678, + cardIdIA5 "5678", + cardName "testcard", + cardType 123, + leadingCardIdNum 3456, + leadingCardIdIA5 "3456", + trailingCardIdNum 100, + trailingCardIdIA5 "100" + } + }, + identificationByIdCard FALSE, + identificationByPassportId FALSE + identificationItem 12, + passportValidationRequired FALSE, + onlineValidationRequired FALSE, + randomDetailedValidationRequired 50, + ageCheckRequired FALSE , + reductionCardCheckRequired FALSE, + infoText "control", + includedTickets { + { + referenceIA5 "KDJET", + referenceNum 801234567890, + issuerName "XYZ", + issuerPNR "LDWDUR45", + productOwnerNum 1080, + productOwnerIA5 "IEFHU", + ticketType openTicket, + linkMode issuedTogether + } + }, + extension {extensionId "1", extensionData '82DA'H} + }, + extension { + { extensionId "1", extensionData '82DA'H }, + { extensionId "2", extensionData '83DA'H } + } + } \ No newline at end of file diff --git a/misc/uicRailTicketData_v1.3.1_a.data b/misc/uicRailTicketData_v1.3.1_a.data new file mode 100644 index 0000000..49729eb --- /dev/null +++ b/misc/uicRailTicketData_v1.3.1_a.data @@ -0,0 +1,245 @@ +value UicRailTicketData ::= { + issuingDetail { + securityProviderNum 1, + securityProviderIA5 "1", + issuerNum 32000, + issuerIA5 "1", + issuingYear 2018, + issuingDay 1, + issuingTime 600, + issuerName "name", + specimen TRUE, + securePaperTicket FALSE, + activated TRUE, + currency "SRF", + currencyFract 3, + issuerPNR "issuerTestPNR", + extension { extensionId "1", extensionData '82DA'H }, + issuedOnTrainNum 123, + issuedOnTrainIA5 "123", + issuedOnLine 12, + pointOfSale { + geoUnit microDegree, + coordinateSystem wgs84 + hemisphereLongitude north, + hemisphereLatitude east, + longitude 12345, + latitude 56789, + accuracy microDegree + } + }, + travelerDetail{ + traveler { + { + firstName "John", + secondName "Little", + lastName "Dow", + idCard "12345", + passportId "JDTS", + title "PhD", + gender male, + customerIdIA5 "DZE5gT", + customerIdNum 12345, + yearOfBirth 1901, + dayOfBirth 331, + ticketHolder TRUE, + passengerType senior, + passengerWithReducedMobility FALSE, + countryOfResidence 101, + countryOfPassport 102, + countryOfIdCard 103, + status { + {customerStatus 1, customerStatusDescr "senior" } + } + } + }, + preferredLanguage "EN", + groupName "myGroup" + }, + transportDocument { + { + ticket reservation : { + trainNum 12345, + trainIA5 "12345", + departureDate 2, + referenceIA5 "810123456789", + referenceNum 80123456789, + productOwnerNum 23456, + productOwnerIA5 "23456", + productIdNum 32000, + productIdIA5 "123456", + serviceBrand 12, + serviceBrandAbrUTF8 "TGV", + serviceBrandNameUTF8 "Lyria", + service couchette, + stationCodeTable stationUIC, + fromStationNum 8100001, + fromStationIA5 "8100001", + toStationNum 8000002, + toStationIA5 "8100002", + fromStationNameUTF8 "A-STATION", + toStationNameUTF8 "B-STATION", + departureTime 1439, + departureUTCOffset -60, + arrivalDate 20, + arrivalTime 0, + arrivalUTCOffset 10, + carrierNum {1080, 1181}, + carrierIA5 {"1080", "1181"}, + classCode first, + serviceLevel "A", + places { + coach "31A", + placeString "31-47", + placeDescription "Window", + placeIA5 {"31A", "31B"}, + placeNum {31, 32} + }, + additionalPlaces { + coach "31A", + placeString "31-47", + placeDescription "Window", + placeIA5 {"31A", "31B"}, + placeNum {31, 32} + }, + bicyclePlaces { + coach "31A", + placeString "31-47", + placeDescription "Window", + placeIA5 {"31A", "31B"}, + placeNum {31, 32} + }, + compartmentDetails { + coachType 1, + compartmentType 99, + specialAllocation 50, + coachTypeDescr "xwz", + compartmentTypeDescr "xwz", + specialAllocationDescr "xwz", + position upperLevel + }, + numberOfOverbooked 200, + berth { + { + berthType single, + numberOfBerths 999, + gender female + } + }, + tariff { + { + numberOfPassengers 1, + passengerType senior, + ageBelow 64, + ageAbove 60, + travelerid { 1 }, + restrictedToCountryOfResidence FALSE, + restrictedToRouteSection { + stationCodeTable stationERA, + fromStationNum 123, + fromStationIA5 "123", + toStationNum 234, + toStationIA5 "234", + fromStationNameUTF8 "A", + toStationNameUTF8 "B" + }, + seriesDataDetails { + supplyingCarrier 12345, + offerIdentification 99, + series 23456 + }, + tariffIdNum 72, + tariffIdIA5 "72", + tariffDesc "Leasure Fare", + reductionCard { + { + cardIssuerNum 1234, + cardIssuerIA5 "1234", + cardIdNum 5678, + cardIdIA5 "5678", + cardName "testcard", + cardType 123, + leadingCardIdNum 3456, + leadingCardIdIA5 "3456", + trailingCardIdNum 100, + trailingCardIdIA5 "100" + } + } + } + }, + priceType travelPrice, + price 12345, + vatDetail { + { + country 80, + percentage 70, + amount 10, + vatId "IUDGTE" + } + }, + typeOfSupplement 9, + numberOfSupplements 2, + luggage { + maxHandLuggagePieces 2, + maxNonHandLuggagePieces 1, + registeredLuggage { + { + registrationId "IODHUV", + maxWeight 20, + maxSize 100 + }, + { + registrationId "XXDHUV", + maxWeight 21, + maxSize 101 + } + } + }, + infoText "reservation", + extension {extensionId "1", extensionData '82DA'H} + } + } + }, + controlDetail { + identificationByCardReference { + { + cardIssuerNum 1234, + cardIssuerIA5 "1234", + cardIdNum 5678, + cardIdIA5 "5678", + cardName "testcard", + cardType 123, + leadingCardIdNum 3456, + leadingCardIdIA5 "3456", + trailingCardIdNum 100, + trailingCardIdIA5 "100" + } + }, + identificationByIdCard FALSE, + identificationByPassportId FALSE + identificationItem 12, + passportValidationRequired FALSE, + onlineValidationRequired FALSE, + randomDetailedValidationRequired 50, + ageCheckRequired FALSE , + reductionCardCheckRequired FALSE, + infoText "control", + includedTickets { + { + referenceIA5 "KDJET", + referenceNum 801234567890, + issuerName "XYZ", + issuerPNR "LDWDUR45", + productOwnerNum 1080, + productOwnerIA5 "IEFHU", + ticketType openTicket, + linkMode issuedTogether + } + }, + extension {extensionId "1", extensionData '82DA'H} + }, + extension { + { extensionId "1", extensionData '82DA'H }, + { extensionId "2", extensionData '83DA'H } + } + } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 033cd38..d4ef4cc 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.uic.barcode org.uic.barcode - 1.2.13-SNAPSHOT + 1.3.1-SNAPSHOT jar UIC barcode encoding and decoding of bar code content according to UIC IRS 90918-9 diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index 4c8b044..b980f19 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -10,11 +10,11 @@ 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.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.SimpleDynamicFrame; import org.uic.barcode.staticFrame.StaticFrame; import org.uic.barcode.staticFrame.UFLEXDataRecord; import org.uic.barcode.staticFrame.UTLAYDataRecord; @@ -34,7 +34,7 @@ public class Decoder { /** The dynamic frame. */ - private DynamicFrame dynamicFrame = null; + private IDynamicFrame dynamicFrame = null; /** The static frame. */ private StaticFrame staticFrame = null; @@ -123,8 +123,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 { @@ -137,7 +138,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 { @@ -157,24 +158,25 @@ public class Decoder { public void decode(byte[] data) throws IOException, EncodingFormatException, DataFormatException { if (!isStaticHeader(data)) { + + dynamicFrame = new SimpleDynamicFrame(); - dynamicFrame = DynamicFrame.decode(data); + dynamicFrame.decode(data); - Level2DataType level2 = dynamicFrame.getLevel2SignedData(); + ILevel2Data level2 = dynamicFrame.getLevel2Data(); - Level1DataType level1 = level2.getLevel1Data(); + ILevel1Data level1 = level2.getLevel1Data(); - SequenceOfDataType dataList = level1.getData(); - 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); } } @@ -234,7 +236,7 @@ public class Decoder { * * @return the dynamic header */ - public DynamicFrame getDynamicHeader() { + public IDynamicFrame getDynamicHeader() { return dynamicFrame; } @@ -254,7 +256,7 @@ public class Decoder { * * @param dynamicHeader the new dynamic header */ - public void setDynamicHeader(DynamicFrame dynamicHeader) { + public void setDynamicHeader(IDynamicFrame dynamicHeader) { this.dynamicFrame = dynamicHeader; } @@ -276,9 +278,9 @@ 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; } diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java index 3b30e8a..5f10806 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -5,15 +5,15 @@ import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; -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.IData; +import org.uic.barcode.dynamicFrame.api.IDynamicFrame; +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.staticFrame.StaticFrame; import org.uic.barcode.staticFrame.UFLEXDataRecord; import org.uic.barcode.staticFrame.UHEADDataRecord; @@ -34,7 +34,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; @@ -87,18 +87,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) { @@ -108,8 +109,8 @@ 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); } } @@ -151,8 +152,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); } } @@ -165,68 +166,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 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.addDynamicContent(content); } } - public void setLevel2Data(DataType level2data) { + public void setLevel2Data(IData level2data) { if (dynamicFrame != null) { - if (dynamicFrame.getLevel2SignedData() == null) { - dynamicFrame.setLevel2SignedData(new Level2DataType()); + if (dynamicFrame.getLevel2Data() == null) { + dynamicFrame.setLevel2Data(new SimpleLevel2Data()); } - dynamicFrame.getLevel2SignedData().setLevel2Data(level2data); + 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 IUicDynamicContent getDynamicContent() { - if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) { + if (dynamicFrame != null && dynamicFrame.getLevel2Data() != null) { return dynamicFrame.getDynamicContent(); } return null; } - public UicDynamicContentDataFDC1 getDynamicContentDataUIC1() { - if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) { - return dynamicFrame.getDynamicDataFDC1(); - } - return null; - } /** @@ -240,10 +235,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); @@ -266,10 +261,11 @@ 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); + //dynamicFrame.getLevel2Data().signLevel1(key, prov); } else if (staticFrame != null) { staticFrame.setSignatureKey(keyId); staticFrame.setSecurityProvider(securityProvider); @@ -299,7 +295,7 @@ public class Encoder { * * @return the dynamic frame */ - public DynamicFrame getDynamicFrame() { + public IDynamicFrame getDynamicFrame() { return dynamicFrame; } 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 a1b9581..c2cd8fa 100644 --- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java +++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java @@ -105,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()); 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 3ced173..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()); diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java index 8f47986..ba15f3f 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java @@ -36,4 +36,6 @@ 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"; } diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/DataType.java deleted file mode 100644 index 2ea63ca..0000000 --- a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.uic.barcode.dynamicFrame; - -import org.uic.barcode.asn1.datatypes.CharacterRestriction; -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) - public String format; - - /** The data. */ - 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/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java deleted file mode 100644 index eb26729..0000000 --- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java +++ /dev/null @@ -1,429 +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.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; - - -// TODO: Auto-generated Javadoc -/** - * 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); - } - - /** - * Verify the level 2 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @return the int - */ - public int validateLevel2() { - - return validateLevel2(null); - - } - - /** - * Verify the level 2 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @param prov the prov - * @return the int - */ - 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 - * - * @param key the key - * @param prov the prov - * @return the int - */ - 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 - * - * @param key the key - * @return the int - */ - public int validateLevel1(PublicKey key) { - - return validateLevel1(key, null); - - } - - /** - * 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) { - this.getLevel2SignedData().setLevel2Data( dynamicData.getDataType()); - } - - /** - * 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/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java deleted file mode 100644 index 958cafc..0000000 --- a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.uic.barcode.dynamicFrame; - -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; - - @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; - - @FieldOrder(order = 7) - @RestrictedString(CharacterRestriction.ObjectIdentifier) - @Asn1Optional public String level2SigningAlg; - - - /** The level 2 public key*/ - @FieldOrder(order = 8) - @Asn1Optional public OctetString level2publicKey; - - - - /** - * 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; - } - - public Long getKeyId() { - return keyId; - } - - public void setKeyId(Long keyId) { - this.keyId = keyId; - } - - public SequenceOfDataType getData() { - return data; - } - - public void setData(SequenceOfDataType data) { - this.data = data; - } - - public String getLevel2KeyAlg() { - return level2KeyAlg; - } - - public void setLevel2KeyAlg(String level2KeyAlg) { - this.level2KeyAlg = level2KeyAlg; - } - - public String getLevel1SigningAlg() { - return level1SigningAlg; - } - - public void setLevel1SigningAlg(String level1SigningAlg) { - this.level1SigningAlg = level1SigningAlg; - } - - public String getLevel2SigningAlg() { - return level2SigningAlg; - } - - public void setLevel2SigningAlg(String level2SigningAlg) { - this.level2SigningAlg = level2SigningAlg; - } - - public OctetString getLevel2publicKey() { - return level2publicKey; - } - - public void setLevel2publicKey(OctetString level2publicKey) { - this.level2publicKey = level2publicKey; - } - - - - public String getLevel1KeyAlg() { - return level1KeyAlg; - } - - public void setLevel1KeyAlg(String level1KeyAlg) { - this.level1KeyAlg = level1KeyAlg; - } - - /** - * 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/Level2DataType.java deleted file mode 100644 index 8c3cd60..0000000 --- a/src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.uic.barcode.dynamicFrame; - -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.FieldOrder; -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.utils.AlgorithmNameResolver; - -/** - * 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); - } - - /** - * 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 - */ - public void signLevel1(PrivateKey key) throws Exception { - //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel1Data().level1SigningAlg); - Signature sig = Signature.getInstance(algo); - sig.initSign(key); - byte[] data = level1Data.encode(); - sig.update(data); - this.level1Signature = new OctetString(sig.sign()); - } - - /** - * 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 - */ - public void signLevel1(PrivateKey key, Provider prov) throws Exception { - //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel1Data().level1SigningAlg); - Signature sig = Signature.getInstance(algo, prov); - sig.initSign(key); - byte[] data = level1Data.encode(); - sig.update(data); - this.level1Signature = new OctetString(sig.sign()); - } - - -} diff --git a/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java b/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java deleted file mode 100644 index b5c130e..0000000 --- a/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.uic.barcode.dynamicFrame; - - -import java.util.Collection; - -import org.uic.barcode.asn1.datatypes.Asn1SequenceOf; - -/** - * The Class SequenceOfDataType. - */ -public class SequenceOfDataType extends Asn1SequenceOf{ - - /** - * Instantiates a new sequence of data type. - */ - public SequenceOfDataType() { super(); } - - /** - * Instantiates a new sequence of data type. - * - * @param coll the coll - */ - public SequenceOfDataType(Collection coll) { super(coll); } - -} 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..f357c4d --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java @@ -0,0 +1,202 @@ +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 level2SignedData the new level 2 signed 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); + + + /** + * Encode. + * + * Encode the header as ASN.1 PER UNALIGNED byte array + * + * @return the byte[] + * @throws EncodingFormatException + */ + public byte[] encode() throws EncodingFormatException; + + /** + * Decode. + * + * Decode the header from an ASN.1 PER UNALIGNED encoded byte array + * + * @param bytes the bytes + * @return the dynamic header + */ + public void decode(byte[] bytes); + + + + /** + * Verify the level 2 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @return the int + * @throws EncodingFormatException + */ + 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 prov + * @return the int + * @throws EncodingFormatException + */ + 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 prov the prov + * @return the int + * @throws EncodingFormatException + */ + 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 + * @return the int + * @throws EncodingFormatException + */ + public int validateLevel1(PublicKey key) 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 key + * @return + * @return the byte[] + * @throws 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 key + * @param security provider - security provider that must be sued to create the signature + * @return + * @return the byte[] + * @throws Exception + */ + public void signLevel1(PrivateKey key, Provider prov) throws Exception; + + + +} 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..206d613 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java @@ -0,0 +1,164 @@ +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 securityProviderNum 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 getData(); + + + /** + * Sets the data. + * + * @param data the new data + */ + public void setData(Collection data); + + /** + * Adds data. + * + * @param data the new data + */ + public void addData(IData data); + + /** + * Gets the level 2 key alg. + * + * @return the level 2 key alg + */ + public String getLevel2KeyAlg(); + + + /** + * Sets the level 2 key alg. + * + * @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 alg. + * + * @param level1SigningAlg the new level 1 signing alg + */ + public void setLevel1SigningAlg(String level1SigningAlg); + + + /** + * Gets the level 2 signing alg. + * + * @return the level 2 signing alg + */ + public String getLevel2SigningAlg(); + + + /** + * Sets the level 2 signing alg. + * + * @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 alg. + * + * @return the level 1 key alg + */ + public String getLevel1KeyAlg(); + + /** + * Sets the level 1 key alg. + * + * @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. + * + * @param date the new end of validity date + */ + public void setEndOfBarcodeValidity(Date date); + + + /** + * Gets the end of validity date. + * + * @return the end of validity date + */ + public Date getEndOfBarcodeValidity(); +} 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..cb762de --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java @@ -0,0 +1,59 @@ +package org.uic.barcode.dynamicFrame.api; + +import org.uic.barcode.asn1.datatypes.CharacterRestriction; +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.datatypesimpl.OctetString; +import org.uic.barcode.asn1.uper.UperEncoder; + +/** + * 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..4c5c879 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java @@ -0,0 +1,553 @@ +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 = Constants.DYNAMIC_BARCODE_FORMAT_DEFAULT; + + /** 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 + */ + 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 ILevel2Data getLevel2Data() { + return level2Data; + } + + /** + * Sets the level 2 signed data. + * + * @param level2SignedData the new level 2 signed data + */ + public void setLevel2Data(ILevel2Data level2SignedData) { + this.level2Data = level2SignedData; + } + + /** + * Gets the level 2 signature. + * + * @return the level 2 signature + */ + public byte[] getLevel2Signature() { + return level2Signature; + } + + /** + * Sets the level 2 signature. + * + * @param level2Signature the new level 2 signature + */ + public void setLevel2Signature(byte[] level2Signature) { + this.level2Signature = level2Signature; + } + + /** + * Encode. + * + * Encode the header as ASN.1 PER UNALIGNED byte array + * + * @return the byte[] + * @throws EncodingFormatException + */ + public byte[] encode() throws EncodingFormatException { + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV1.encode(this); + + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV2.encode(this); + + } + + return null; + } + + private byte[] encode(ILevel1Data level1Data) throws EncodingFormatException { + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV1.encode(level1Data); + + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV2.encode(level1Data); + + } + + return null; + } + + private byte[] encode(ILevel2Data level2SignedData2) throws EncodingFormatException { + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV1.encode(level2SignedData2); + + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV2.encode(level2SignedData2); + + } + + return null; + } + + /** + * Decode. + * + * Decode the header from an ASN.1 PER UNALIGNED encoded byte array + * + * @param bytes the bytes + * @return the dynamic header + */ + public void decode(byte[] bytes) { + + String format = getFormat(bytes); + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + DynamicFrameCoderV1.decode(this,bytes); + + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { + + DynamicFrameCoderV2.decode(this,bytes); + + } + + + + } + + + + + /** + * Checks if is static header. + * + * @param data the data + * @return true, if is static header + */ + private static String getFormat(byte[] data) { + byte[] start = "U1".getBytes(); + if (start[0] != data[0] || start[1]!= start[1]) { + return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1; + } + start = "U2".getBytes(); + if (start[0] != data[0] || start[1]!= start[1]) { + return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2; + } + return null; + } + + /** + * Verify the level 2 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @return the int + * @throws EncodingFormatException + */ + 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 prov + * @return the int + * @throws EncodingFormatException + */ + public int validateLevel2(Provider prov) throws EncodingFormatException { + + + String level2KeyAlg = this.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); + } 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); + } 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 = encode(level2Data); + 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; + 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 + * + * @param key the key + * @param prov the prov + * @return the int + * @throws EncodingFormatException + */ + public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException { + + if (level2Data == null) { + return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; + } + + + if (level2Data == null || + level2Data.getLevel1Signature().length == 0) { + return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; + } + + byte[] signature = this.getLevel2Data().getLevel1Signature(); + + //find the algorithm name for the signature OID + String algo = null; + try { + algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2Data().getLevel1Data().getLevel1SigningAlg()); + } 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(encode(level2Data.getLevel1Data())); + } 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 + * + * @param key the key + * @return the int + * @throws EncodingFormatException + */ + public int validateLevel1(PublicKey key) throws EncodingFormatException { + + return validateLevel1(key, null); + + } + + /** + * 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(level2Data.getLevel1Data().getLevel2SigningAlg()); + Signature sig = Signature.getInstance(algo); + sig.initSign(key); + byte[] data = encode(level2Data); + sig.update(data); + level2Signature = sig.sign(); + + } + + /** + * 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.getLevel2Data().getLevel1Data().getLevel2SigningAlg()); + Signature sig = Signature.getInstance(algo,prov); + sig.initSign(key); + byte[] data = encode(level2Data); + sig.update(data); + level2Signature = 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 { + + + 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 + */ + public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) { + this.getLevel2Data().setLevel2Data(dynamicData.getApiDataType()); + } + + /** + * Gets the dynamic content. + * + * @return the dynamic content + */ + 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 + */ + public void signLevel1(PrivateKey key) 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 = Signature.getInstance(algo); + sig.initSign(key); + byte[] data = encode(level1Data); + sig.update(data); + level2Data.setLevel1Signature(sig.sign()); + } + + /** + * 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 = Signature.getInstance(algo, prov); + sig.initSign(key); + + byte[] data = encode(level1Data); + sig.update(data); + level2Data.setLevel1Signature(sig.sign()); + } + + + + + +} 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..241cf6d --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java @@ -0,0 +1,254 @@ +package org.uic.barcode.dynamicFrame.api; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import org.uic.barcode.asn1.uper.UperEncoder; + +/** + * The Class SignedDataType. + */ + +public class SimpleLevel1Data implements ILevel1Data { + + /** The security provider */ + public String securityProvider; + + + /** The key id. */ + public Long keyId; + + + /** The data. */ + public Collection 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; + + + + + + /** + * 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 getData() { + return dataList; + } + + /** + * Sets the data. + * + * @param data the new data + */ + public void setData(Collection 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(); + } + + dataList.add(data); + + } +} 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..395db4d --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java @@ -0,0 +1,75 @@ +package org.uic.barcode.dynamicFrame.api; + +import org.uic.barcode.asn1.datatypes.Asn1Optional; +import org.uic.barcode.asn1.datatypes.FieldOrder; +import org.uic.barcode.asn1.datatypes.HasExtensionMarker; +import org.uic.barcode.asn1.datatypes.Sequence; +import org.uic.barcode.asn1.uper.UperEncoder; + +/** + * The Class DataType. + */ +@Sequence +@HasExtensionMarker +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; + } + + + /** + * 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/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 @@ - - - - - -

drafted new header for dynamic content

-

Provides a decoding and encoding of the header data frame. (Draft for UIC IRS 90918-9).

- - \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java new file mode 100644 index 0000000..6195b3c --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java @@ -0,0 +1,93 @@ +package org.uic.barcode.dynamicFrame.v1; + +import org.uic.barcode.asn1.datatypes.CharacterRestriction; +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) + public String format; + + /** The data. */ + 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/v1/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java new file mode 100644 index 0000000..3af9c8f --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java @@ -0,0 +1,432 @@ +package org.uic.barcode.dynamicFrame.v1; + +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.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.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); + } + + /** + * Verify the level 2 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @return the int + */ + public int validateLevel2() { + + return validateLevel2(null); + + } + + /** + * Verify the level 2 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @param prov the prov + * @return the int + */ + 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 + * + * @param key the key + * @param prov the prov + * @return the int + */ + 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 + * + * @param key the key + * @return the int + */ + public int validateLevel1(PublicKey key) { + + return validateLevel1(key, null); + + } + + /** + * 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..f7b3f3d --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java @@ -0,0 +1,189 @@ +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.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()); + } + + } + + 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[] encode(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); + + } + + } + + return asnLevel1; + } + + + +} diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java new file mode 100644 index 0000000..5104c50 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java @@ -0,0 +1,226 @@ +package org.uic.barcode.dynamicFrame.v1; + +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; + + @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; + + @FieldOrder(order = 7) + @RestrictedString(CharacterRestriction.ObjectIdentifier) + @Asn1Optional public String level2SigningAlg; + + + /** The level 2 public key*/ + @FieldOrder(order = 8) + @Asn1Optional public OctetString level2publicKey; + + + + /** + * 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; + } + + public Long getKeyId() { + return keyId; + } + + public void setKeyId(Long keyId) { + this.keyId = keyId; + } + + public SequenceOfDataType getData() { + return data; + } + + public void setData(SequenceOfDataType data) { + this.data = data; + } + + public String getLevel2KeyAlg() { + return level2KeyAlg; + } + + public void setLevel2KeyAlg(String level2KeyAlg) { + this.level2KeyAlg = level2KeyAlg; + } + + public String getLevel1SigningAlg() { + return level1SigningAlg; + } + + public void setLevel1SigningAlg(String level1SigningAlg) { + this.level1SigningAlg = level1SigningAlg; + } + + public String getLevel2SigningAlg() { + return level2SigningAlg; + } + + public void setLevel2SigningAlg(String level2SigningAlg) { + this.level2SigningAlg = level2SigningAlg; + } + + public OctetString getLevel2publicKey() { + return level2publicKey; + } + + public void setLevel2publicKey(OctetString level2publicKey) { + this.level2publicKey = level2publicKey; + } + + + + public String getLevel1KeyAlg() { + return level1KeyAlg; + } + + public void setLevel1KeyAlg(String level1KeyAlg) { + this.level1KeyAlg = level1KeyAlg; + } + + /** + * 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/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/v1/SequenceOfDataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java new file mode 100644 index 0000000..be0bf95 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java @@ -0,0 +1,25 @@ +package org.uic.barcode.dynamicFrame.v1; + + +import java.util.Collection; + +import org.uic.barcode.asn1.datatypes.Asn1SequenceOf; + +/** + * The Class SequenceOfDataType. + */ +public class SequenceOfDataType extends Asn1SequenceOf{ + + /** + * Instantiates a new sequence of data type. + */ + public SequenceOfDataType() { super(); } + + /** + * Instantiates a new sequence of data type. + * + * @param coll the coll + */ + public SequenceOfDataType(Collection coll) { super(coll); } + +} 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..f94b622 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java @@ -0,0 +1,95 @@ +package org.uic.barcode.dynamicFrame.v2; + +import org.uic.barcode.asn1.datatypes.CharacterRestriction; +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.datatypesimpl.OctetString; +import org.uic.barcode.asn1.uper.UperEncoder; + +/** + * The Class DataType. + */ +@Sequence +@HasExtensionMarker +public class DataType { + + + /** The data format. + * + * -- FCB1 FCB version 1 + * -- FCB2 FCB version 2 + * -- RICS company code + ... + **/ + @RestrictedString(CharacterRestriction.IA5String) + public String format; + + /** The data. */ + 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..2986f75 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java @@ -0,0 +1,434 @@ +package org.uic.barcode.dynamicFrame.v2; + +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.HasExtensionMarker; +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.dynamicFrame.Constants; +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 +@HasExtensionMarker +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); + } + + /** + * Verify the level 2 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @return the int + */ + public int validateLevel2() { + + return validateLevel2(null); + + } + + /** + * Verify the level 2 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @param prov the prov + * @return the int + */ + 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 + * + * @param key the key + * @param prov the prov + * @return the int + */ + 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 + * + * @param key the key + * @return the int + */ + public int validateLevel1(PublicKey key) { + + return validateLevel1(key, null); + + } + + /** + * 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..8987f59 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java @@ -0,0 +1,203 @@ +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()); + } + + } + + 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()); + } + + 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[] encode(ILevel2Data level2SignedData) throws EncodingFormatException { + + Level2DataType asn = populateAsn(level2SignedData); + + return UperEncoder.encode(asn); + } + + private static DynamicFrame populateAsn(IDynamicFrame frame) throws EncodingFormatException { + + DynamicFrame asnFrame = new DynamicFrame(); + + frame.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()); + + + return asnLevel1; + } + + + +} 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..1dff709 --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java @@ -0,0 +1,374 @@ +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.HasExtensionMarker; +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; + +// TODO: Auto-generated Javadoc +/** + * The Class SignedDataType. + */ +@Sequence +@HasExtensionMarker +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) + public Long EndOfValidityYear; + + /** The End of validity day. */ + @FieldOrder(order = 10) + @IntRange(minValue=1,maxValue=366) + public Long EndOfValidityDay; + + /** The End of validity time. */ + @FieldOrder(order = 11) + @IntRange(minValue=0,maxValue=1440) + @Asn1Optional public Long EndOfValidityTime; + + + + + + /** + * 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. The validity date has to be provided in UTC. + * + * @param date the new end of validity date + */ + public void setEndOfValidityDate(Date date){ + + if (date == null) { + date = Calendar.getInstance().getTime(); + } + + 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 ); + } + + } + + /** + * Gets the end of validity date. + * + * @return the end of validity date + */ + public Date getEndOfValidityDate() { + + if (this.EndOfValidityYear == null || this.EndOfValidityDay == null) return null; + + 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(); + return d; + } + + /** + * 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/v2/Level2DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java new file mode 100644 index 0000000..6534c4d --- /dev/null +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java @@ -0,0 +1,123 @@ +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.FieldOrder; +import org.uic.barcode.asn1.datatypes.HasExtensionMarker; +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.utils.AlgorithmNameResolver; + +/** + * The Class DataType. + */ +@Sequence +@HasExtensionMarker +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); + } + + /** + * 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 + */ + public void signLevel1(PrivateKey key) throws Exception { + //find the algorithm name for the signature OID + String algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel1Data().level1SigningAlg); + Signature sig = Signature.getInstance(algo); + sig.initSign(key); + byte[] data = level1Data.encode(); + sig.update(data); + this.level1Signature = new OctetString(sig.sign()); + } + + /** + * 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 + */ + public void signLevel1(PrivateKey key, Provider prov) throws Exception { + //find the algorithm name for the signature OID + String algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel1Data().level1SigningAlg); + Signature sig = Signature.getInstance(algo, prov); + sig.initSign(key); + byte[] data = level1Data.encode(); + sig.update(data); + this.level1Signature = new OctetString(sig.sign()); + } + + +} 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{ + + /** + * Instantiates a new sequence of data type. + */ + public SequenceOfDataType() { super(); } + + /** + * Instantiates a new sequence of data type. + * + * @param coll the coll + */ + public SequenceOfDataType(Collection coll) { super(coll); } + +} diff --git a/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java index 10963c5..5355d5d 100644 --- a/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java @@ -108,7 +108,7 @@ public class DynamicContentCoderTest { assert(content.getTimeStamp() != null); - assert(content.getTimeStamp().toString().equals("Wed Dec 15 12:30:00 CET 2021" )); + 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/DynamicFrameDynamicContentTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java index a5f91ca..4cfca12 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java @@ -24,6 +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.api.IUicDynamicContent; import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateType; import org.uic.barcode.dynamicContent.fdc1.TimeStamp; import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; @@ -217,7 +218,7 @@ public class DynamicFrameDynamicContentTest { assert(level2check == Constants.LEVEL2_VALIDATION_OK); - UicDynamicContentDataFDC1 dynamicData = dec.getDynamicHeader().getDynamicDataFDC1(); + IUicDynamicContent dynamicData = dec.getDynamicHeader().getDynamicContent(); assert(dynamicData.getChallengeString().equals("CHALLENGE")); @@ -228,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..861fc85 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; @@ -144,9 +145,10 @@ public class DynamicFrameFcbVersion1Test { assert(dec.getDynamicHeader().getFormat().equals("U1")); - assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB1")); - - + for (IData data : dec.getDynamicHeader().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..fa055dc 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; @@ -144,8 +145,9 @@ public class DynamicFrameFcbVersion3Test { assert(dec.getDynamicHeader().getFormat().equals("U1")); - assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB3")); - + for (IData data : dec.getDynamicHeader().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..d354837 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 { 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); } -- cgit v1.2.3 From 09f0f9449a10b713207126348105fafec4781bed Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Mon, 24 Jan 2022 16:51:04 +0100 Subject: signature validation changed to work with teh dynamic header version 2. --- src/main/java/org/uic/barcode/Decoder.java | 9 +- .../org/uic/barcode/asn1/uper/AsnExtractor.java | 80 +++++++++++++++ .../java/org/uic/barcode/asn1/uper/AsnUtils.java | 59 +++++++++++ .../java/org/uic/barcode/asn1/uper/BitBuffer.java | 1 + .../org/uic/barcode/asn1/uper/BitStringCoder.java | 2 +- .../org/uic/barcode/asn1/uper/BooleanCoder.java | 2 +- .../org/uic/barcode/asn1/uper/ByteBitBuffer.java | 30 ++++-- .../java/org/uic/barcode/asn1/uper/ByteCoder.java | 2 +- .../org/uic/barcode/asn1/uper/ChoiceCoder.java | 6 +- .../java/org/uic/barcode/asn1/uper/Decoder.java | 2 +- .../java/org/uic/barcode/asn1/uper/EnumCoder.java | 2 +- .../java/org/uic/barcode/asn1/uper/IntCoder.java | 2 +- .../java/org/uic/barcode/asn1/uper/SeqOfCoder.java | 4 +- .../org/uic/barcode/asn1/uper/SequenceCoder.java | 29 +++++- .../org/uic/barcode/asn1/uper/StringCoder.java | 2 +- .../org/uic/barcode/asn1/uper/UperEncoder.java | 46 +++++++-- .../barcode/dynamicFrame/api/IDynamicFrame.java | 26 ++--- .../dynamicFrame/api/SimpleDynamicFrame.java | 109 ++++++++++++--------- .../dynamicFrame/v1/DynamicFrameCoderV1.java | 15 +++ .../dynamicFrame/v2/DynamicFrameCoderV2.java | 11 +++ .../uic/barcode/utils/AlgorithmNameResolver.java | 37 ++++++- .../org/uic/barcode/test/BinaryStringTest.java | 61 ++++++++++++ .../test/DynamicFrameDynamicContentApiTest.java | 2 - 23 files changed, 443 insertions(+), 96 deletions(-) create mode 100644 src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java create mode 100644 src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java create mode 100644 src/test/java/org/uic/barcode/test/BinaryStringTest.java diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index b980f19..5cb0546 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -81,7 +81,7 @@ public class Decoder { */ public int validateLevel1(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel1(key) ; + return dynamicFrame.validateLevel1(key, data) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg)) { return Constants.LEVEL1_VALIDATION_OK; @@ -91,7 +91,6 @@ public class Decoder { } } - /** * Validate level 1. * @@ -109,7 +108,7 @@ public class Decoder { */ public int validateLevel1(PublicKey key, String signingAlg, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel1(key, provider) ; + return dynamicFrame.validateLevel1(key, provider, data) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg, provider)) { return Constants.LEVEL1_VALIDATION_OK; @@ -127,7 +126,7 @@ public class Decoder { */ public int validateLevel2() throws EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel2() ; + return dynamicFrame.validateLevel2(null, data) ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } @@ -140,7 +139,7 @@ public class Decoder { */ public int validateLevel2(Provider prov) throws EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel2(prov) ; + return dynamicFrame.validateLevel2(prov,data) ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } 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..dbb95c9 --- /dev/null +++ b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java @@ -0,0 +1,59 @@ +package org.uic.barcode.asn1.uper; + +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; + } + +} 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 { boolean canDecode(Class classOfT, Annotation[] extraAnnotations); - T decode(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations); + T decode(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations,AsnExtractor extractor); T getDefault(Class 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 decode(BitBuffer bitbuffer, Class 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 decode(byte[] bytes, Class 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 decode(byte[] bytes, Class 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 byte[] extract(byte[] bytes,String path,Class 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 decode(byte[] bytes, Class classOfT, Field f) throws IllegalArgumentException, + public static T decode(byte[] bytes, Class 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 decodeAny(BitBuffer bitbuffer,Class classOfT, Field f, Annotation[] extraAnnotations) { + static T decodeAny(BitBuffer bitbuffer,Class 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 decodeAsOpenType(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations) { + static T decodeAsOpenType(BitBuffer bitbuffer, Class 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/dynamicFrame/api/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java index f357c4d..1e8a0ff 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java @@ -89,21 +89,23 @@ public interface IDynamicFrame{ * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @return the int + * @param data the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2() throws EncodingFormatException; + public int validateLevel2(byte[] data) throws EncodingFormatException; /** * Verify the level 2 signature * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @param prov the prov - * @return the int + * @param prov the registered security provider + * @param data the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2(Provider prov) throws EncodingFormatException; + public int validateLevel2(Provider prov, byte[] data) throws EncodingFormatException; /** * Verify the level 1 signature @@ -111,23 +113,25 @@ public interface IDynamicFrame{ * Note: an appropriate security provider (e.g. BC) must be registered before * * @param key the key - * @param prov the prov - * @return the int + * @param data the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException; + public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException; - /** * Verify the level 1 signature * * Note: an appropriate security provider (e.g. BC) must be registered before * * @param key the key - * @return the int + * @param prov the registered security provider + * @param the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key) throws EncodingFormatException; + public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException; + /** * Sign level 2 data without a specific security provider. diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java index 4c5c879..ec52758 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java @@ -12,6 +12,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Date; +import org.uic.barcode.asn1.uper.AsnUtils; import org.uic.barcode.dynamicContent.api.DynamicContentCoder; import org.uic.barcode.dynamicContent.api.IUicDynamicContent; import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; @@ -143,6 +144,22 @@ public class SimpleDynamicFrame implements IDynamicFrame { return null; } + private byte[] getEncoded(String path, byte[] data) throws EncodingFormatException { + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV1.getEncoded(path, data); + + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV2.getEncoded(path, data); + + } + + return null; + } + + private byte[] encode(ILevel2Data level2SignedData2) throws EncodingFormatException { if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { @@ -213,9 +230,9 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel2() throws EncodingFormatException { + public int validateLevel2(byte[] data) throws EncodingFormatException { - return validateLevel2(null); + return validateLevel2(null, data); } @@ -224,11 +241,11 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @param prov the prov - * @return the int + * @param prov the registered security provider + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2(Provider prov) throws EncodingFormatException { + public int validateLevel2(Provider prov, byte[] data) throws EncodingFormatException { String level2KeyAlg = this.getLevel2Data().getLevel1Data().getLevel2KeyAlg(); @@ -244,7 +261,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { String keyAlgName = null; try { - keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg); + keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg,prov); } catch (Exception e1) { return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED; } @@ -268,7 +285,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { String sigAlgName = null; try { - sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg); + sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg,prov); } catch (Exception e1) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } @@ -293,8 +310,14 @@ public class SimpleDynamicFrame implements IDynamicFrame { } try { - byte[] data = encode(level2Data); - sig.update(data); + //TODO + //byte[] signedData = encode(level2Data); + //String s1 = AsnUtils.toBooleanString(signedData); + + byte[] signedData2 = getEncoded("Level2Data", data); + //String s2 = AsnUtils.toBooleanString(signedData); + + sig.update(signedData2); } catch (SignatureException e) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } catch (IllegalArgumentException e) { @@ -325,7 +348,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException { + public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException { if (level2Data == null) { return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; @@ -342,7 +365,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { //find the algorithm name for the signature OID String algo = null; try { - algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2Data().getLevel1Data().getLevel1SigningAlg()); + algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2Data().getLevel1Data().getLevel1SigningAlg(), prov); } catch (Exception e1) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } @@ -368,7 +391,15 @@ public class SimpleDynamicFrame implements IDynamicFrame { } try { - sig.update(encode(level2Data.getLevel1Data())); + + //byte[] encodedData = encode(level2Data.getLevel1Data()); + //String s1 = AsnUtils.toBooleanString(encodedData); + //TODO + byte[] encodedData2 = getEncoded("Level1Data", data); + //String s2 = AsnUtils.toBooleanString(encodedData2); + + sig.update(encodedData2); + } catch (SignatureException e) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } catch (IllegalArgumentException e) { @@ -402,9 +433,9 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key) throws EncodingFormatException { + public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException { - return validateLevel1(key, null); + return validateLevel1(key, null,data); } @@ -416,13 +447,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { */ public void signLevel2(PrivateKey key) throws Exception { - //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level2Data.getLevel1Data().getLevel2SigningAlg()); - Signature sig = Signature.getInstance(algo); - sig.initSign(key); - byte[] data = encode(level2Data); - sig.update(data); - level2Signature = sig.sign(); + signLevel2(key, null); } @@ -430,17 +455,22 @@ public class SimpleDynamicFrame implements IDynamicFrame { * Sign level 2 data. * * @param key the key - * @param prov the security Provider + * @param prov the registered 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.getLevel2Data().getLevel1Data().getLevel2SigningAlg()); - Signature sig = Signature.getInstance(algo,prov); + 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[] data = encode(level2Data); - sig.update(data); + byte[] signedData = encode(level2Data); + sig.update(signedData); level2Signature = sig.sign(); } @@ -453,8 +483,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @throws EncodingFormatException the encoding format exception */ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException { - - + level2Data.setLevel2Data(new SimpleData()); level2Data.getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1); @@ -501,19 +530,8 @@ public class SimpleDynamicFrame implements IDynamicFrame { */ public void signLevel1(PrivateKey key) throws Exception { - if (level2Data == null) return; - - ILevel1Data level1Data = level2Data.getLevel1Data(); - - if (level1Data == null) return; + signLevel1(key, null); - //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg()); - Signature sig = Signature.getInstance(algo); - sig.initSign(key); - byte[] data = encode(level1Data); - sig.update(data); - level2Data.setLevel1Signature(sig.sign()); } /** @@ -538,16 +556,17 @@ public class SimpleDynamicFrame implements IDynamicFrame { //find the algorithm name for the signature OID String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg()); - Signature sig = Signature.getInstance(algo, prov); + Signature sig = null; + if (prov != null) { + sig = Signature.getInstance(algo, prov); + } else { + sig = Signature.getInstance(algo); + } sig.initSign(key); byte[] data = encode(level1Data); sig.update(data); level2Data.setLevel1Signature(sig.sign()); } - - - - } diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java index f7b3f3d..1cffa12 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java @@ -100,6 +100,19 @@ public class DynamicFrameCoderV1 { 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[] encode(ILevel2Data level2SignedData) throws EncodingFormatException { Level2DataType asn = populateAsn(level2SignedData); @@ -183,6 +196,8 @@ public class DynamicFrameCoderV1 { return asnLevel1; } + + diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java index 8987f59..bdaa31a 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java @@ -197,6 +197,17 @@ public class DynamicFrameCoderV2 { 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; + } 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/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/DynamicFrameDynamicContentApiTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java index 5a70841..4d34c1b 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java @@ -10,8 +10,6 @@ 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.time.temporal.ChronoUnit; -- cgit v1.2.3 From 7af6c4ca50322258bbd23214920c4c9122482966 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 25 Jan 2022 13:33:37 +0100 Subject: test for the new dynamic header version 2 --- .../java/org/uic/barcode/asn1/uper/AsnUtils.java | 16 ++ .../org/uic/barcode/dynamicFrame/Constants.java | 3 + .../barcode/dynamicFrame/api/IDynamicFrame.java | 3 +- .../uic/barcode/dynamicFrame/api/SimpleData.java | 7 - .../dynamicFrame/api/SimpleDynamicFrame.java | 68 ++++--- .../barcode/dynamicFrame/api/SimpleLevel1Data.java | 1 - .../dynamicFrame/v1/DynamicFrameCoderV1.java | 12 +- .../dynamicFrame/v2/DynamicFrameCoderV2.java | 2 +- .../barcode/dynamicFrame/v2/Level1DataType.java | 25 ++- .../test/DynamicFrameV2FcbVersion3Test.java | 176 +++++++++++++++++ .../test/DynamicFrameV2ValidityDateTest.java | 208 +++++++++++++++++++++ 11 files changed, 472 insertions(+), 49 deletions(-) create mode 100644 src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java create mode 100644 src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java diff --git a/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java index dbb95c9..414f181 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java +++ b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java @@ -1,5 +1,7 @@ package org.uic.barcode.asn1.uper; +import java.math.BigInteger; + public class AsnUtils { @@ -55,5 +57,19 @@ public class AsnUtils { 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/dynamicFrame/Constants.java b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java index ba15f3f..3623817 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java @@ -38,4 +38,7 @@ public class Constants { 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/api/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java index 1e8a0ff..d901a6e 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java @@ -79,8 +79,9 @@ public interface IDynamicFrame{ * * @param bytes the bytes * @return the dynamic header + * @throws EncodingFormatException */ - public void decode(byte[] bytes); + public void decode(byte[] bytes) throws EncodingFormatException; diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java index cb762de..d6e1410 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java @@ -1,12 +1,5 @@ package org.uic.barcode.dynamicFrame.api; -import org.uic.barcode.asn1.datatypes.CharacterRestriction; -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.datatypesimpl.OctetString; -import org.uic.barcode.asn1.uper.UperEncoder; - /** * The Class DataType. */ diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java index ec52758..65b81d6 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java @@ -120,7 +120,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { return DynamicFrameCoderV1.encode(this); - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { return DynamicFrameCoderV2.encode(this); @@ -135,13 +135,12 @@ public class SimpleDynamicFrame implements IDynamicFrame { return DynamicFrameCoderV1.encode(level1Data); - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { return DynamicFrameCoderV2.encode(level1Data); } - - return null; + throw new EncodingFormatException("Dynamic Header Version not supported: " + format); } private byte[] getEncoded(String path, byte[] data) throws EncodingFormatException { @@ -150,29 +149,29 @@ public class SimpleDynamicFrame implements IDynamicFrame { return DynamicFrameCoderV1.getEncoded(path, data); - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { return DynamicFrameCoderV2.getEncoded(path, data); } - return null; + throw new EncodingFormatException("Dynamic Header Version not supported: " + format); } - private byte[] encode(ILevel2Data level2SignedData2) throws EncodingFormatException { + private byte[] encode(ILevel2Data level2Data) throws EncodingFormatException { if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { - return DynamicFrameCoderV1.encode(level2SignedData2); + return DynamicFrameCoderV1.encode(level2Data); - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { - return DynamicFrameCoderV2.encode(level2SignedData2); + return DynamicFrameCoderV2.encode(level2Data); } - return null; + throw new EncodingFormatException("Dynamic Header Version not supported: " + format); } /** @@ -182,22 +181,24 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @param bytes the bytes * @return the dynamic header + * @throws EncodingFormatException */ - public void decode(byte[] bytes) { + public void decode(byte[] bytes) throws EncodingFormatException { String format = getFormat(bytes); if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { DynamicFrameCoderV1.decode(this,bytes); + return; } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { DynamicFrameCoderV2.decode(this,bytes); - + return; } - + throw new EncodingFormatException("Dynamic Header Version not supported"); } @@ -211,12 +212,35 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return true, if is static header */ private static String getFormat(byte[] data) { - byte[] start = "U1".getBytes(); - if (start[0] != data[0] || start[1]!= start[1]) { + + if (data == null || data.length < 4) return null; + + byte[] startBits = new byte[4]; + startBits[0] = data[0]; + startBits[1] = data[1]; + startBits[2] = data[2]; + startBits[3] = data[3]; + + String start = AsnUtils.toBooleanString(startBits); + + /* + * bitshift: + * + * version 1: + * optional Level2Data 1 bit + * length of format: 8 bit + * + * version 2: + * extensionIndicator 1 bit + * optional Level2Data 1 bit + * length of format: 8 bit + */ + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1_BIN.equals(start.substring(9, 23))) { return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1; } - start = "U2".getBytes(); - if (start[0] != data[0] || start[1]!= start[1]) { + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2_BIN.equals(start.substring(10, 24))) { return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2; } return null; @@ -392,13 +416,9 @@ public class SimpleDynamicFrame implements IDynamicFrame { try { - //byte[] encodedData = encode(level2Data.getLevel1Data()); - //String s1 = AsnUtils.toBooleanString(encodedData); - //TODO - byte[] encodedData2 = getEncoded("Level1Data", data); - //String s2 = AsnUtils.toBooleanString(encodedData2); + byte[] encodedData = getEncoded("Level1Data", data); - sig.update(encodedData2); + sig.update(encodedData); } catch (SignatureException e) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java index 241cf6d..e9b1d4e 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java @@ -3,7 +3,6 @@ package org.uic.barcode.dynamicFrame.api; import java.util.ArrayList; import java.util.Collection; import java.util.Date; -import org.uic.barcode.asn1.uper.UperEncoder; /** * The Class SignedDataType. diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java index 1cffa12..39fcf32 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java @@ -113,9 +113,9 @@ public class DynamicFrameCoderV1 { } - public static byte[] encode(ILevel2Data level2SignedData) throws EncodingFormatException { + public static byte[] encode(ILevel2Data level2Data) throws EncodingFormatException { - Level2DataType asn = populateAsn(level2SignedData); + Level2DataType asn = populateAsn(level2Data); return UperEncoder.encode(asn); } @@ -150,10 +150,10 @@ public class DynamicFrameCoderV1 { 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); + DataType asnData = new DataType(); + asnData.setFormat(level2.getLevel2Data().getFormat()); + asnData.setData(new OctetString(level2.getLevel2Data().getData())); + asnLevel2.setLevel2Data(asnData); } return asnLevel2; diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java index bdaa31a..de475a9 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java @@ -120,7 +120,7 @@ public class DynamicFrameCoderV2 { DynamicFrame asnFrame = new DynamicFrame(); - frame.setFormat(frame.getFormat()); + asnFrame.setFormat(frame.getFormat()); if (frame.getLevel2Signature() != null && frame.getLevel2Signature().length > 0) { asnFrame.setLevel2Signature(new OctetString(frame.getLevel2Signature())); diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java index 1dff709..63db364 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java @@ -100,16 +100,16 @@ public class Level1DataType { /** The End of validity year. */ @FieldOrder(order = 9) @IntRange(minValue=2016,maxValue=2269) - public Long EndOfValidityYear; + @Asn1Optional public Long EndOfValidityYear; /** The End of validity day. */ @FieldOrder(order = 10) @IntRange(minValue=1,maxValue=366) - public Long EndOfValidityDay; + @Asn1Optional public Long EndOfValidityDay; /** The End of validity time. */ @FieldOrder(order = 11) - @IntRange(minValue=0,maxValue=1440) + @IntRange(minValue=0,maxValue=1439) @Asn1Optional public Long EndOfValidityTime; @@ -309,25 +309,26 @@ public class Level1DataType { } /** - * Sets the end of validity date. The validity date has to be provided in UTC. - * + * Sets the end of validity date. * @param date the new end of validity date */ public void setEndOfValidityDate(Date date){ - if (date == null) { - date = Calendar.getInstance().getTime(); - } + 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); } @@ -340,6 +341,9 @@ public class Level1DataType { 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")); @@ -356,6 +360,9 @@ public class Level1DataType { } Date d = cal.getTime(); + + TimeZone.setDefault(local); + return d; } 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..8014b78 --- /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.getDynamicHeader().getFormat().equals("U2")); + + for (IData data : dec.getDynamicHeader().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/DynamicFrameV2ValidityDateTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java new file mode 100644 index 0000000..03536c4 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java @@ -0,0 +1,208 @@ +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); + + 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); + + 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.getDynamicHeader().getFormat().equals("U2")); + + for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) { + assert(data.getFormat().equals("FCB3") ); + } + + Date endDate2 = dec.getDynamicHeader().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)); + + } + + 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(); + } + + +} -- cgit v1.2.3 From 7410ac59ba8e1994254a872104ea660b992cba9a Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Fri, 28 Jan 2022 17:06:47 +0100 Subject: new dynamic header version --- misc/uicBarcodeHeader_v2.0.0.asn | 25 +- src/main/java/org/uic/barcode/Decoder.java | 44 +++- src/main/java/org/uic/barcode/Encoder.java | 59 ++++- .../dynamicContent/api/IUicDynamicContent.java | 1 - .../fdc1/GeoCoordinateSystemType.java | 1 - .../barcode/dynamicContent/fdc1/GeoUnitType.java | 1 - .../fdc1/HemisphereLatitudeType.java | 1 - .../fdc1/HemisphereLongitudeType.java | 1 - .../dynamicFrame/api/DynamicFrameCoder.java | 107 ++++++++ .../barcode/dynamicFrame/api/IDynamicFrame.java | 75 +++--- .../uic/barcode/dynamicFrame/api/ILevel1Data.java | 60 ++++- .../dynamicFrame/api/SimpleDynamicFrame.java | 183 ++++--------- .../barcode/dynamicFrame/api/SimpleLevel1Data.java | 11 + .../barcode/dynamicFrame/api/SimpleLevel2Data.java | 19 -- .../dynamicFrame/v1/DynamicFrameCoderV1.java | 19 +- .../org/uic/barcode/dynamicFrame/v2/DataType.java | 2 - .../uic/barcode/dynamicFrame/v2/DynamicFrame.java | 2 - .../dynamicFrame/v2/DynamicFrameCoderV2.java | 25 +- .../barcode/dynamicFrame/v2/Level1DataType.java | 41 +-- .../barcode/dynamicFrame/v2/Level2DataType.java | 2 - .../asn1/test/UperEncodeFieldOrderTest.java | 2 - .../asn1/test/UperEncodeIntegerExtensionTest.java | 2 - .../asn1/test/UperEncodeSequenceOfStringTest.java | 2 - .../test/DynamicFrameDynamicContentTest.java | 2 +- .../barcode/test/DynamicFrameFcbVersion1Test.java | 4 +- .../barcode/test/DynamicFrameFcbVersion3Test.java | 4 +- .../test/DynamicFrameV2FcbVersion3Test.java | 4 +- .../test/DynamicFrameV2SignatureInsertTest.java | 289 +++++++++++++++++++++ .../test/DynamicFrameV2ValidityDateTest.java | 10 +- .../uic/barcode/test/utils/DynamicTestContent.java | 2 + 30 files changed, 729 insertions(+), 271 deletions(-) create mode 100644 src/main/java/org/uic/barcode/dynamicFrame/api/DynamicFrameCoder.java create mode 100644 src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsertTest.java diff --git a/misc/uicBarcodeHeader_v2.0.0.asn b/misc/uicBarcodeHeader_v2.0.0.asn index 79d104d..e7363b0 100644 --- a/misc/uicBarcodeHeader_v2.0.0.asn +++ b/misc/uicBarcodeHeader_v2.0.0.asn @@ -52,10 +52,7 @@ ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN level2SignedData Level2DataType, -- signature is calculated on the PER unaligned encoding of level2 signature data - level2Signature OCTET STRING OPTIONAL, - ... - - + level2Signature OCTET STRING OPTIONAL } Level2DataType ::= SEQUENCE { @@ -65,8 +62,7 @@ ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN -- signature is calculated on the PER unaligned encoding of level1 signature data level1Signature OCTET STRING OPTIONAL, - level2Data DataType OPTIONAL, - ... + level2Data DataType OPTIONAL } @@ -98,17 +94,21 @@ ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN level2SigningAlg OBJECT IDENTIFIER OPTIONAL, level2PublicKey OCTET STRING OPTIONAL, - -- end of the validity of the bar code, after this date and time the bar code needs to be regenerated + -- 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 must ensure that the end of validity of the bar code is - -- before the end of validity of the key pair used on level 2 + -- 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. endOfValidityYear INTEGER (2016..2269) OPTIONAL, -- number of the day in the year (1.1. = 1) endOfValidityDay INTEGER (1..366) OPTIONAL, -- The number of the minutes of the day - endOfValidityTime INTEGER (0..1439) OPTIONAL, - ... + endOfValidityTime INTEGER (0..1439) OPTIONAL, + + -- validity duration in seconds of the bar code shown with reference to the time stamp dynamicContentTimeStamp + -- in the dynamic data included in the level2Data + validityDuration INTEGER (1..3600) OPTIONAL } DataType ::= SEQUENCE { @@ -118,8 +118,7 @@ ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN -- or proprietary: -- _RICS company code + addon dataFormat IA5String, - data OCTET STRING, - ... + data OCTET STRING } diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index 5cb0546..3d97e0a 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -10,11 +10,11 @@ import java.util.zip.DataFormatException; import org.uic.barcode.dynamicContent.api.IUicDynamicContent; import org.uic.barcode.dynamicFrame.Constants; +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.dynamicFrame.api.SimpleDynamicFrame; import org.uic.barcode.staticFrame.StaticFrame; import org.uic.barcode.staticFrame.UFLEXDataRecord; import org.uic.barcode.staticFrame.UTLAYDataRecord; @@ -80,7 +80,7 @@ public class Decoder { * @throws EncodingFormatException the encoding format exception */ public int validateLevel1(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { - if (!isStaticHeader(data)) { + if (dynamicFrame != null) { return dynamicFrame.validateLevel1(key, data) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg)) { @@ -158,9 +158,7 @@ public class Decoder { if (!isStaticHeader(data)) { - dynamicFrame = new SimpleDynamicFrame(); - - dynamicFrame.decode(data); + dynamicFrame = DynamicFrameCoder.decode(data); ILevel2Data level2 = dynamicFrame.getLevel2Data(); @@ -229,13 +227,13 @@ public class Decoder { public TicketLayout getLayout() { return layout; } - + /** * Gets the dynamic header. * * @return the dynamic header */ - public IDynamicFrame getDynamicHeader() { + public IDynamicFrame getDynamicFrame() { return dynamicFrame; } @@ -284,7 +282,39 @@ public class Decoder { 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 5f10806..51e86a2 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -8,12 +8,16 @@ import java.security.PublicKey; 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.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; @@ -116,6 +120,48 @@ public class Encoder { } } + /** + * 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"); + } + + + } + /** @@ -265,7 +311,6 @@ public class Encoder { dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(signingAlg); dynamicFrame.getLevel2Data().getLevel1Data().setKeyId(Long.parseLong(keyId)); dynamicFrame.signLevel1(key,prov); - //dynamicFrame.getLevel2Data().signLevel1(key, prov); } else if (staticFrame != null) { staticFrame.setSignatureKey(keyId); staticFrame.setSecurityProvider(securityProvider); @@ -321,7 +366,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(); } @@ -329,7 +374,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/dynamicContent/api/IUicDynamicContent.java b/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java index 718d013..3b0afde 100644 --- a/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java +++ b/src/main/java/org/uic/barcode/dynamicContent/api/IUicDynamicContent.java @@ -6,7 +6,6 @@ import java.util.List; import org.uic.barcode.ticket.api.spec.IExtension; import org.uic.barcode.ticket.api.spec.IGeoCoordinate; -// TODO: Auto-generated Javadoc /** * The Interface IUicDynamicContent. */ 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/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/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java index d901a6e..c917b6a 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java @@ -8,9 +8,9 @@ import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; import org.uic.barcode.ticket.EncodingFormatException; + /** - * The DynamicHeader for bar codes - * + * The DynamicHeader for bar codes . */ public interface IDynamicFrame{ @@ -41,7 +41,7 @@ public interface IDynamicFrame{ /** * Sets the level 2 signed data. * - * @param level2SignedData the new level 2 signed data + * @param level2Data the new level 2 data */ public void setLevel2Data(ILevel2Data level2Data); @@ -61,29 +61,6 @@ public interface IDynamicFrame{ */ public void setLevel2Signature(byte[] level2Signature); - - /** - * Encode. - * - * Encode the header as ASN.1 PER UNALIGNED byte array - * - * @return the byte[] - * @throws EncodingFormatException - */ - public byte[] encode() throws EncodingFormatException; - - /** - * Decode. - * - * Decode the header from an ASN.1 PER UNALIGNED encoded byte array - * - * @param bytes the bytes - * @return the dynamic header - * @throws EncodingFormatException - */ - public void decode(byte[] bytes) throws EncodingFormatException; - - /** * Verify the level 2 signature @@ -92,7 +69,7 @@ public interface IDynamicFrame{ * * @param data the data content * @return the return error code - * @throws EncodingFormatException + * @throws EncodingFormatException the encoding format exception */ public int validateLevel2(byte[] data) throws EncodingFormatException; @@ -102,9 +79,9 @@ public interface IDynamicFrame{ * Note: an appropriate security provider (e.g. BC) must be registered before * * @param prov the registered security provider - * @param data the data content + * @param data the data content * @return the return error code - * @throws EncodingFormatException + * @throws EncodingFormatException the encoding format exception */ public int validateLevel2(Provider prov, byte[] data) throws EncodingFormatException; @@ -116,7 +93,7 @@ public interface IDynamicFrame{ * @param key the key * @param data the data content * @return the return error code - * @throws EncodingFormatException + * @throws EncodingFormatException the encoding format exception */ public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException; @@ -126,10 +103,10 @@ public interface IDynamicFrame{ * Note: an appropriate security provider (e.g. BC) must be registered before * * @param key the key - * @param prov the registered security provider - * @param the data content + * @param prov the registered security provider + * @param data the data * @return the return error code - * @throws EncodingFormatException + * @throws EncodingFormatException the encoding format exception */ public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException; @@ -183,9 +160,8 @@ public interface IDynamicFrame{ * Note: an appropriate security provider (e.g. BC) must be registered before * * @param key the key - * @return * @return the byte[] - * @throws Exception + * @throws Exception the exception */ public void signLevel1(PrivateKey key) throws Exception; @@ -195,13 +171,36 @@ public interface IDynamicFrame{ * 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 + * @param prov the prov * @return the byte[] - * @throws Exception + * @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 index 206d613..e23fc88 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java @@ -11,15 +11,15 @@ public interface ILevel1Data { /** - * Sets the security provider + * Sets the security provider . * - * @param securityProviderNum the new security provider + * @param securityProvider the new security provider */ public void setSecurityProvider(String securityProvider); /** - * Gets the security provider + * Gets the security provider. * * @return the security provider */ @@ -68,7 +68,7 @@ public interface ILevel1Data { public void addData(IData data); /** - * Gets the level 2 key alg. + * Gets the level 2 key algorithm OID. * * @return the level 2 key alg */ @@ -76,7 +76,7 @@ public interface ILevel1Data { /** - * Sets the level 2 key alg. + * Sets the level 2 key algorithm OID. * * @param level2KeyAlg the new level 2 key alg */ @@ -92,7 +92,7 @@ public interface ILevel1Data { /** - * Sets the level 1 signing alg. + * Sets the level 1 signing algorithm OID. * * @param level1SigningAlg the new level 1 signing alg */ @@ -100,7 +100,7 @@ public interface ILevel1Data { /** - * Gets the level 2 signing alg. + * Gets the level 2 signing algorithm OID. * * @return the level 2 signing alg */ @@ -108,7 +108,7 @@ public interface ILevel1Data { /** - * Sets the level 2 signing alg. + * Sets the level 2 signing algorithm OID. * * @param level2SigningAlg the new level 2 signing alg */ @@ -133,14 +133,14 @@ public interface ILevel1Data { /** - * Gets the level 1 key alg. + * Gets the level 1 key algorithm OID. * * @return the level 1 key alg */ public String getLevel1KeyAlg(); /** - * Sets the level 1 key alg. + * Sets the level 1 key algorithm OID. * * @param level1KeyAlg the new level 1 key alg */ @@ -149,6 +149,13 @@ public interface ILevel1Data { /** * 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 */ @@ -156,9 +163,40 @@ public interface ILevel1Data { /** - * Gets the end of validity 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/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java index 65b81d6..8d53f9a 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java @@ -12,7 +12,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Date; -import org.uic.barcode.asn1.uper.AsnUtils; +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; @@ -40,7 +40,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { } /** The format. */ - public String format = Constants.DYNAMIC_BARCODE_FORMAT_DEFAULT; + public String format = null; /** The level 2 signed data. */ /*level 2 data*/ @@ -115,136 +115,15 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @throws EncodingFormatException */ public byte[] encode() throws EncodingFormatException { - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { - - return DynamicFrameCoderV1.encode(this); - - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { - - return DynamicFrameCoderV2.encode(this); - - } - - return null; - } - - private byte[] encode(ILevel1Data level1Data) throws EncodingFormatException { - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { - - return DynamicFrameCoderV1.encode(level1Data); - - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { - - return DynamicFrameCoderV2.encode(level1Data); - - } - throw new EncodingFormatException("Dynamic Header Version not supported: " + format); - } - - private byte[] getEncoded(String path, byte[] data) throws EncodingFormatException { - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { - - return DynamicFrameCoderV1.getEncoded(path, data); - - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { - - return DynamicFrameCoderV2.getEncoded(path, data); - - } - throw new EncodingFormatException("Dynamic Header Version not supported: " + format); - } - - - private byte[] encode(ILevel2Data level2Data) throws EncodingFormatException { - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { - - return DynamicFrameCoderV1.encode(level2Data); - - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { - - return DynamicFrameCoderV2.encode(level2Data); - - } - - throw new EncodingFormatException("Dynamic Header Version not supported: " + format); - } - - /** - * Decode. - * - * Decode the header from an ASN.1 PER UNALIGNED encoded byte array - * - * @param bytes the bytes - * @return the dynamic header - * @throws EncodingFormatException - */ - public void decode(byte[] bytes) throws EncodingFormatException { - - String format = getFormat(bytes); - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { - - DynamicFrameCoderV1.decode(this,bytes); - return; + return DynamicFrameCoder.encode(this); - } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) { - - DynamicFrameCoderV2.decode(this,bytes); - return; - } - - throw new EncodingFormatException("Dynamic Header Version not supported"); + } - - /** - * Checks if is static header. - * - * @param data the data - * @return true, if is static header - */ - private static String getFormat(byte[] data) { - - if (data == null || data.length < 4) return null; - - byte[] startBits = new byte[4]; - startBits[0] = data[0]; - startBits[1] = data[1]; - startBits[2] = data[2]; - startBits[3] = data[3]; - - String start = AsnUtils.toBooleanString(startBits); - - /* - * bitshift: - * - * version 1: - * optional Level2Data 1 bit - * length of format: 8 bit - * - * version 2: - * extensionIndicator 1 bit - * optional Level2Data 1 bit - * length of format: 8 bit - */ - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1_BIN.equals(start.substring(9, 23))) { - return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1; - } - - if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2_BIN.equals(start.substring(10, 24))) { - return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2; - } - return null; - } /** * Verify the level 2 signature @@ -334,13 +213,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { } try { - //TODO - //byte[] signedData = encode(level2Data); - //String s1 = AsnUtils.toBooleanString(signedData); - - byte[] signedData2 = getEncoded("Level2Data", data); - //String s2 = AsnUtils.toBooleanString(signedData); - + byte[] signedData2 = getLevel2DataBin(); sig.update(signedData2); } catch (SignatureException e) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; @@ -416,7 +289,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { try { - byte[] encodedData = getEncoded("Level1Data", data); + byte[] encodedData = getLevel1DataBin(); sig.update(encodedData); @@ -489,7 +362,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { sig = Signature.getInstance(algo); } sig.initSign(key); - byte[] signedData = encode(level2Data); + byte[] signedData = DynamicFrameCoder.encodeLevel2Data(this); sig.update(signedData); level2Signature = sig.sign(); @@ -584,9 +457,49 @@ public class SimpleDynamicFrame implements IDynamicFrame { } sig.initSign(key); - byte[] data = encode(level1Data); + 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"); + + } + + + 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 index e9b1d4e..f42ff98 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java @@ -63,6 +63,7 @@ public class SimpleLevel1Data implements ILevel1Data { public Date endOfBarcodeValidity = null; + public Long validityDuration = null; @@ -250,4 +251,14 @@ public class SimpleLevel1Data implements ILevel1Data { 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 index 395db4d..17e71db 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java @@ -2,15 +2,10 @@ package org.uic.barcode.dynamicFrame.api; import org.uic.barcode.asn1.datatypes.Asn1Optional; import org.uic.barcode.asn1.datatypes.FieldOrder; -import org.uic.barcode.asn1.datatypes.HasExtensionMarker; -import org.uic.barcode.asn1.datatypes.Sequence; -import org.uic.barcode.asn1.uper.UperEncoder; /** * The Class DataType. */ -@Sequence -@HasExtensionMarker public class SimpleLevel2Data implements ILevel2Data { @FieldOrder(order = 0) @@ -56,20 +51,6 @@ public class SimpleLevel2Data implements ILevel2Data { public void setLevel2Data(IData 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/v1/DynamicFrameCoderV1.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java index 39fcf32..71de58e 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java @@ -3,6 +3,7 @@ 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; @@ -30,6 +31,14 @@ public class DynamicFrameCoderV1 { } } + + public static ILevel1Data decodeLevel1(byte[] bytes) { + + Level1DataType asnData = UperEncoder.decode(bytes,Level1DataType.class); + + return populateApi(asnData); + + } private static void populateApi(ILevel2Data level2, Level2DataType asnLevel2) { @@ -113,7 +122,7 @@ public class DynamicFrameCoderV1 { } - public static byte[] encode(ILevel2Data level2Data) throws EncodingFormatException { + public static byte[] encodeLevel2Data(ILevel2Data level2Data) throws EncodingFormatException { Level2DataType asn = populateAsn(level2Data); @@ -198,6 +207,14 @@ public class DynamicFrameCoderV1 { } + 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/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java index f94b622..d4f3c15 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java @@ -1,7 +1,6 @@ package org.uic.barcode.dynamicFrame.v2; import org.uic.barcode.asn1.datatypes.CharacterRestriction; -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.datatypesimpl.OctetString; @@ -11,7 +10,6 @@ import org.uic.barcode.asn1.uper.UperEncoder; * The Class DataType. */ @Sequence -@HasExtensionMarker public class DataType { diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java index 2986f75..4831c6a 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java @@ -14,7 +14,6 @@ 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.HasExtensionMarker; import org.uic.barcode.asn1.datatypes.RestrictedString; import org.uic.barcode.asn1.datatypes.Sequence; import org.uic.barcode.asn1.datatypesimpl.OctetString; @@ -33,7 +32,6 @@ import org.uic.barcode.utils.AlgorithmNameResolver; * Implementation of the Draft under discussion, not final. */ @Sequence -@HasExtensionMarker public class DynamicFrame extends Object{ /** diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java index de475a9..5d980dd 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java @@ -34,11 +34,20 @@ public class DynamicFrameCoderV2 { } } + + 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) { @@ -89,6 +98,8 @@ public class DynamicFrameCoderV2 { level1.setEndOfBarcodeValidity(asnLevel1.getEndOfValidityDate()); } + level1.setValidityDuration(asnLevel1.getValidityDuration()); + return level1; } @@ -109,7 +120,7 @@ public class DynamicFrameCoderV2 { return UperEncoder.encode(asn); } - public static byte[] encode(ILevel2Data level2SignedData) throws EncodingFormatException { + public static byte[] encodeLevel2Data(ILevel2Data level2SignedData) throws EncodingFormatException { Level2DataType asn = populateAsn(level2SignedData); @@ -194,6 +205,8 @@ public class DynamicFrameCoderV2 { asnLevel1.setEndOfValidityDate(level1.getEndOfBarcodeValidity()); + asnLevel1.setValidityDuration(level1.getValidityDuration()); + return asnLevel1; } @@ -208,6 +221,14 @@ public class DynamicFrameCoderV2 { 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 index 63db364..b42e9dc 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java @@ -7,7 +7,6 @@ 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.HasExtensionMarker; import org.uic.barcode.asn1.datatypes.IntRange; import org.uic.barcode.asn1.datatypes.RestrictedString; import org.uic.barcode.asn1.datatypes.Sequence; @@ -16,12 +15,10 @@ import org.uic.barcode.asn1.uper.UperEncoder; import org.uic.barcode.ticket.EncodingFormatException; import org.uic.barcode.ticket.api.utils.UicEncoderUtils; -// TODO: Auto-generated Javadoc /** * The Class SignedDataType. */ @Sequence -@HasExtensionMarker public class Level1DataType { /** @@ -100,18 +97,22 @@ public class Level1DataType { /** The End of validity year. */ @FieldOrder(order = 9) @IntRange(minValue=2016,maxValue=2269) - @Asn1Optional public Long EndOfValidityYear; + @Asn1Optional public Long endOfValidityYear; /** The End of validity day. */ @FieldOrder(order = 10) @IntRange(minValue=1,maxValue=366) - @Asn1Optional public Long EndOfValidityDay; + @Asn1Optional public Long endOfValidityDay; /** The End of validity time. */ @FieldOrder(order = 11) @IntRange(minValue=0,maxValue=1439) - @Asn1Optional public Long EndOfValidityTime; + @Asn1Optional public Long endOfValidityTime; + /** The validity duration in seconds. */ + @FieldOrder(order = 12) + @IntRange(minValue=1,maxValue=3600) + @Asn1Optional public Long validityDuration; @@ -322,11 +323,11 @@ public class Level1DataType { 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)); + 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 ); + this.endOfValidityTime = new Long (time ); } TimeZone.setDefault(local); @@ -339,7 +340,7 @@ public class Level1DataType { */ public Date getEndOfValidityDate() { - if (this.EndOfValidityYear == null || this.EndOfValidityDay == null) return null; + if (this.endOfValidityYear == null || this.endOfValidityDay == null) return null; TimeZone local = TimeZone.getDefault(); TimeZone.setDefault(TimeZone.getTimeZone("UTC")); @@ -347,13 +348,13 @@ public class Level1DataType { 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()); + cal.set(Calendar.YEAR, this.endOfValidityYear.intValue()); + cal.set(Calendar.DAY_OF_YEAR, this.endOfValidityDay.intValue()); - if (this.EndOfValidityTime != null) { + if (this.endOfValidityTime != null) { - int hours = this.EndOfValidityTime.intValue() / 60; - int minutes = this.EndOfValidityTime.intValue() % 60; + int hours = this.endOfValidityTime.intValue() / 60; + int minutes = this.endOfValidityTime.intValue() % 60; cal.set(Calendar.HOUR_OF_DAY, hours); cal.set(Calendar.MINUTE,minutes); @@ -365,6 +366,16 @@ public class Level1DataType { return d; } + + + + public Long getValidityDuration() { + return validityDuration; + } + + public void setValidityDuration(Long validityDuration) { + this.validityDuration = validityDuration; + } /** * Gets the data for signature. diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java index 6534c4d..cd0800e 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java @@ -6,7 +6,6 @@ import java.security.Signature; import org.uic.barcode.asn1.datatypes.Asn1Optional; import org.uic.barcode.asn1.datatypes.FieldOrder; -import org.uic.barcode.asn1.datatypes.HasExtensionMarker; import org.uic.barcode.asn1.datatypes.Sequence; import org.uic.barcode.asn1.datatypesimpl.OctetString; import org.uic.barcode.asn1.uper.UperEncoder; @@ -16,7 +15,6 @@ import org.uic.barcode.utils.AlgorithmNameResolver; * The Class DataType. */ @Sequence -@HasExtensionMarker public class Level2DataType { @FieldOrder(order = 0) 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/DynamicFrameDynamicContentTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java index 4cfca12..d26ab77 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java @@ -218,7 +218,7 @@ public class DynamicFrameDynamicContentTest { assert(level2check == Constants.LEVEL2_VALIDATION_OK); - IUicDynamicContent dynamicData = dec.getDynamicHeader().getDynamicContent(); + IUicDynamicContent dynamicData = dec.getDynamicFrame().getDynamicContent(); assert(dynamicData.getChallengeString().equals("CHALLENGE")); diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java index 861fc85..ea95a88 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java @@ -143,9 +143,9 @@ public class DynamicFrameFcbVersion1Test { assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); - assert(dec.getDynamicHeader().getFormat().equals("U1")); + assert(dec.getDynamicFrame().getFormat().equals("U1")); - for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) { + for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) { assert(data.getFormat().equals("FCB1") ); } diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java index fa055dc..4095d93 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java @@ -143,9 +143,9 @@ public class DynamicFrameFcbVersion3Test { assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); - assert(dec.getDynamicHeader().getFormat().equals("U1")); + assert(dec.getDynamicFrame().getFormat().equals("U1")); - for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) { + for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) { assert(data.getFormat().equals("FCB3") ); } diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java index 8014b78..17bccd6 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2FcbVersion3Test.java @@ -143,9 +143,9 @@ public class DynamicFrameV2FcbVersion3Test { assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); - assert(dec.getDynamicHeader().getFormat().equals("U2")); + assert(dec.getDynamicFrame().getFormat().equals("U2")); - for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) { + for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) { assert(data.getFormat().equals("FCB3") ); } 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 index 03536c4..9bbd736 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2ValidityDateTest.java @@ -87,6 +87,7 @@ public class DynamicFrameV2ValidityDateTest { TimeZone.setDefault(local); enc.getDynamicFrame().getLevel2Data().getLevel1Data().setEndOfBarcodeValidity(endDate); + enc.getDynamicFrame().getLevel2Data().getLevel1Data().setValidityDuration(100L); try { enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1"); @@ -132,6 +133,7 @@ public class DynamicFrameV2ValidityDateTest { TimeZone.setDefault(local); enc.getDynamicFrame().getLevel2Data().getLevel1Data().setEndOfBarcodeValidity(endDate); + enc.getDynamicFrame().getLevel2Data().getLevel1Data().setValidityDuration(100L); try { enc.signLevel1("1080", keyPair.getPrivate(), signatureAlgorithmOID, "1"); @@ -171,13 +173,13 @@ public class DynamicFrameV2ValidityDateTest { assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); - assert(dec.getDynamicHeader().getFormat().equals("U2")); + assert(dec.getDynamicFrame().getFormat().equals("U2")); - for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) { + for (IData data : dec.getDynamicFrame().getLevel2Data().getLevel1Data().getData()) { assert(data.getFormat().equals("FCB3") ); } - Date endDate2 = dec.getDynamicHeader().getLevel2Data().getLevel1Data().getEndOfBarcodeValidity(); + Date endDate2 = dec.getDynamicFrame().getLevel2Data().getLevel1Data().getEndOfBarcodeValidity(); TimeZone.setDefault(TimeZone.getTimeZone("UTC")); @@ -186,6 +188,8 @@ public class DynamicFrameV2ValidityDateTest { 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{ diff --git a/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java b/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java index a39b270..9380372 100644 --- a/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java +++ b/src/test/java/org/uic/barcode/test/utils/DynamicTestContent.java @@ -35,4 +35,6 @@ public class DynamicTestContent { return dc; } + + } -- cgit v1.2.3 From 2f72a6419dd1e20acf6e77a9276a6055892e732a Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 1 Feb 2022 12:45:04 +0100 Subject: - missing fieldOrder added - validation of level1 when the signature algorithm is missing --- src/main/java/org/uic/barcode/Decoder.java | 35 +++- .../barcode/dynamicFrame/api/IDynamicFrame.java | 45 +++-- .../dynamicFrame/api/SimpleDynamicFrame.java | 144 +++++++-------- .../org/uic/barcode/dynamicFrame/v1/DataType.java | 3 + .../uic/barcode/dynamicFrame/v1/DynamicFrame.java | 203 --------------------- .../org/uic/barcode/dynamicFrame/v2/DataType.java | 3 + .../uic/barcode/dynamicFrame/v2/DynamicFrame.java | 202 -------------------- .../barcode/test/DynamicFrameFcbVersion3Test.java | 2 +- .../uic/barcode/test/DynamicFrameLOwLevelTest.java | 6 +- 9 files changed, 139 insertions(+), 504 deletions(-) diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index 3d97e0a..9f5ea82 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -65,6 +65,32 @@ public class Decoder { decode(data); } + /** + * 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) 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. * @@ -81,7 +107,7 @@ public class Decoder { */ public int validateLevel1(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { if (dynamicFrame != null) { - return dynamicFrame.validateLevel1(key, data) ; + return dynamicFrame.validateLevel1(key, signingAlg) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg)) { return Constants.LEVEL1_VALIDATION_OK; @@ -108,7 +134,7 @@ public class Decoder { */ public int validateLevel1(PublicKey key, String signingAlg, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel1(key, provider, data) ; + return dynamicFrame.validateLevel1(key, provider) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg, provider)) { return Constants.LEVEL1_VALIDATION_OK; @@ -126,7 +152,7 @@ public class Decoder { */ public int validateLevel2() throws EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel2(null, data) ; + return dynamicFrame.validateLevel2() ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } @@ -139,7 +165,7 @@ public class Decoder { */ public int validateLevel2(Provider prov) throws EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel2(prov,data) ; + return dynamicFrame.validateLevel2(prov) ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } @@ -164,7 +190,6 @@ public class Decoder { ILevel1Data level1 = level2.getLevel1Data(); - for (IData level1Content : level1.getData()) { uicTicketCoder = new UicRailTicketCoder(); diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java index c917b6a..4b2d1f4 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java @@ -66,12 +66,10 @@ public interface IDynamicFrame{ * Verify the level 2 signature * * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @param data the data content * @return the return error code * @throws EncodingFormatException the encoding format exception */ - public int validateLevel2(byte[] data) throws EncodingFormatException; + public int validateLevel2() throws EncodingFormatException; /** * Verify the level 2 signature @@ -79,11 +77,10 @@ public interface IDynamicFrame{ * Note: an appropriate security provider (e.g. BC) must be registered before * * @param prov the registered security provider - * @param data the data content * @return the return error code * @throws EncodingFormatException the encoding format exception */ - public int validateLevel2(Provider prov, byte[] data) throws EncodingFormatException; + public int validateLevel2(Provider prov) throws EncodingFormatException; /** * Verify the level 1 signature @@ -95,7 +92,20 @@ public interface IDynamicFrame{ * @return the return error code * @throws EncodingFormatException the encoding format exception */ - public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException; + 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 @@ -104,12 +114,22 @@ public interface IDynamicFrame{ * * @param key the key * @param prov the registered security provider - * @param data the data * @return the return error code * @throws EncodingFormatException the encoding format exception */ - public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException; + 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. @@ -159,8 +179,8 @@ public interface IDynamicFrame{ * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @param key the key - * @return the byte[] + * @param key the private key + * @return the signature * @throws Exception the exception */ public void signLevel1(PrivateKey key) throws Exception; @@ -170,8 +190,8 @@ public interface IDynamicFrame{ * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @param key the key - * @param prov the prov + * @param key the private key + * @param prov the security provider providing the signature implementation * @return the byte[] * @throws Exception the exception */ @@ -185,7 +205,6 @@ public interface IDynamicFrame{ */ public byte[] getLevel1Signature(); - /** * Gets the level 1 data in binary as they are signed by the level 1 signature. * diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java index 8d53f9a..a05a936 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java @@ -12,7 +12,6 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Date; -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; @@ -57,6 +56,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @return the format */ + @Override public String getFormat() { return format; } @@ -66,6 +66,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @param format the new format */ + @Override public void setFormat(String format) { this.format = format; } @@ -75,6 +76,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @return the level 2 signed data */ + @Override public ILevel2Data getLevel2Data() { return level2Data; } @@ -84,6 +86,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @param level2SignedData the new level 2 signed data */ + @Override public void setLevel2Data(ILevel2Data level2SignedData) { this.level2Data = level2SignedData; } @@ -93,6 +96,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @return the level 2 signature */ + @Override public byte[] getLevel2Signature() { return level2Signature; } @@ -102,29 +106,13 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @param level2Signature the new level 2 signature */ + @Override public void setLevel2Signature(byte[] level2Signature) { this.level2Signature = level2Signature; } - /** - * Encode. - * - * Encode the header as ASN.1 PER UNALIGNED byte array - * - * @return the byte[] - * @throws EncodingFormatException - */ - public byte[] encode() throws EncodingFormatException { - - return DynamicFrameCoder.encode(this); - - - - } - - /** * Verify the level 2 signature * @@ -133,9 +121,9 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel2(byte[] data) throws EncodingFormatException { - - return validateLevel2(null, data); + @Override + public int validateLevel2() throws EncodingFormatException { + return validateLevel2(null); } @@ -148,10 +136,17 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2(Provider prov, byte[] data) 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 = this.getLevel2Data().getLevel1Data().getLevel2KeyAlg(); + String level2KeyAlg = getLevel2Data().getLevel1Data().getLevel2KeyAlg(); if (level2KeyAlg == null || level2KeyAlg.length() == 0) { @@ -235,34 +230,53 @@ public class SimpleDynamicFrame implements IDynamicFrame { } } - /** - * Verify the level 1 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @param key the key - * @param prov the prov - * @return the int - * @throws EncodingFormatException - */ - public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException { - - if (level2Data == null) { - return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; - } - + @Override + public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException { + return validateLevel1(key, prov, null); + + } - if (level2Data == null || - level2Data.getLevel1Signature().length == 0) { + @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(getLevel2Data().getLevel1Data().getLevel1SigningAlg(), prov); + algo = AlgorithmNameResolver.getSignatureAlgorithmName(signingAlgorithmOid, prov); } catch (Exception e1) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } @@ -301,47 +315,20 @@ public class SimpleDynamicFrame implements IDynamicFrame { return Constants.LEVEL1_VALIDATION_ENCODING_ERROR; } - try { if (sig.verify(signature)){ - return Constants.LEVEL2_VALIDATION_OK; + return Constants.LEVEL1_VALIDATION_OK; } else { - return Constants.LEVEL2_VALIDATION_FRAUD; + return Constants.LEVEL1_VALIDATION_FRAUD; } } catch (SignatureException e) { - return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; + return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } - } - - - - - - /** - * Verify the level 1 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @param key the key - * @return the int - * @throws EncodingFormatException - */ - public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException { - - return validateLevel1(key, null,data); - - } + } - /** - * Sign level 2 data without a specific security provider. - * - * @param key the key - * @throws Exception the exception - */ + @Override public void signLevel2(PrivateKey key) throws Exception { - signLevel2(key, null); - } /** @@ -351,6 +338,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @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 @@ -375,6 +363,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @param content the dynamic content * @throws EncodingFormatException the encoding format exception */ + @Override public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException { level2Data.setLevel2Data(new SimpleData()); @@ -390,6 +379,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @param dynamicData the dynamic data */ + @Override public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) { this.getLevel2Data().setLevel2Data(dynamicData.getApiDataType()); } @@ -399,6 +389,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * @return the dynamic content */ + @Override public IUicDynamicContent getDynamicContent() { if (this.getLevel2Data() == null || @@ -421,6 +412,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the byte[] * @throws Exception */ + @Override public void signLevel1(PrivateKey key) throws Exception { signLevel1(key, null); @@ -484,7 +476,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { } - + @Override public byte[] getLevel2DataBin() throws EncodingFormatException { if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { @@ -501,5 +493,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { } + + } diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java index 6195b3c..e8cfc50 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java @@ -1,6 +1,7 @@ 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 index 3af9c8f..3bfcbf5 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java @@ -1,16 +1,8 @@ package org.uic.barcode.dynamicFrame.v1; -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; @@ -21,7 +13,6 @@ 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.dynamicFrame.Constants; import org.uic.barcode.ticket.EncodingFormatException; import org.uic.barcode.utils.AlgorithmNameResolver; @@ -131,200 +122,6 @@ public class DynamicFrame extends Object{ return UperEncoder.decode(bytes, DynamicFrame.class); } - /** - * Verify the level 2 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @return the int - */ - public int validateLevel2() { - - return validateLevel2(null); - - } - - /** - * Verify the level 2 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @param prov the prov - * @return the int - */ - 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 - * - * @param key the key - * @param prov the prov - * @return the int - */ - 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 - * - * @param key the key - * @return the int - */ - public int validateLevel1(PublicKey key) { - - return validateLevel1(key, null); - - } - /** * Sign level 2 data without a specific security provider. * diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java index d4f3c15..beceda9 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java @@ -1,6 +1,7 @@ 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; @@ -20,9 +21,11 @@ public class DataType { * -- RICS company code + ... **/ @RestrictedString(CharacterRestriction.IA5String) + @FieldOrder(order = 0) public String format; /** The data. */ + @FieldOrder(order = 1) public OctetString data; /** diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java index 4831c6a..55af066 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java @@ -1,16 +1,8 @@ package org.uic.barcode.dynamicFrame.v2; -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; @@ -21,7 +13,6 @@ 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.dynamicFrame.Constants; import org.uic.barcode.ticket.EncodingFormatException; import org.uic.barcode.utils.AlgorithmNameResolver; @@ -131,199 +122,6 @@ public class DynamicFrame extends Object{ return UperEncoder.decode(bytes, DynamicFrame.class); } - /** - * Verify the level 2 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @return the int - */ - public int validateLevel2() { - - return validateLevel2(null); - - } - - /** - * Verify the level 2 signature - * - * Note: an appropriate security provider (e.g. BC) must be registered before - * - * @param prov the prov - * @return the int - */ - 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 - * - * @param key the key - * @param prov the prov - * @return the int - */ - 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 - * - * @param key the key - * @return the int - */ - public int validateLevel1(PublicKey key) { - - return validateLevel1(key, null); - - } /** * Sign level 2 data without a specific security provider. diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java index 4095d93..199a32d 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java @@ -135,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); diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java index d354837..b8a851b 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java @@ -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); -- cgit v1.2.3 From 9ff0dde49e818348df5ba9c7bca91d165227234b Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 1 Feb 2022 14:16:00 +0100 Subject: - smplified api for level 2 signature --- src/main/java/org/uic/barcode/Encoder.java | 52 ++++ .../test/DynamicFrameV2SignatureInsert2Test.java | 270 +++++++++++++++++++++ 2 files changed, 322 insertions(+) create mode 100644 src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java index 51e86a2..9afddce 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; +import java.util.zip.DataFormatException; import org.uic.barcode.dynamicContent.api.IUicDynamicContent; import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; @@ -163,6 +164,57 @@ public class Encoder { } + /** + * Instantiates a new encoder for a level 2 encoding with tan encoded dynamic frame containing the level 1 data and signature. + * + * @param level1Data the level 1 data (binary as signed) + * @param signatureLevel1 the signature of the level 1 data + * @param version the version of the bar code + * @throws IOException Signals that an I/O exception has occurred. + * @throws EncodingFormatException the encoding format exception + * @throws DataFormatException + */ + public Encoder(byte[] encoded, int version) throws IOException, EncodingFormatException, DataFormatException { + + Decoder decoder = new Decoder(encoded); + + if (decoder.getDynamicFrame() == null) { + throw new EncodingFormatException("No dynamic frame included"); + } + + + dynamicFrame = decoder.getDynamicFrame(); + byte[] level1DataBin = decoder.getEncodedLevel1Data(); + byte[] signatureLevel1 = decoder.getLevel1Signature(); + + if (version == 1) { + + dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1); + + ILevel1Data l1 = DynamicFrameCoderV1.decodeLevel1(level1DataBin); + + dynamicFrame.getLevel2Data().setLevel1Data(l1); + + dynamicFrame.getLevel2Data().setLevel1Signature(signatureLevel1); + + } else if (version == 2) { + + dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2); + + ILevel1Data l1 = DynamicFrameCoderV2.decodeLevel1(level1DataBin); + + dynamicFrame.getLevel2Data().setLevel1Data(l1); + + dynamicFrame.getLevel2Data().setLevel1Signature(signatureLevel1); + + } else { + throw new EncodingFormatException("Version of the dynamic header not supported"); + } + + + } + + /** * Signing level 2 of a dynamic bar code diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java new file mode 100644 index 0000000..a7d5098 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/DynamicFrameV2SignatureInsert2Test.java @@ -0,0 +1,270 @@ +package org.uic.barcode.test; + +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.Security; +import java.security.SignatureException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.TimeZone; +import java.util.zip.DataFormatException; + +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.junit.Before; +import org.junit.Test; +import org.uic.barcode.Decoder; +import org.uic.barcode.Encoder; +import org.uic.barcode.dynamicFrame.Constants; +import org.uic.barcode.test.utils.DynamicTestContent; +import org.uic.barcode.test.utils.SimpleUICTestTicket; +import org.uic.barcode.ticket.EncodingFormatException; +import org.uic.barcode.ticket.api.spec.IUicRailTicket; + +public class DynamicFrameV2SignatureInsert2Test { + + public String signatureAlgorithmOID = null; + public String elipticCurve = null; + public String keyPairAlgorithmOID = null; + + public KeyPair keyPairLevel1 = null; + public KeyPair keyPairLevel2 = null; + + public byte[] passIdHash = "PassId".getBytes(); + public byte[] phoneIdHash = "myPhone".getBytes(); + + public IUicRailTicket testFCBticket = null; + + ZonedDateTime originalTimeStamp = ZonedDateTime.now(ZoneId.of("UTC")); + + @Before public void initialize() { + + signatureAlgorithmOID = Constants.ECDSA_SHA256; + keyPairAlgorithmOID = Constants.KG_EC_256; + elipticCurve = "secp256k1"; + + testFCBticket = SimpleUICTestTicket.getUicTestTicket(); + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPairLevel1 = generateECKeys(keyPairAlgorithmOID, elipticCurve); + keyPairLevel2 = generateECKeys(keyPairAlgorithmOID, elipticCurve); + } catch (Exception e) { + assert(false); + } + + + assert(keyPairLevel1 != null); + assert(keyPairLevel2 != null); + + } + + + @Test public void testDynamicHeaderBarcodeDecoding() { + + //--------------------------------------------------------------------------- + //create barcode data + IUicRailTicket ticket = testFCBticket; + + Encoder enc = null; + try { + enc = new Encoder(ticket, null, Encoder.UIC_BARCODE_TYPE_DOSIPAS, 2, 3); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + assert(enc != null); + + //complete level 1 data + enc.setLevel1Algs(signatureAlgorithmOID, keyPairAlgorithmOID); + enc.setLevel2Algs(signatureAlgorithmOID, keyPairAlgorithmOID,keyPairLevel2.getPublic()); + enc.getDynamicFrame().getLevel2Data().getLevel1Data().setEndOfBarcodeValidity(getUtcDate("2021.03.04-12:30")); + enc.getDynamicFrame().getLevel2Data().getLevel1Data().setValidityDuration(100L); + + + //sign level 1 data + try { + enc.signLevel1("1080", keyPairLevel1.getPrivate(), signatureAlgorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + // encode + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + assert(encoded != null); + + + + //---------------------------------------------------------------------------------------------- + //decode and check level 1 + Decoder dec = null; + try { + dec = new Decoder(encoded); + } catch (IOException e) { + assert(false); + } catch (EncodingFormatException e) { + assert(false); + } catch (DataFormatException e) { + assert(false); + } + assert(dec != null); + + String keyId = null; + try { + keyId = dec.getLevel1KeyId(); + } catch (EncodingFormatException e3) { + assert(false); + } + assert(keyId != null); + + + + int signatureCheck = 0; + try { + signatureCheck = dec.validateLevel1(keyPairLevel1.getPublic(),null); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + + + + + //-------------------------------------------------------------------------------------------------- + // get encoder with dynamic frame to continue + try { + enc = new Encoder(encoded, 2); + } catch (Exception e1) { + assert(false); + } + + + //set dynamic content + try { + enc.setDynamicData(DynamicTestContent.createDynamicTestContent()); + } catch (EncodingFormatException e1) { + assert(false); + } + //----------- + // sign level 2 + try { + enc.signLevel2(keyPairLevel2.getPrivate()); + } catch (Exception e) { + assert(false); + } + + //------------------------ + //encode complete bar code + encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + assert(encoded != null); + + //---------------------------------------------------------------------------------------------------- + //decode full bar code + + dec = null; + try { + dec = new Decoder(encoded); + } catch (IOException e) { + assert(false); + } catch (EncodingFormatException e) { + assert(false); + } catch (DataFormatException e) { + assert(false); + } + assert(dec != null); + + //--------------------------------------------------------------------------------------------------- + //check level 1 signature + + signatureCheck = 0; + try { + signatureCheck = dec.validateLevel1(keyPairLevel1.getPublic(),null); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + //-------------------------------------------------------------------------------------------------------- + //check level 2 signature + + signatureCheck = 0; + try { + signatureCheck = dec.validateLevel2(); + } catch (Exception e) { + assert(false); + } + assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK); + + + } + + public KeyPair generateECDSAKeys(String keyAlgorithmName, String paramName) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + + ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(paramName); + KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC"); + g.initialize(ecSpec, new SecureRandom()); + return g.generateKeyPair(); + + } + + public KeyPair generateECKeys(String keyAlgorithmOid, String curve) throws Exception{ + + String keyAlgorithmName = "ECDSA"; + ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(curve); + KeyPairGenerator g = KeyPairGenerator.getInstance(keyAlgorithmName, "BC"); + g.initialize(ecSpec, new SecureRandom()); + return g.generateKeyPair(); + + } + + public Date getUtcDate(String s) { + + TimeZone local = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + Date date = null; + try { + date = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).parse(s); + } catch (ParseException e1) { + assert(false); + } + TimeZone.setDefault(local); + + return date; + + } + + public String formatUTC(Date date) { + + TimeZone local = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + String dateS = new SimpleDateFormat( "yyyy.MM.dd-HH:mm" ).format(date); + TimeZone.setDefault(local); + return dateS; + + } + + +} -- cgit v1.2.3 From 5c88c74cc3a3aa248a2141617ed5bcb38734fd35 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Wed, 2 Feb 2022 09:09:29 +0100 Subject: version number update --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d4ef4cc..675888e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.uic.barcode org.uic.barcode - 1.3.1-SNAPSHOT + 1.3.0-SNAPSHOT jar UIC barcode encoding and decoding of bar code content according to UIC IRS 90918-9 -- cgit v1.2.3