From fc6a4042f7fca1828f0b8e267cfd660e6fe1d40a Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 22 Nov 2022 14:04:27 +0100 Subject: support for SSB barcodes SSB frame implenmentation including decoding, encoding, signing and verification --- .../java/org/uic/barcode/ssbFrame/SsbClass.java | 8 + .../uic/barcode/ssbFrame/SsbCommonTicketPart.java | 132 ++++++++++ .../java/org/uic/barcode/ssbFrame/SsbFrame.java | 282 +++++++++++++++++++++ .../java/org/uic/barcode/ssbFrame/SsbGroup.java | 146 +++++++++++ .../java/org/uic/barcode/ssbFrame/SsbHeader.java | 108 ++++++++ .../uic/barcode/ssbFrame/SsbNonReservation.java | 114 +++++++++ .../java/org/uic/barcode/ssbFrame/SsbNonUic.java | 46 ++++ .../java/org/uic/barcode/ssbFrame/SsbPass.java | 225 ++++++++++++++++ .../org/uic/barcode/ssbFrame/SsbReservation.java | 208 +++++++++++++++ .../uic/barcode/ssbFrame/SsbStationCodeTable.java | 9 + .../java/org/uic/barcode/ssbFrame/SsbStations.java | 116 +++++++++ .../org/uic/barcode/ssbFrame/SsbTicketPart.java | 29 +++ .../org/uic/barcode/ssbFrame/SsbTicketType.java | 39 +++ .../java/org/uic/barcode/utils/SecurityUtils.java | 81 ++++++ 14 files changed, 1543 insertions(+) create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbClass.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbPass.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbStationCodeTable.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbStations.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java create mode 100644 src/main/java/org/uic/barcode/ssbFrame/SsbTicketType.java diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbClass.java b/src/main/java/org/uic/barcode/ssbFrame/SsbClass.java new file mode 100644 index 0000000..cf8d9aa --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbClass.java @@ -0,0 +1,8 @@ +package org.uic.barcode.ssbFrame; + +public enum SsbClass { + + FIRST, + Second; + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java b/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java new file mode 100644 index 0000000..9512fc1 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java @@ -0,0 +1,132 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public abstract class SsbCommonTicketPart extends SsbTicketPart { + + /* + Number of adult passengers Num (<100) 7,000 + Number of child passengers Num (<100) 7,000 + "specimen" code Bit Flag 1,000 + Class of travel Lookup of 64 options 6,000 + TCN: Issuing unique Ticket number 14 AlphaNum 84,000 + Year of issue Num (0..9) 4,000 + Issuing day, from first of January Num (<512) 9,000 + */ + + protected int numberOfAdults = 0; + protected int numberOfChildren = 0; + protected boolean specimen = true; + protected SsbClass classCode = null; + protected String ticketNumber = null; + protected int year = 0; + protected int day = 0; + + protected int decodeCommonPart(byte[] bytes) { + + BitBuffer bits = new ByteBitBuffer(bytes); + + int offset = 27; // header offset + numberOfAdults = bits.getInteger(offset, 7); + offset = offset + 7; + numberOfChildren = bits.getInteger(offset, 7); + offset = offset + 7; + specimen = bits.get(offset); + offset++; + int classIndex = bits.getInteger(offset, 6); + classCode = SsbClass.values()[classIndex]; + offset = offset + 6; + ticketNumber = bits.getChar6String(offset, 84); + offset = offset + 84; + year = bits.getInteger(offset, 4); + offset = offset + 4; + day = bits.getInteger(offset, 9); + offset = offset + 9; + return offset; + } + + protected int encodeCommonPart(byte[] bytes) { + + BitBuffer bits = new ByteBitBuffer(bytes); + + int offset = 27; // header offset + bits.putInteger(offset,7, numberOfAdults); + offset = offset + 7; + bits.putInteger(numberOfChildren,offset, 7); + offset = offset + 7; + bits.put(offset,specimen); + offset++; + bits.putInteger(offset, 6,classCode.ordinal()); + offset = offset + 6; + bits.putChar6String(offset, 84, ticketNumber); + offset = offset + 84; + bits.putInteger(offset, 4, year); + offset = offset + 4; + bits.putInteger(offset, 9, day); + offset = offset + 9; + + return offset; + + + } + + public int getNumberOfAdults() { + return numberOfAdults; + } + + public void setNumberOfAdults(int numberOfAdults) { + this.numberOfAdults = numberOfAdults; + } + + public int getNumberOfChildren() { + return numberOfChildren; + } + + public void setNumberOfChildren(int numberOfChildren) { + this.numberOfChildren = numberOfChildren; + } + + public boolean isSpecimen() { + return specimen; + } + + public void setSpecimen(boolean specimen) { + this.specimen = specimen; + } + + public SsbClass getClassCode() { + return classCode; + } + + public void setClassCode(SsbClass classCode) { + this.classCode = classCode; + } + + public String getTicketNumber() { + return ticketNumber; + } + + public void setTicketNumber(String ticketNumber) { + this.ticketNumber = ticketNumber; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + + public int getDay() { + return day; + } + + public void setDay(int day) { + this.day = day; + } + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java new file mode 100644 index 0000000..b496b17 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java @@ -0,0 +1,282 @@ +package org.uic.barcode.ssbFrame; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +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.Provider.Service; +import java.util.Arrays; + + +import org.uic.barcode.ticket.EncodingFormatException; +import org.uic.barcode.utils.AlgorithmNameResolver; +import org.uic.barcode.utils.SecurityUtils; + +public class SsbFrame { + + private SsbHeader header = null; + + private byte[] signaturePart1 = null; + + private byte[] signaturePart2 = null; + + private SsbNonUic nonUicData = null; + + private SsbNonReservation nonReservationData = null; + + private SsbReservation reservationData = null; + + private SsbGroup groupData = null; + + private SsbPass passData = null; + + public void decode(byte[] bytes) throws EncodingFormatException { + + if (bytes.length != 114) { + throw new EncodingFormatException("Data size does not fit to SSB"); + } + + header = new SsbHeader(); + header.decode(bytes); + + if (header.getTicketType().equals(SsbTicketType.UIC_1_IRT_RES_BOA)) { + + reservationData = new SsbReservation(); + reservationData.decode(bytes); + + } else if (header.getTicketType().equals(SsbTicketType.UIC_2_NRT)) { + + nonReservationData = new SsbNonReservation(); + nonReservationData.decode(bytes); + + } else if (header.getTicketType().equals(SsbTicketType.UIC_3_GRP)) { + + groupData = new SsbGroup(); + groupData.decode(bytes); + + } else if (header.getTicketType().equals(SsbTicketType.UIC_4_RPT)) { + + passData = new SsbPass(); + passData.decode(bytes); + + } else { + + nonUicData = new SsbNonUic(); + nonUicData.decode(bytes); + + } + + signaturePart1 = new byte[28]; + signaturePart2 = new byte[28]; + + for (int i = 0 ; i < 28;i++) { + signaturePart1[i] = bytes[59 + i]; + signaturePart2[i] = bytes[59 + 28 + i]; + } + + } + + public byte[] encode() throws EncodingFormatException { + + byte[] bytes = new byte[114]; + + header.encode(bytes); + + if (nonUicData != null) { + nonUicData.encode(bytes); + } else if (nonReservationData != null) { + nonReservationData.encode(bytes); + } else if (reservationData != null) { + reservationData.encode(bytes); + } else if (groupData != null) { + groupData.encode(bytes); + } else if (passData != null) { + passData.encode(bytes); + } else { + throw new EncodingFormatException("Data Content for SSB missing"); + }; + + for (int i = 0 ; i < 28;i++) { + bytes[59 + i] = signaturePart1[i]; + bytes[59 + 28 + i] = signaturePart2[i]; + } + + return bytes; + + } + + public byte[] getDataForSignature() throws EncodingFormatException { + + byte[] bytes = new byte[58]; + + header.encode(bytes); + + if (nonUicData != null) { + nonUicData.encode(bytes); + } else if (nonReservationData != null) { + nonReservationData.encode(bytes); + } else if (reservationData != null) { + reservationData.encode(bytes); + } else if (groupData != null) { + groupData.encode(bytes); + } else if (passData != null) { + passData.encode(bytes); + } else { + throw new EncodingFormatException("Data Content for SSB missing"); + }; + + return bytes; + + } + + public SsbHeader getHeader() { + return header; + } + + public void setHeader(SsbHeader header) { + this.header = header; + } + + public byte[] getSignaturePart1() { + return signaturePart1; + } + + public void setSignaturePart1(byte[] signaturePart1) { + this.signaturePart1 = signaturePart1; + } + + public byte[] getSignaturePart2() { + return signaturePart2; + } + + public void setSignaturePart2(byte[] signaturePart2) { + this.signaturePart2 = signaturePart2; + } + + public SsbNonUic getNonUicData() { + return nonUicData; + } + + public void setNonUicData(SsbNonUic nonUicData) { + this.nonUicData = nonUicData; + } + + public SsbNonReservation getNonReservationData() { + return nonReservationData; + } + + public void setNonReservationData(SsbNonReservation nonReservationData) { + this.nonReservationData = nonReservationData; + } + + public SsbReservation getReservationData() { + return reservationData; + } + + public void setReservationData(SsbReservation reservationData) { + this.reservationData = reservationData; + } + + public SsbGroup getGroupData() { + return groupData; + } + + public void setGroupData(SsbGroup groupData) { + this.groupData = groupData; + } + + public SsbPass getPassData() { + return passData; + } + + public void setPassData(SsbPass passData) { + this.passData = passData; + } + + public void signLevel1(PrivateKey key, Provider prov, String algorithmOid) throws Exception { + + + byte[] data = getDataForSignature(); + + if (prov == null) { + //check for a provider supporting the key + prov = SecurityUtils.findPrivateKeyProvider(key); + } + + //find the algorithm name for the signature OID + String algo = AlgorithmNameResolver.getSignatureAlgorithmName(algorithmOid, prov); + Signature sig = null; + + if (prov != null) { + sig = Signature.getInstance(algo, prov); + } else { + sig = Signature.getInstance(algo); + } + sig.initSign(key); + + sig.update(data); + + byte[] signature = sig.sign(); + + BigInteger[] bInts = SecurityUtils.decodeSignatureIntegerSequence(signature); + + signaturePart1 = toUnsignedBytes(bInts[0]); + + signaturePart2 = toUnsignedBytes(bInts[1]); + + + } + + private static byte[] toUnsignedBytes(BigInteger i) { + byte[] b = i.abs().toByteArray(); + //remove top sign bit + if (b[0] == 0) { + b = Arrays.copyOfRange(b, 1, b.length); + } + return b; + } + + /** + * Verify the signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + * @param key the key + * @param singningAlg the Object ID of the signing algorithm + * @param a dedicated security provider to validate the signature + * @return true, if successful + * @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 operating exception + * @throws EncodingFormatException + * @throws IOException + */ + public boolean verifyByAlgorithmOid(PublicKey key, String signingAlg, Provider prov) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { + //find the algorithm name for the signature OID + String algo = null; + Service service = prov.getService("Signature",signingAlg); + if (service != null) { + algo = service.getAlgorithm(); + } + if (algo == null) { + throw new NoSuchAlgorithmException("No service for algorithm found: " + signingAlg); + } + Signature sig = Signature.getInstance(algo); + sig.initVerify(key); + sig.update(getDataForSignature()); + + BigInteger r = new BigInteger(1,signaturePart1); + BigInteger s = new BigInteger(1,signaturePart2); + + byte[] signature = SecurityUtils.encodeSignatureIntegerSequence(r,s); + + return sig.verify(signature); + } +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java b/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java new file mode 100644 index 0000000..52c3a52 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java @@ -0,0 +1,146 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbGroup extends SsbCommonTicketPart { + + protected int firstDayOfValidity = 0; + protected int lastDayOfValidity = 0; + protected boolean isReturnJourney = false; + private int infoCode = 0; + private String text = null; + private SsbStations stations = new SsbStations(); + + private String groupName = null; + + private int counterMarkNumber = 0; + + + @Override + protected void decodeContent(byte[] bytes) { + + int offset = decodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + isReturnJourney = bits.get(offset); + offset = offset++; + + firstDayOfValidity = bits.getInteger(offset, 9); + offset = offset + 9; + + lastDayOfValidity = bits.getInteger(offset, 9); + offset = offset + 9; + + offset = stations.decode(offset, bytes); + + groupName = bits.getChar6String(offset, 72); + offset = offset + 72; + + counterMarkNumber = bits.getInteger(offset, 9); + offset = offset + 9; + + infoCode = bits.getInteger(offset, 14); + offset = offset + 14; + + text = bits.getChar6String(offset, 222); + offset = offset + 222; + + } + + @Override + protected void encodeContent(byte[] bytes) { + + int offset = encodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + bits.put(offset, isReturnJourney); + offset = offset++; + + bits.putInteger(offset, 9, firstDayOfValidity); + offset = offset + 9; + + bits.putInteger(offset, 9, lastDayOfValidity); + offset = offset + 9; + + offset = stations.decode(offset, bytes); + + bits.putChar6String(offset, 72,groupName); + offset = offset + 72; + + bits.putInteger(offset, 9,counterMarkNumber); + offset = offset + 9; + + bits.putInteger(offset, 14, infoCode); + offset = offset + 14; + + bits.putChar6String(offset, 144, text); + offset = offset + 222; + + } + + public int getFirstDayOfValidity() { + return firstDayOfValidity; + } + + public void setFirstDayOfValidity(int firstDayOfValidity) { + this.firstDayOfValidity = firstDayOfValidity; + } + + public int getLastDayOfValidity() { + return lastDayOfValidity; + } + + public void setLastDayOfValidity(int lastDayOfValidity) { + this.lastDayOfValidity = lastDayOfValidity; + } + + public boolean isReturnJourney() { + return isReturnJourney; + } + + public void setReturnJourney(boolean isReturnJourney) { + this.isReturnJourney = isReturnJourney; + } + + public int getInfoCode() { + return infoCode; + } + + public void setInfoCode(int infoCode) { + this.infoCode = infoCode; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public SsbStations getStations() { + return stations; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public int getCounterMarkNumber() { + return counterMarkNumber; + } + + public void setCounterMarkNumber(int counterMarkNumber) { + this.counterMarkNumber = counterMarkNumber; + } + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java b/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java new file mode 100644 index 0000000..0d5424b --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java @@ -0,0 +1,108 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbHeader extends SsbTicketPart { + + private int version = 3; + private SsbTicketType ticketType = null; + private int keyId = 0; + private int issuer = 0; + + /* + Version Num 0-4 Bits + Issuer code Num 14 Bits + ID Num 4 Bits + Ticket type code Num 5 Bits + */ + + public SsbHeader(int version, SsbTicketType type, int keyId, int issuer) { + this.issuer = issuer; + this.keyId = keyId; + this.ticketType = type; + this.version = version; + } + + public SsbHeader() { + } + + public void decodeContent(byte[] headerData) { + + BitBuffer bits = new ByteBitBuffer(headerData); + + version = bits.getInteger(0, 4); + issuer = bits.getInteger(4, 14); + keyId = bits.getInteger(18, 4); + ticketType = SsbTicketType.values()[bits.getInteger(22, 5)]; + + return; + + } + + public void encodeContent(byte[] bytes) { + + BitBuffer bits = new ByteBitBuffer(bytes); + + bits.putInteger(0, 4, version); + bits.putInteger(4, 14, issuer); + bits.putInteger(18, 4, keyId); + bits.putInteger(22, 5, ticketType.ordinal()); + + } + + + + public int getVersion() { + return version; + } + + + + public void setVersion(int version) { + this.version = version; + } + + + + public SsbTicketType getTicketType() { + return ticketType; + } + + + + public void setTicketType(SsbTicketType ticketType) { + this.ticketType = ticketType; + } + + + + public int getKeyId() { + return keyId; + } + + + + public void setKeyId(int keyId) { + this.keyId = keyId; + } + + + + public int getIssuer() { + return issuer; + } + + + + public void setIssuer(int issuer) { + this.issuer = issuer; + } + + + + + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java b/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java new file mode 100644 index 0000000..e96e853 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java @@ -0,0 +1,114 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbNonReservation extends SsbCommonTicketPart { + + protected int firstDayOfValidity = 0; + protected int lastDayOfValidity = 0; + protected boolean isReturnJourney = false; + private int infoCode = 0; + private String text = null; + private SsbStations stations = new SsbStations(); + + + @Override + protected void decodeContent(byte[] bytes) { + + int offset = decodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + isReturnJourney = bits.get(offset); + offset = offset++; + + firstDayOfValidity = bits.getInteger(offset, 9); + offset = offset + 9; + + lastDayOfValidity = bits.getInteger(offset, 9); + offset = offset + 9; + + offset = stations.decode(offset, bytes); + + infoCode = bits.getInteger(offset, 14); + offset = offset + 14; + + text = bits.getChar6String(offset, 222); + offset = offset + 222; + + } + + @Override + protected void encodeContent(byte[] bytes) { + + int offset = encodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + bits.put(offset, isReturnJourney); + offset = offset++; + + bits.putInteger(offset, 9, firstDayOfValidity); + offset = offset + 9; + + bits.putInteger(offset, 9, lastDayOfValidity); + offset = offset + 9; + + offset = stations.decode(offset, bytes); + + bits.putInteger(offset, 14, infoCode); + offset = offset + 14; + + bits.putChar6String(offset, 222, text); + offset = offset + 222; + + } + + public int getFirstDayOfValidity() { + return firstDayOfValidity; + } + + public void setFirstDayOfValidity(int firstDayOfValidity) { + this.firstDayOfValidity = firstDayOfValidity; + } + + public int getLastDayOfValidity() { + return lastDayOfValidity; + } + + public void setLastDayOfValidity(int lastDayOfValidity) { + this.lastDayOfValidity = lastDayOfValidity; + } + + public boolean isReturnJourney() { + return isReturnJourney; + } + + public void setReturnJourney(boolean isReturnJourney) { + this.isReturnJourney = isReturnJourney; + } + + public int getInfoCode() { + return infoCode; + } + + public void setInfoCode(int infoCode) { + this.infoCode = infoCode; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public SsbStations getStations() { + return stations; + } + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java b/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java new file mode 100644 index 0000000..28e5105 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java @@ -0,0 +1,46 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.AsnUtils; +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbNonUic extends SsbTicketPart { + + byte[] openData = null; + + @Override + protected void decodeContent(byte[] bytes) { + + String bitString = AsnUtils.toBooleanString(bytes); + + openData = AsnUtils.fromBooleanString(bitString); + + } + + @Override + protected void encodeContent(byte[] bytes) { + + BitBuffer bits = new ByteBitBuffer(bytes); + + String bitString = AsnUtils.toBooleanString(openData); + + for (int i = 0;i< 58 *8 ;i++) { + if (bitString.charAt(i) == '0') { + bits.put(27 + i, true); + } else { + bits.put(27 + i, false); + } + } + } + + public byte[] getOpenData() { + return openData; + } + + public void setOpenData(byte[] openData) { + this.openData = openData; + } + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java b/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java new file mode 100644 index 0000000..a38dfaf --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java @@ -0,0 +1,225 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbPass extends SsbCommonTicketPart { + + /* + * RPT sub ticket type 3 values 2 2 bit 1 = INTERRAIL, 2 = EURAIL EUROPE, 3 = EURAIL OVERSEAS + First day of validity from the issuing date Num (<367) 9 bit 000 = open date for regular Eurail pass to be activated + Maximum duration from the issuing date for OVERSEAS; otherwise, last day of validity Num (<278) 9 bit 9 months max. validity + Number of days of travel allowed Num (<93) 7 bit + Country code 1 Num (<100) 7 0.875 100 = all countries + Country code 2 Num (<99) 7 0.875 If country code 1 is 100, then 00 + Country code 3 Num (<99) 7 0.875 If country code 1 is 100, then 00 + Country code 4 Num (<99) 7 0.875 If country code 1 is 100, then 00 + Country code 5 Num (<99) 7 0.875 If country code 1 is 100, then 00 + Second page Bit flag 1 0.125 For a two-page pass + Information messages Num (<9999) 14 1.75 + Open text 6-bit ASCII (40 Char) 240 30 + */ + + + private int passSubType = 0; + private int firstDayOfValidity = 0; + private int maximumValidityDuration = 0; + private int numberOfTravels = 0; + private int country_1 = 0; + private int country_2 = 0; + private int country_3 = 0; + private int country_4 = 0; + private int country_5 = 0; + private boolean hasSecondPage = false; + private int infoCode = 0; + private String text = null; + + @Override + protected void decodeContent(byte[] bytes) { + + int offset = decodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + passSubType = bits.getInteger(offset, 2); + offset = offset + 2; + + firstDayOfValidity = bits.getInteger(offset, 9); + offset = offset + 9; + + maximumValidityDuration = bits.getInteger(offset, 9); + offset = offset + 9; + + numberOfTravels = bits.getInteger(offset, 7); + offset = offset + 7; + + country_1 = bits.getInteger(offset, 7); + offset = offset + 7; + + country_2 = bits.getInteger(offset, 7); + offset = offset + 7; + + country_3 = bits.getInteger(offset, 7); + offset = offset + 7; + + country_4 = bits.getInteger(offset, 7); + offset = offset + 7; + + country_5 = bits.getInteger(offset, 7); + offset = offset + 7; + + hasSecondPage = bits.get(offset); + offset++; + + infoCode = bits.getInteger(offset, 14); + offset = offset + 14; + + text = bits.getChar6String(offset, 240); + offset = offset + 240; + + } + + @Override + protected void encodeContent(byte[] bytes) { + + int offset = encodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + bits.putInteger(offset, 2,passSubType); + offset = offset + 2; + + bits.putInteger(offset, 9,firstDayOfValidity); + offset = offset + 9; + + bits.putInteger(offset, 9,maximumValidityDuration); + offset = offset + 9; + + bits.putInteger(offset, 7, numberOfTravels); + offset = offset + 7; + + bits.putInteger(offset, 7,country_1); + offset = offset + 7; + + bits.putInteger(offset, 7,country_2); + offset = offset + 7; + + bits.putInteger(offset, 7,country_3); + offset = offset + 7; + + bits.putInteger(offset, 7,country_4); + offset = offset + 7; + + bits.putInteger(offset, 7,country_5); + offset = offset + 7; + + bits.put(offset, hasSecondPage); + offset++; + + bits.putInteger(offset, 14, infoCode); + offset = offset + 14; + + bits.putChar6String(offset, 240,text); + offset = offset + 240; + } + + public int getPassSubType() { + return passSubType; + } + + public void setPassSubType(int passSubType) { + this.passSubType = passSubType; + } + + public int getFirstDayOfValidity() { + return firstDayOfValidity; + } + + public void setFirstDayOfValidity(int firstDayOfValidity) { + this.firstDayOfValidity = firstDayOfValidity; + } + + public int getMaximumValidityDuration() { + return maximumValidityDuration; + } + + public void setMaximumValidityDuration(int maximumValidityDuration) { + this.maximumValidityDuration = maximumValidityDuration; + } + + public int getNumberOfTravels() { + return numberOfTravels; + } + + public void setNumberOfTravels(int numberOfTravels) { + this.numberOfTravels = numberOfTravels; + } + + public int getCountry_1() { + return country_1; + } + + public void setCountry_1(int country_1) { + this.country_1 = country_1; + } + + public int getCountry_2() { + return country_2; + } + + public void setCountry_2(int country_2) { + this.country_2 = country_2; + } + + public int getCountry_3() { + return country_3; + } + + public void setCountry_3(int country_3) { + this.country_3 = country_3; + } + + public int getCountry_4() { + return country_4; + } + + public void setCountry_4(int country_4) { + this.country_4 = country_4; + } + + public int getCountry_5() { + return country_5; + } + + public void setCountry_5(int country_5) { + this.country_5 = country_5; + } + + public boolean isHasSecondPage() { + return hasSecondPage; + } + + public void setHasSecondPage(boolean hasSecondPage) { + this.hasSecondPage = hasSecondPage; + } + + public int getInfoCode() { + return infoCode; + } + + public void setInfoCode(int infoCode) { + this.infoCode = infoCode; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java b/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java new file mode 100644 index 0000000..c7f520d --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java @@ -0,0 +1,208 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbReservation extends SsbCommonTicketPart { + + private SsbStations stations = new SsbStations(); + + private int ticketSubType = 0; + + private int departureDate = 0; + + private int departureTime = 0; + + private String train = null; + + private int coach = 0; + + private String place = null; + + private boolean overbooking = false; + + private int infoCode = 0; + + private String text = null; + + + + + + @Override + protected void decodeContent(byte[] bytes) { + + int offset = decodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + ticketSubType = bits.getInteger(offset, 2); + offset = offset + 4; + + stations = new SsbStations(); + stations.decode(offset, bytes); + + /* + * Departure date : First day of validity from the issuing date Num (<367) 9,000 + Departure Time Num (<1440) 11,000 + Train number AlphaNum + 5 Car 30,000 + Coach number Num (< 999) 10,000 + Seat/berth number 3 AlphaNum 18,000 + Overbooking indicator Bit Flag 1,000 + Information Messages Num (< 9999) 14,000 + Open Tekst 6 Bit ASCII (27 Car) 162,000 + */ + + departureDate = bits.getInteger(offset, 9); + offset = offset + 9; + + departureTime = bits.getInteger(offset, 11); + offset = offset + 11; + + train = bits.getChar6String(offset, 30); + offset = offset +30; + + coach = bits.getInteger(offset, 10); + offset = offset + 10; + + place = bits.getChar6String(offset, 18); + offset = offset + 18; + + overbooking = bits.get(offset); + offset++; + + infoCode = bits.getInteger(offset, 14); + offset = offset + 14; + + text = bits.getChar6String(offset, 162); + offset = offset + 162; + } + + @Override + protected void encodeContent(byte[] bytes) { + + int offset = encodeCommonPart(bytes); + + BitBuffer bits = new ByteBitBuffer(bytes); + + bits.putInteger(offset, 2,ticketSubType); + offset = offset + 4; + + offset = stations.encode(offset, bytes); + + /* + * Departure date : First day of validity from the issuing date Num (<367) 9,000 + Departure Time Num (<1440) 11,000 + Train number AlphaNum + 5 Car 30,000 + Coach number Num (< 999) 10,000 + Seat/berth number 3 AlphaNum 18,000 + Overbooking indicator Bit Flag 1,000 + Information Messages Num (< 9999) 14,000 + Open Tekst 6 Bit ASCII (27 Car) 162,000 + */ + + bits.putInteger(offset, 9, departureDate); + offset = offset + 9; + + bits.putInteger(offset, 11,departureTime); + offset = offset + 11; + + bits.putChar6String(offset, 30,train); + offset = offset +30; + + bits.putInteger(offset, 10,coach); + offset = offset + 10; + + bits.putChar6String(offset, 18,place); + offset = offset + 18; + + bits.put(offset, overbooking); + offset++; + + bits.putInteger(offset, 14, infoCode); + offset = offset + 14; + + bits.putChar6String(offset, 162, text); + offset = offset + 162; + + } + + public SsbStations getStations() { + return stations; + } + + public int getTicketSubType() { + return ticketSubType; + } + + public void setTicketSubType(int ticketSubType) { + this.ticketSubType = ticketSubType; + } + + public int getDepartureDate() { + return departureDate; + } + + public void setDepartureDate(int departureDate) { + this.departureDate = departureDate; + } + + public int getDepartureTime() { + return departureTime; + } + + public void setDepartureTime(int departureTime) { + this.departureTime = departureTime; + } + + public String getTrain() { + return train; + } + + public void setTrain(String train) { + this.train = train; + } + + public int getCoach() { + return coach; + } + + public void setCoach(int coach) { + this.coach = coach; + } + + public String getPlace() { + return place; + } + + public void setPlace(String place) { + this.place = place; + } + + public boolean isOverbooking() { + return overbooking; + } + + public void setOverbooking(boolean overbooking) { + this.overbooking = overbooking; + } + + public int getInfoCode() { + return infoCode; + } + + public void setInfoCode(int infoCode) { + this.infoCode = infoCode; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbStationCodeTable.java b/src/main/java/org/uic/barcode/ssbFrame/SsbStationCodeTable.java new file mode 100644 index 0000000..8aeaf22 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbStationCodeTable.java @@ -0,0 +1,9 @@ +package org.uic.barcode.ssbFrame; + +public enum SsbStationCodeTable { + + UNKNOWN_0, + NRT, + RESERVATION, + UNKNOWN_3; +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java b/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java new file mode 100644 index 0000000..34fbbc3 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java @@ -0,0 +1,116 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.asn1.uper.BitBuffer; +import org.uic.barcode.asn1.uper.ByteBitBuffer; + +public class SsbStations { + + /* + * Station code 1 bit 0 = Num; or 1=Bilateral AlphaNum 6Char + + Numeric: + Station code List 4 bit 1= NRT; 2=Reservation + Departure station Location 28 bit + Arrival Station 28 bit + + AlphaNum: + Departure: 30 bit + Arrival = 30 bit + + */ + + protected String arrivalStationCode = " "; + protected String departureStationCode = " "; + protected SsbStationCodeTable codeTable = SsbStationCodeTable.NRT; + + + + public int encode(int offset, byte[] bytes) { + + boolean isAlphaNumeric = false; + + BitBuffer bits = new ByteBitBuffer(bytes); + + try { + Integer.parseInt(arrivalStationCode); + Integer.parseInt(departureStationCode); + isAlphaNumeric = false; + } catch(NumberFormatException e) { + isAlphaNumeric = true; + } + bits.put(offset, isAlphaNumeric); + offset++; + + if (isAlphaNumeric) { + bits.putChar6String(offset,30, departureStationCode); + offset = offset + 30; + bits.putChar6String(offset,30, arrivalStationCode); + offset = offset + 30; + } else { + bits.putInteger(offset, 4, codeTable.ordinal()); + offset = offset + 4; + bits.putInteger(offset, 28, Integer.parseInt(departureStationCode)); + offset = offset + 28; + bits.putInteger(offset, 28, Integer.parseInt(arrivalStationCode)); + offset = offset + 28; + } + + return offset; + + } + + public int decode(int offset, byte[] bytes) { + + BitBuffer bits = new ByteBitBuffer(bytes); + + boolean isAlphaNumeric = bits.get(offset); + offset++; + + if (isAlphaNumeric) { + departureStationCode = bits.getChar6String(offset,30); + offset = offset + 30; + arrivalStationCode = bits.getChar6String(offset,30); + offset = offset + 30; + } else { + codeTable = SsbStationCodeTable.values()[bits.getInteger(offset, 4)]; + offset = offset + 4; + departureStationCode = Integer.toString(bits.getInteger(offset, 28)); + offset = offset + 28; + arrivalStationCode = Integer.toString(bits.getInteger(offset, 28)); + offset = offset + 28; + } + + + + return offset; + + } + + public String getArrivalStationCode() { + return arrivalStationCode; + } + + public void setArrivalStationCode(String arrivalStationCode) { + this.arrivalStationCode = arrivalStationCode; + } + + public String getDepartureStationCode() { + return departureStationCode; + } + + public void setDepartureStationCode(String departureStationCode) { + this.departureStationCode = departureStationCode; + } + + public SsbStationCodeTable getCodeTable() { + return codeTable; + } + + public void setCodeTable(SsbStationCodeTable codeTable) { + this.codeTable = codeTable; + } + + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java new file mode 100644 index 0000000..3855c5c --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java @@ -0,0 +1,29 @@ +package org.uic.barcode.ssbFrame; + +import org.uic.barcode.ticket.EncodingFormatException; + +public abstract class SsbTicketPart { + + public void decode(byte[] bytes) throws EncodingFormatException { + if (bytes.length != 114) { + throw new EncodingFormatException("Data size does not fit to SSB"); + } + decodeContent(bytes); + }; + + protected abstract void decodeContent(byte[] bytes); + + public void encode(byte[] bytes) throws EncodingFormatException { + if (bytes.length != 114) { + throw new EncodingFormatException("Data size does not fit to SSB"); + } + encodeContent(bytes); + } + + protected abstract void encodeContent(byte[] bytes); + + + + + +} diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbTicketType.java b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketType.java new file mode 100644 index 0000000..cb60a26 --- /dev/null +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketType.java @@ -0,0 +1,39 @@ +package org.uic.barcode.ssbFrame; + +public enum SsbTicketType { + + UIC_1_IRT_RES_BOA, + UIC_2_NRT, + UIC_3_GRP, + UIC_4_RPT, + UIC_5_UNDEFINED, + UIC_6_UNDEFINED, + UIC_7_UNDEFINED, + UIC_8_UNDEFINED, + UIC_9_UNDEFINED, + UIC_10_UNDEFINED, + UIC_11_UNDEFINED, + UIC_12_UNDEFINED, + UIC_13_UNDEFINED, + UIC_14_UNDEFINED, + UIC_15_UNDEFINED, + UIC_16_UNDEFINED, + UIC_17_UNDEFINED, + UIC_18_UNDEFINED, + UIC_19_UNDEFINED, + UIC_20_UNDEFINED, + NONUIC_21_BILATERAL, + NONUIC_22_BILATERAL, + NONUIC_23_BILATERAL, + NONUIC_24_BILATERAL, + NONUIC_25_BILATERAL, + NONUIC_26_BILATERAL, + NONUIC_27_BILATERAL, + NONUIC_28_BILATERAL, + NONUIC_29_BILATERAL, + NONUIC_30_BILATERAL, + NONUIC_31_BILATERAL, + NONUIC_32_BILATERAL; + + +} diff --git a/src/main/java/org/uic/barcode/utils/SecurityUtils.java b/src/main/java/org/uic/barcode/utils/SecurityUtils.java index 5fdbda7..29a2346 100644 --- a/src/main/java/org/uic/barcode/utils/SecurityUtils.java +++ b/src/main/java/org/uic/barcode/utils/SecurityUtils.java @@ -1,5 +1,8 @@ package org.uic.barcode.utils; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -10,6 +13,7 @@ import java.security.Security; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; /** * The Class SecurityUtils. @@ -182,4 +186,81 @@ public class SecurityUtils { return null; } + + /** + * Decode signature integer sequence. + * + * Support function to decode a DSA signature + * Provides the two DSA signature parameter encoded in a DSA signature + * + * @param bytes the bytes + * @return the big integer[] + * @throws Exception the exception + */ + public static BigInteger[] decodeSignatureIntegerSequence(byte[] bytes) throws Exception { + + int sequenceTag = (int) bytes[0]; + + if (sequenceTag != 48) throw new Exception("signature is not a sequence"); + + int sequenceLength = (int) bytes[1]; + + if (sequenceLength < 6) throw new Exception("signature sequence too short"); + + BigInteger[] result = new BigInteger[2]; + + int offset = 2; + int i = 0; + while (offset < bytes.length && i < 2) { + int integerTag = (int) bytes[offset]; + if (integerTag != 2) throw new Exception("signature is not an integer sequence"); + int integerLength = (int) bytes[offset + 1]; + byte[] value = Arrays.copyOfRange(bytes, offset + 2, offset + 2 + integerLength); + result[i] = new BigInteger(+1, value); + offset = offset + integerLength + 2; + i++; + } + + return result; + } + + /** + * Encode signature integer sequence. + * + * Support function to format two parameters as DER encoded integer list + * to get a valid formated DSA signature from the signature parameter + * + * @param i1 the i 1 + * @param i2 the i 2 + * @return the byte[] + * @throws IOException Signals that an I/O exception has occurred. + */ + public static byte[] encodeSignatureIntegerSequence(BigInteger i1, BigInteger i2) throws IOException { + + //SEQUENCE OF --> tag 16 + int sequenceTag = 16 + 32; // (bits 6 = 1 constructed) + //INTEGER --> tag 2 + int integerTag = 2; + + byte[] b1 = i1.toByteArray(); + int lb1 = b1.length; + byte[] b2 = i2.toByteArray(); + int lb2 = b2.length; + + int sequenceLength = lb1 + lb2 + 4; + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + out.write((byte) sequenceTag); + out.write((byte) sequenceLength); + out.write((byte) integerTag); + out.write((byte) lb1); + out.write(b1); + out.write((byte) integerTag); + out.write((byte) lb2); + out.write(b2); + + return out.toByteArray(); + } + } -- cgit v1.2.3 From d86d66e0ac0c296d813e985217299a4a900a5e49 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Fri, 10 Feb 2023 14:22:57 +0100 Subject: new exception for wrong identifiers in U_HEAD --- src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java b/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java index 22ba8ce..fdef178 100644 --- a/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java +++ b/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java @@ -224,6 +224,16 @@ public class UHEADDataRecord extends DataRecord{ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String issuerElement = String.format("%4s", this.issuer); + + if (this.identifier == null || this.identifier.length() < 1) { + throw new EncodingFormatException("Identifier in U_HEAD missing"); + } + + if (this.identifier.length() > 20) { + throw new EncodingFormatException("Identifier in U_HEAD too long (max. 20 byte)"); + } + + String idElement = String.format("%20s", this.identifier); -- cgit v1.2.3 From 51da5b4938b7acb2ce75b4a1d35f5fc3115276cc Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Fri, 10 Feb 2023 14:29:44 +0100 Subject: error messages for wrong header content --- .../uic/barcode/staticFrame/UHEADDataRecord.java | 24 ++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java b/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java index fdef178..31a664b 100644 --- a/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java +++ b/src/main/java/org/uic/barcode/staticFrame/UHEADDataRecord.java @@ -222,7 +222,15 @@ public class UHEADDataRecord extends DataRecord{ protected void encodeContent() throws IOException, EncodingFormatException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - + + if (this.issuer == null || this.issuer.length() < 1) { + throw new EncodingFormatException("Issuer in U_HEAD missing"); + } + if (this.issuer.length() > 4) { + throw new EncodingFormatException("Issuer in U_HEAD too long (max 4 bytes)"); + } + + String issuerElement = String.format("%4s", this.issuer); if (this.identifier == null || this.identifier.length() < 1) { @@ -230,7 +238,7 @@ public class UHEADDataRecord extends DataRecord{ } if (this.identifier.length() > 20) { - throw new EncodingFormatException("Identifier in U_HEAD too long (max. 20 byte)"); + throw new EncodingFormatException("Identifier in U_HEAD too long (max. 20 bytes)"); } @@ -258,12 +266,20 @@ public class UHEADDataRecord extends DataRecord{ String language1 = null; String language2 = null; if (this.language != null) { - language1 = String.format("%2s" ,this.language); + if (this.language.length() > 2) { + language1 = String.format("%2s" ,this.language.substring(0, 2)); + } else { + language1 = String.format("%2s" ,this.language); + } } else { language1 = " "; } if (this.additionalLanguage != null) { - language2 = String.format("%2s" ,this.additionalLanguage); + if (this.additionalLanguage.length() > 2) { + language2 = String.format("%2s" ,this.additionalLanguage.substring(0, 2)); + } else { + language2 = String.format("%2s" ,this.additionalLanguage); + } } else { language2 = " "; } -- cgit v1.2.3 From 37ddd3d075d0664de44f05639712869596bfb9cd Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Thu, 9 Mar 2023 16:30:19 +0100 Subject: ssb added to encoder and decoder --- src/main/java/org/uic/barcode/Decoder.java | 151 +++++++++++++++------ src/main/java/org/uic/barcode/Encoder.java | 24 ++++ .../java/org/uic/barcode/ssbFrame/SsbFrame.java | 32 ++++- 3 files changed, 162 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index 9f5ea82..1b3fb0c 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -15,6 +15,7 @@ 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.ssbFrame.SsbFrame; import org.uic.barcode.staticFrame.StaticFrame; import org.uic.barcode.staticFrame.UFLEXDataRecord; import org.uic.barcode.staticFrame.UTLAYDataRecord; @@ -39,6 +40,9 @@ public class Decoder { /** The static frame. */ private StaticFrame staticFrame = null; + /** The ssb frame. */ + private SsbFrame ssbFrame = null; + /** The uic ticket coder. */ private UicRailTicketCoder uicTicketCoder = null; @@ -80,7 +84,7 @@ public class Decoder { * @throws EncodingFormatException the encoding format exception */ public int validateLevel1(PublicKey key) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { - if (dynamicFrame != null) { + if (dynamicFrame != null && dynamicFrame != null) { return dynamicFrame.validateLevel1(key) ; } else { if (staticFrame != null) { @@ -106,15 +110,22 @@ 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 (dynamicFrame != null) { + if (dynamicFrame != null ) { return dynamicFrame.validateLevel1(key, signingAlg) ; - } else { + } else if (staticFrame != null) { if (staticFrame.verifyByAlgorithmOid(key,signingAlg)) { return Constants.LEVEL1_VALIDATION_OK; } else { return Constants.LEVEL1_VALIDATION_FRAUD; } + } else if (ssbFrame!= null) { + if (ssbFrame.verifyByAlgorithmOid(key,signingAlg, null)) { + return Constants.LEVEL1_VALIDATION_OK; + } else { + return Constants.LEVEL1_VALIDATION_FRAUD; + } } + return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; } /** @@ -133,15 +144,25 @@ public class Decoder { * @throws EncodingFormatException the encoding format exception */ public int validateLevel1(PublicKey key, String signingAlg, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { - if (!isStaticHeader(data)) { + if (!isStaticHeader(data) && dynamicFrame != null) { return dynamicFrame.validateLevel1(key, provider) ; - } else { + } else if (isSsbFrame(data) && ssbFrame != null) { + + if (ssbFrame.verifyByAlgorithmOid(key,signingAlg, provider)) { + return Constants.LEVEL1_VALIDATION_OK; + } else { + return Constants.LEVEL1_VALIDATION_FRAUD; + } + + } else if (staticFrame != null) { + if (staticFrame.verifyByAlgorithmOid(key,signingAlg, provider)) { return Constants.LEVEL1_VALIDATION_OK; } else { return Constants.LEVEL1_VALIDATION_FRAUD; } } + return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; } /** @@ -151,7 +172,7 @@ public class Decoder { * @throws EncodingFormatException */ public int validateLevel2() throws EncodingFormatException { - if (!isStaticHeader(data)) { + if (!isStaticHeader(data) && dynamicFrame != null) { return dynamicFrame.validateLevel2() ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; @@ -164,7 +185,7 @@ public class Decoder { * @return the return code indicating errors */ public int validateLevel2(Provider prov) throws EncodingFormatException { - if (!isStaticHeader(data)) { + if (!isStaticHeader(data) && dynamicFrame != null) { return dynamicFrame.validateLevel2(prov) ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; @@ -183,45 +204,74 @@ public class Decoder { public void decode(byte[] data) throws IOException, EncodingFormatException, DataFormatException { if (!isStaticHeader(data)) { - - dynamicFrame = DynamicFrameCoder.decode(data); - - ILevel2Data level2 = dynamicFrame.getLevel2Data(); - - ILevel1Data level1 = level2.getLevel1Data(); - - for (IData level1Content : level1.getData()) { - - uicTicketCoder = new UicRailTicketCoder(); - if (level1Content.getFormat().equals("FCB1")) { - uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 1); - } else if (level1Content.getFormat().equals("FCB2")) { - uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 2); - } else if (level1Content.getFormat().equals("FCB3")) { - uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 3); + try { + decodeDynamicFrame(data); + } catch (Exception e) { + dynamicFrame = null; + if (isSsbFrame(data)) { + decodeSsbFrame(data); + } else { + throw e; } } - + } else if (isStaticHeader(data)){ - - staticFrame = new StaticFrame(); - - staticFrame.decode(data); - - UFLEXDataRecord flex = staticFrame.getuFlex(); - - if (flex != null) { - uicTicket = flex.getTicket(); + try { + decodeStaticFrame(data); + } catch (Exception e) { + staticFrame = null; + throw e; } - - UTLAYDataRecord tlay = staticFrame.getuTlay(); + } + } + + private void decodeDynamicFrame(byte[] data) throws EncodingFormatException, IOException { + + dynamicFrame = DynamicFrameCoder.decode(data); + + ILevel2Data level2 = dynamicFrame.getLevel2Data(); + + ILevel1Data level1 = level2.getLevel1Data(); + + for (IData level1Content : level1.getData()) { - if (tlay != null) { - layout = tlay.getLayout(); + uicTicketCoder = new UicRailTicketCoder(); + if (level1Content.getFormat().equals("FCB1")) { + uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 1); + } else if (level1Content.getFormat().equals("FCB2")) { + uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 2); + } else if (level1Content.getFormat().equals("FCB3")) { + uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 3); } } } + + private void decodeStaticFrame(byte[] data) throws EncodingFormatException, DataFormatException, IOException { + + staticFrame = new StaticFrame(); + + staticFrame.decode(data); + + UFLEXDataRecord flex = staticFrame.getuFlex(); + + if (flex != null) { + uicTicket = flex.getTicket(); + } + + UTLAYDataRecord tlay = staticFrame.getuTlay(); + + if (tlay != null) { + layout = tlay.getLayout(); + } + } + private void decodeSsbFrame(byte[] data) throws EncodingFormatException, DataFormatException, IOException { + + ssbFrame = new SsbFrame(); + + ssbFrame.decode(data); + + } /** * Checks if is static header. @@ -235,6 +285,19 @@ public class Decoder { return true; } + /** + * Checks if is ssb frame. + * + * @param data the data + * @return true, if is static header + */ + private boolean isSsbFrame(byte[] data) { + if (data.length == 144) { + return true; + } + return false; + } + /** * Gets the uic ticket. * @@ -301,14 +364,14 @@ public class Decoder { } public IData getLevel2Data() { - if (!isStaticHeader(data) && dynamicFrame.getLevel2Data() != null) { + if (!isStaticHeader(data) && dynamicFrame != null && dynamicFrame.getLevel2Data() != null) { return dynamicFrame.getLevel2Data().getLevel2Data(); } return null; } public byte[] getEncodedLevel1Data() throws IOException, EncodingFormatException { - if (!isStaticHeader(data)) { + if (!isStaticHeader(data) && dynamicFrame != null) { return dynamicFrame.getLevel1DataBin(); } else if (staticFrame != null) { return staticFrame.getDataForSignature(); @@ -341,5 +404,15 @@ public class Decoder { } } + + public SsbFrame getSsbFrame() { + return ssbFrame; + } + + public void setSsbFrame(SsbFrame ssbFrame) { + this.ssbFrame = ssbFrame; + } + + } diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java index b01ca14..cf2d4d2 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -19,6 +19,7 @@ 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.ssbFrame.SsbFrame; import org.uic.barcode.staticFrame.StaticFrame; import org.uic.barcode.staticFrame.UFLEXDataRecord; import org.uic.barcode.staticFrame.UHEADDataRecord; @@ -45,6 +46,9 @@ public class Encoder { /** The static frame. */ private StaticFrame staticFrame = null; + /** The ssb frame. */ + private SsbFrame ssbFrame = null; + /** The UIC bar code type classic. */ public static String UIC_BARCODE_TYPE_CLASSIC = "UIC_CLASSIC"; @@ -52,6 +56,9 @@ public class Encoder { /** The UIC bar code type DOSIPAS. */ public static String UIC_BARCODE_TYPE_DOSIPAS = "UIC_DOSIPAS"; + /** The UIC bar code type SSB. */ + public static String UIC_BARCODE_TYPE_SSB = "UIC_SSB"; + /** * Instantiates a new encoder. * @@ -119,6 +126,11 @@ public class Encoder { dynamicFrame.getLevel2Data().getLevel1Data().addData(ticketData); } + + } else if (barcodeType == UIC_BARCODE_TYPE_SSB) { + + ssbFrame = new SsbFrame(); + } } @@ -369,6 +381,8 @@ public class Encoder { staticFrame.getHeaderRecord().setIssuer(securityProvider); } staticFrame.signByAlgorithmOID(key,signingAlg); + } else if (ssbFrame != null) { + ssbFrame.signLevel1(key, null, keyId, signingAlg); } } @@ -395,6 +409,8 @@ public class Encoder { staticFrame.getHeaderRecord().setIssuer(securityProvider); } staticFrame.signByAlgorithmOID(key,signingAlg,prov); + } else if (ssbFrame != null) { + ssbFrame.signLevel1(key, prov, keyId, signingAlg); } } @@ -461,6 +477,14 @@ public class Encoder { } } + public SsbFrame getSsbFrame() { + return ssbFrame; + } + + public void setSsbFrame(SsbFrame ssbFrame) { + this.ssbFrame = ssbFrame; + } + diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java index b496b17..81b5eb4 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java @@ -7,6 +7,7 @@ import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.PublicKey; +import java.security.Security; import java.security.Signature; import java.security.SignatureException; import java.security.Provider.Service; @@ -198,16 +199,18 @@ public class SsbFrame { this.passData = passData; } - public void signLevel1(PrivateKey key, Provider prov, String algorithmOid) throws Exception { + public void signLevel1(PrivateKey key, Provider prov, String keyId, String algorithmOid) throws Exception { + this.header.setKeyId(Integer.parseInt(keyId)); + byte[] data = getDataForSignature(); if (prov == null) { //check for a provider supporting the key prov = SecurityUtils.findPrivateKeyProvider(key); } - + //find the algorithm name for the signature OID String algo = AlgorithmNameResolver.getSignatureAlgorithmName(algorithmOid, prov); Signature sig = null; @@ -261,10 +264,25 @@ public class SsbFrame { public boolean verifyByAlgorithmOid(PublicKey key, String signingAlg, Provider prov) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { //find the algorithm name for the signature OID String algo = null; - Service service = prov.getService("Signature",signingAlg); - if (service != null) { - algo = service.getAlgorithm(); - } + + if (prov != null) { + Service service = prov.getService("Signature",signingAlg); + if (service != null) { + algo = service.getAlgorithm(); + } + } else { + Provider[] provs = Security.getProviders(); + for (Provider p : provs) { + if (algo == null) { + Service service = p.getService("Signature",signingAlg); + if (service != null) { + algo = service.getAlgorithm(); + } + } + } + + } + if (algo == null) { throw new NoSuchAlgorithmException("No service for algorithm found: " + signingAlg); } @@ -279,4 +297,6 @@ public class SsbFrame { return sig.verify(signature); } + + } -- cgit v1.2.3 From 7ec06722923d96d2e51300bafb44b920ca341d58 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Fri, 10 Mar 2023 16:49:58 +0100 Subject: ssb unit tests --- src/main/java/org/uic/barcode/Decoder.java | 9 +- src/main/java/org/uic/barcode/Encoder.java | 2 + .../org/uic/barcode/asn1/uper/ByteBitBuffer.java | 1 + src/main/java/org/uic/barcode/package.html | 30 +-- .../uic/barcode/ssbFrame/SsbCommonTicketPart.java | 7 +- .../java/org/uic/barcode/ssbFrame/SsbFrame.java | 102 +++++++--- .../java/org/uic/barcode/ssbFrame/SsbGroup.java | 19 +- .../java/org/uic/barcode/ssbFrame/SsbHeader.java | 8 +- .../uic/barcode/ssbFrame/SsbNonReservation.java | 14 +- .../java/org/uic/barcode/ssbFrame/SsbNonUic.java | 41 +++- .../java/org/uic/barcode/ssbFrame/SsbPass.java | 11 +- .../org/uic/barcode/ssbFrame/SsbReservation.java | 24 ++- .../org/uic/barcode/ssbFrame/SsbTicketPart.java | 10 +- .../java/org/uic/barcode/staticFrame/package.html | 29 +-- .../org/uic/barcode/ticket/api/asn/package.html | 8 +- .../org/uic/barcode/ticket/api/impl/package.html | 7 +- .../org/uic/barcode/ticket/api/spec/package.html | 10 +- .../org/uic/barcode/ticket/api/utils/package.html | 7 +- src/main/java/org/uic/barcode/ticket/package.html | 12 +- src/main/java/org/uic/barcode/utils/package.html | 21 +- .../uic/barcode/test/SsbFrameBarcodeTestGroup.java | 220 ++++++++++++++++++++ .../barcode/test/SsbFrameBarcodeTestNonUic.java | 207 +++++++++++++++++++ .../uic/barcode/test/SsbFrameBarcodeTestNrt.java | 214 ++++++++++++++++++++ .../uic/barcode/test/SsbFrameBarcodeTestPass.java | 215 ++++++++++++++++++++ .../test/SsbFrameBarcodeTestReservation.java | 222 +++++++++++++++++++++ .../uic/barcode/test/utils/SsbTicketFactory.java | 193 ++++++++++++++++++ 26 files changed, 1520 insertions(+), 123 deletions(-) create mode 100644 src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestGroup.java create mode 100644 src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNonUic.java create mode 100644 src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNrt.java create mode 100644 src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestPass.java create mode 100644 src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestReservation.java create mode 100644 src/test/java/org/uic/barcode/test/utils/SsbTicketFactory.java diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index 1b3fb0c..85faa4a 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -213,6 +213,13 @@ public class Decoder { } else { throw e; } + } catch (AssertionError e) { + dynamicFrame = null; + if (isSsbFrame(data)) { + decodeSsbFrame(data); + } else { + throw new EncodingFormatException(e.getMessage()); + } } } else if (isStaticHeader(data)){ @@ -292,7 +299,7 @@ public class Decoder { * @return true, if is static header */ private boolean isSsbFrame(byte[] data) { - if (data.length == 144) { + if (data.length == 114) { return true; } return false; diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java index cf2d4d2..f2b9b0c 100644 --- a/src/main/java/org/uic/barcode/Encoder.java +++ b/src/main/java/org/uic/barcode/Encoder.java @@ -462,6 +462,8 @@ public class Encoder { return DynamicFrameCoder.encode(dynamicFrame); } else if (staticFrame != null) { return staticFrame.encode(); + } else if (ssbFrame != null) { + return ssbFrame.encode(); } return null; } 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 e409005..ce5ca60 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java +++ b/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java @@ -125,6 +125,7 @@ public class ByteBitBuffer implements BitBuffer { public ByteBitBuffer(byte[] backingArray) { this.bytes = backingArray; this.isFinite = true; + this.limit = backingArray.length * 8; } private ByteBitBuffer(int initialCapacity) { diff --git a/src/main/java/org/uic/barcode/package.html b/src/main/java/org/uic/barcode/package.html index 4a6ee0d..075af29 100644 --- a/src/main/java/org/uic/barcode/package.html +++ b/src/main/java/org/uic/barcode/package.html @@ -3,19 +3,21 @@ -

Provides the decoder and encoder for a UIC barcode

- - -

Included features:

-

-

- - +

Provides the decoder and encoder for a UIC barcode

+ + +

+ Included features:
+
+

+

+ + \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java b/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java index 9512fc1..0a158f3 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java @@ -46,14 +46,13 @@ public abstract class SsbCommonTicketPart extends SsbTicketPart { return offset; } - protected int encodeCommonPart(byte[] bytes) { + protected int encodeCommonPart(byte[] bytes, int offset) { BitBuffer bits = new ByteBitBuffer(bytes); - - int offset = 27; // header offset + bits.putInteger(offset,7, numberOfAdults); offset = offset + 7; - bits.putInteger(numberOfChildren,offset, 7); + bits.putInteger(offset, 7, numberOfChildren); offset = offset + 7; bits.put(offset,specimen); offset++; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java index 81b5eb4..1ee68bb 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java @@ -20,7 +20,7 @@ import org.uic.barcode.utils.SecurityUtils; public class SsbFrame { - private SsbHeader header = null; + private SsbHeader header = new SsbHeader(); private byte[] signaturePart1 = null; @@ -42,33 +42,38 @@ public class SsbFrame { throw new EncodingFormatException("Data size does not fit to SSB"); } - header = new SsbHeader(); - header.decode(bytes); + if (header == null) { + header = new SsbHeader(); + } + + int offset = 0; + + offset = offset + header.decodeContent(bytes,0); if (header.getTicketType().equals(SsbTicketType.UIC_1_IRT_RES_BOA)) { reservationData = new SsbReservation(); - reservationData.decode(bytes); + offset = offset + reservationData.decodeContent(bytes,offset); } else if (header.getTicketType().equals(SsbTicketType.UIC_2_NRT)) { nonReservationData = new SsbNonReservation(); - nonReservationData.decode(bytes); + offset = offset + nonReservationData.decodeContent(bytes,offset); } else if (header.getTicketType().equals(SsbTicketType.UIC_3_GRP)) { groupData = new SsbGroup(); - groupData.decode(bytes); + offset = offset + groupData.decodeContent(bytes, offset); } else if (header.getTicketType().equals(SsbTicketType.UIC_4_RPT)) { passData = new SsbPass(); - passData.decode(bytes); + offset = offset + passData.decodeContent(bytes,offset); } else { nonUicData = new SsbNonUic(); - nonUicData.decode(bytes); + offset = offset + nonUicData.decodeContent(bytes,offset); } @@ -76,8 +81,8 @@ public class SsbFrame { signaturePart2 = new byte[28]; for (int i = 0 ; i < 28;i++) { - signaturePart1[i] = bytes[59 + i]; - signaturePart2[i] = bytes[59 + 28 + i]; + signaturePart1[i] = bytes[58 + i]; + signaturePart2[i] = bytes[58 + 28 + i]; } } @@ -86,27 +91,48 @@ public class SsbFrame { byte[] bytes = new byte[114]; - header.encode(bytes); + int offset = header.encodeContent(bytes,0); + + if (nonUicData != null) { - nonUicData.encode(bytes); + offset = nonUicData.encodeContent(bytes, offset); } else if (nonReservationData != null) { - nonReservationData.encode(bytes); + offset = nonReservationData.encodeContent(bytes, offset); } else if (reservationData != null) { - reservationData.encode(bytes); + offset = reservationData.encodeContent(bytes, offset); } else if (groupData != null) { - groupData.encode(bytes); + offset = groupData.encodeContent(bytes, offset); } else if (passData != null) { - passData.encode(bytes); + offset = passData.encodeContent(bytes, offset); } else { throw new EncodingFormatException("Data Content for SSB missing"); }; - for (int i = 0 ; i < 28;i++) { - bytes[59 + i] = signaturePart1[i]; - bytes[59 + 28 + i] = signaturePart2[i]; + + if (signaturePart1.length > 28) { + throw new EncodingFormatException("Signature too large"); + } + if (signaturePart2.length > 28) { + throw new EncodingFormatException("Signature too large"); } + for (int i = 1 ; i < 29; i++) { + int sigInd = signaturePart1.length - i; + if (sigInd < signaturePart1.length && sigInd >= 0) { + bytes[58 + 28 - i] = signaturePart1[sigInd]; + } else { + bytes[58 + 28 - i] = '\0'; + } + sigInd = signaturePart2.length - i; + if (sigInd < signaturePart2.length && sigInd >= 0) { + bytes[58 + 28 + 28 - i] = signaturePart2[sigInd]; + } else { + bytes[58 + 28 + 28 - i] = '\0'; + } + } + + return bytes; } @@ -115,18 +141,19 @@ public class SsbFrame { byte[] bytes = new byte[58]; - header.encode(bytes); + int offset = header.encodeContent(bytes,0); + if (nonUicData != null) { - nonUicData.encode(bytes); + offset = nonUicData.encodeContent(bytes, offset); } else if (nonReservationData != null) { - nonReservationData.encode(bytes); + offset = nonReservationData.encodeContent(bytes, offset); } else if (reservationData != null) { - reservationData.encode(bytes); + offset = reservationData.encodeContent(bytes, offset); } else if (groupData != null) { - groupData.encode(bytes); + offset = groupData.encodeContent(bytes, offset); } else if (passData != null) { - passData.encode(bytes); + offset = passData.encodeContent(bytes, offset); } else { throw new EncodingFormatException("Data Content for SSB missing"); }; @@ -165,6 +192,10 @@ public class SsbFrame { public void setNonUicData(SsbNonUic nonUicData) { this.nonUicData = nonUicData; + this.nonReservationData = null; + this.reservationData = null; + this.groupData = null; + this.passData = null; } public SsbNonReservation getNonReservationData() { @@ -173,6 +204,11 @@ public class SsbFrame { public void setNonReservationData(SsbNonReservation nonReservationData) { this.nonReservationData = nonReservationData; + header.setTicketType(SsbTicketType.UIC_2_NRT); + this.reservationData = null; + this.nonUicData = null; + this.groupData = null; + this.passData = null; } public SsbReservation getReservationData() { @@ -180,6 +216,11 @@ public class SsbFrame { } public void setReservationData(SsbReservation reservationData) { + header.setTicketType(SsbTicketType.UIC_1_IRT_RES_BOA); + this.nonReservationData = null; + this.nonUicData = null; + this.groupData = null; + this.passData = null; this.reservationData = reservationData; } @@ -189,6 +230,12 @@ public class SsbFrame { public void setGroupData(SsbGroup groupData) { this.groupData = groupData; + header.setTicketType(SsbTicketType.UIC_3_GRP); + this.nonReservationData = null; + this.nonUicData = null; + this.reservationData = null; + this.passData = null; + } public SsbPass getPassData() { @@ -197,6 +244,11 @@ public class SsbFrame { public void setPassData(SsbPass passData) { this.passData = passData; + header.setTicketType(SsbTicketType.UIC_4_RPT); + this.nonReservationData = null; + this.nonUicData = null; + this.groupData = null; + this.reservationData = null; } public void signLevel1(PrivateKey key, Provider prov, String keyId, String algorithmOid) throws Exception { diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java b/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java index 52c3a52..1b2f6e7 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java @@ -18,9 +18,9 @@ public class SsbGroup extends SsbCommonTicketPart { @Override - protected void decodeContent(byte[] bytes) { + protected int decodeContent(byte[] bytes, int offset) { - int offset = decodeCommonPart(bytes); + offset = offset + decodeCommonPart(bytes); BitBuffer bits = new ByteBitBuffer(bytes); @@ -44,15 +44,17 @@ public class SsbGroup extends SsbCommonTicketPart { infoCode = bits.getInteger(offset, 14); offset = offset + 14; - text = bits.getChar6String(offset, 222); - offset = offset + 222; + text = bits.getChar6String(offset, 144); + offset = offset + 144; + + return offset; } @Override - protected void encodeContent(byte[] bytes) { + protected int encodeContent(byte[] bytes, int offset) { - int offset = encodeCommonPart(bytes); + offset = offset + encodeCommonPart(bytes, offset); BitBuffer bits = new ByteBitBuffer(bytes); @@ -65,7 +67,7 @@ public class SsbGroup extends SsbCommonTicketPart { bits.putInteger(offset, 9, lastDayOfValidity); offset = offset + 9; - offset = stations.decode(offset, bytes); + offset = stations.encode(offset, bytes); bits.putChar6String(offset, 72,groupName); offset = offset + 72; @@ -77,8 +79,9 @@ public class SsbGroup extends SsbCommonTicketPart { offset = offset + 14; bits.putChar6String(offset, 144, text); - offset = offset + 222; + offset = offset + 144; + return offset; } public int getFirstDayOfValidity() { diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java b/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java index 0d5424b..2ea4a51 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java @@ -27,7 +27,7 @@ public class SsbHeader extends SsbTicketPart { public SsbHeader() { } - public void decodeContent(byte[] headerData) { + public int decodeContent(byte[] headerData, int offset) { BitBuffer bits = new ByteBitBuffer(headerData); @@ -36,11 +36,11 @@ public class SsbHeader extends SsbTicketPart { keyId = bits.getInteger(18, 4); ticketType = SsbTicketType.values()[bits.getInteger(22, 5)]; - return; + return 4 + 14 + 4 + 5; } - public void encodeContent(byte[] bytes) { + public int encodeContent(byte[] bytes, int offset) { BitBuffer bits = new ByteBitBuffer(bytes); @@ -49,6 +49,8 @@ public class SsbHeader extends SsbTicketPart { bits.putInteger(18, 4, keyId); bits.putInteger(22, 5, ticketType.ordinal()); + return 4 + 14 + 4 + 5; + } diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java b/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java index e96e853..a1fb3ae 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java @@ -14,9 +14,9 @@ public class SsbNonReservation extends SsbCommonTicketPart { @Override - protected void decodeContent(byte[] bytes) { + protected int decodeContent(byte[] bytes, int offset) { - int offset = decodeCommonPart(bytes); + offset = offset + decodeCommonPart(bytes); BitBuffer bits = new ByteBitBuffer(bytes); @@ -37,12 +37,14 @@ public class SsbNonReservation extends SsbCommonTicketPart { text = bits.getChar6String(offset, 222); offset = offset + 222; + return offset; + } @Override - protected void encodeContent(byte[] bytes) { + protected int encodeContent(byte[] bytes, int offset) { - int offset = encodeCommonPart(bytes); + offset = offset + encodeCommonPart(bytes, offset); BitBuffer bits = new ByteBitBuffer(bytes); @@ -55,7 +57,7 @@ public class SsbNonReservation extends SsbCommonTicketPart { bits.putInteger(offset, 9, lastDayOfValidity); offset = offset + 9; - offset = stations.decode(offset, bytes); + offset = stations.encode(offset, bytes); bits.putInteger(offset, 14, infoCode); offset = offset + 14; @@ -63,6 +65,8 @@ public class SsbNonReservation extends SsbCommonTicketPart { bits.putChar6String(offset, 222, text); offset = offset + 222; + return offset; + } public int getFirstDayOfValidity() { diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java b/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java index 28e5105..1f0049e 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbNonUic.java @@ -6,31 +6,54 @@ import org.uic.barcode.asn1.uper.ByteBitBuffer; public class SsbNonUic extends SsbTicketPart { + + + byte[] openData = null; @Override - protected void decodeContent(byte[] bytes) { + protected int decodeContent(byte[] bytes, int offset) { + + BitBuffer bits = new ByteBitBuffer(bytes); + + StringBuffer sb = new StringBuffer(); + + + for (int i = offset; i < openDataLength; i++) { + if (bits.get(i) == false) { + sb.append("1"); + } else { + sb.append("0"); + } + } + + for (int i = openDataLength; i < 440; i++) { + sb.append("0"); + } - String bitString = AsnUtils.toBooleanString(bytes); - - openData = AsnUtils.fromBooleanString(bitString); + openData = AsnUtils.fromBooleanString(sb.toString()); + + return offset + openDataLength ; } @Override - protected void encodeContent(byte[] bytes) { + protected int encodeContent(byte[] bytes, int offset) { BitBuffer bits = new ByteBitBuffer(bytes); String bitString = AsnUtils.toBooleanString(openData); - for (int i = 0;i< 58 *8 ;i++) { - if (bitString.charAt(i) == '0') { - bits.put(27 + i, true); + + for (int i = 0; i< openDataLength ; i++) { + if (i < bitString.length() && bitString.charAt(i) == '0') { + bits.put(offset + i, true); } else { - bits.put(27 + i, false); + bits.put(offset + i, false); } } + + return offset + openDataLength; } public byte[] getOpenData() { diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java b/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java index a38dfaf..3598efd 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java @@ -35,9 +35,9 @@ public class SsbPass extends SsbCommonTicketPart { private String text = null; @Override - protected void decodeContent(byte[] bytes) { + protected int decodeContent(byte[] bytes, int offset) { - int offset = decodeCommonPart(bytes); + offset = offset + decodeCommonPart(bytes); BitBuffer bits = new ByteBitBuffer(bytes); @@ -77,12 +77,13 @@ public class SsbPass extends SsbCommonTicketPart { text = bits.getChar6String(offset, 240); offset = offset + 240; + return offset; } @Override - protected void encodeContent(byte[] bytes) { + protected int encodeContent(byte[] bytes, int offset) { - int offset = encodeCommonPart(bytes); + offset = offset + encodeCommonPart(bytes, offset); BitBuffer bits = new ByteBitBuffer(bytes); @@ -121,6 +122,8 @@ public class SsbPass extends SsbCommonTicketPart { bits.putChar6String(offset, 240,text); offset = offset + 240; + + return offset; } public int getPassSubType() { diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java b/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java index c7f520d..73017d7 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java @@ -30,17 +30,17 @@ public class SsbReservation extends SsbCommonTicketPart { @Override - protected void decodeContent(byte[] bytes) { + protected int decodeContent(byte[] bytes, int offset) { - int offset = decodeCommonPart(bytes); + offset = offset + decodeCommonPart(bytes); BitBuffer bits = new ByteBitBuffer(bytes); ticketSubType = bits.getInteger(offset, 2); - offset = offset + 4; + offset = offset + 2; stations = new SsbStations(); - stations.decode(offset, bytes); + offset = stations.decode(offset, bytes); /* * Departure date : First day of validity from the issuing date Num (<367) 9,000 @@ -60,7 +60,7 @@ public class SsbReservation extends SsbCommonTicketPart { offset = offset + 11; train = bits.getChar6String(offset, 30); - offset = offset +30; + offset = offset + 30; coach = bits.getInteger(offset, 10); offset = offset + 10; @@ -76,17 +76,19 @@ public class SsbReservation extends SsbCommonTicketPart { text = bits.getChar6String(offset, 162); offset = offset + 162; + + return offset; } @Override - protected void encodeContent(byte[] bytes) { + protected int encodeContent(byte[] bytes, int offset) { - int offset = encodeCommonPart(bytes); + offset = offset + encodeCommonPart(bytes, offset); BitBuffer bits = new ByteBitBuffer(bytes); bits.putInteger(offset, 2,ticketSubType); - offset = offset + 4; + offset = offset + 2; offset = stations.encode(offset, bytes); @@ -108,7 +110,7 @@ public class SsbReservation extends SsbCommonTicketPart { offset = offset + 11; bits.putChar6String(offset, 30,train); - offset = offset +30; + offset = offset + 30; bits.putInteger(offset, 10,coach); offset = offset + 10; @@ -117,7 +119,7 @@ public class SsbReservation extends SsbCommonTicketPart { offset = offset + 18; bits.put(offset, overbooking); - offset++; + offset++; bits.putInteger(offset, 14, infoCode); offset = offset + 14; @@ -125,6 +127,8 @@ public class SsbReservation extends SsbCommonTicketPart { bits.putChar6String(offset, 162, text); offset = offset + 162; + return offset; + } public SsbStations getStations() { diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java index 3855c5c..5583e66 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java @@ -4,23 +4,25 @@ import org.uic.barcode.ticket.EncodingFormatException; public abstract class SsbTicketPart { + public static int openDataLength = 437; + public void decode(byte[] bytes) throws EncodingFormatException { if (bytes.length != 114) { throw new EncodingFormatException("Data size does not fit to SSB"); } - decodeContent(bytes); + decodeContent(bytes, 0); }; - protected abstract void decodeContent(byte[] bytes); + protected abstract int decodeContent(byte[] bytes , int offset); public void encode(byte[] bytes) throws EncodingFormatException { if (bytes.length != 114) { throw new EncodingFormatException("Data size does not fit to SSB"); } - encodeContent(bytes); + encodeContent(bytes, 0); } - protected abstract void encodeContent(byte[] bytes); + protected abstract int encodeContent(byte[] bytes, int offset); diff --git a/src/main/java/org/uic/barcode/staticFrame/package.html b/src/main/java/org/uic/barcode/staticFrame/package.html index b76540b..5ad7515 100644 --- a/src/main/java/org/uic/barcode/staticFrame/package.html +++ b/src/main/java/org/uic/barcode/staticFrame/package.html @@ -3,19 +3,24 @@ -

static bar code header frame

+

static bar code header frame

-

Provides an implementation of the static bar code header frame specified in UIC IRS 90918-9 including:

- -

-

+

+ Provides an implementation of the static bar code header frame + specified in UIC IRS 90918-9 including:
+
+

+

\ No newline at end of file diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/package.html b/src/main/java/org/uic/barcode/ticket/api/asn/package.html index 307075e..214572b 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/package.html +++ b/src/main/java/org/uic/barcode/ticket/api/asn/package.html @@ -1,7 +1,9 @@ -asn - - Provides code generated from the asn.1 specification using the openAsn compiler to implement the asn.1 encoduing and decoding using unaligned PER encoding. +asn + +Provides code generated from the asn.1 specification using + the openAsn compiler to implement the asn.1 encoduing and decoding + using unaligned PER encoding. \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/ticket/api/impl/package.html b/src/main/java/org/uic/barcode/ticket/api/impl/package.html index 587b741..f2ef54e 100644 --- a/src/main/java/org/uic/barcode/ticket/api/impl/package.html +++ b/src/main/java/org/uic/barcode/ticket/api/impl/package.html @@ -1,7 +1,10 @@ -Ticket Data Implementation +Ticket Data Implementation + - Provides a simple implementation of the ticket data interface specified in package spec. + Provides a simple implementation of the ticket data interface specified + in package + spec. \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/ticket/api/spec/package.html b/src/main/java/org/uic/barcode/ticket/api/spec/package.html index 18d8b53..f3961b8 100644 --- a/src/main/java/org/uic/barcode/ticket/api/spec/package.html +++ b/src/main/java/org/uic/barcode/ticket/api/spec/package.html @@ -1,7 +1,13 @@ -UIC ticket interface +UIC ticket interface + - Provides the interface specification of the ticket data. Any ticket data implementation which wants to use the provided encoder / decoder function must implement this interface. A simple implementation is provided in package impl

. + Provides the interface specification of the ticket data. Any ticket + data implementation which wants to use the provided encoder / decoder + function must implement this interface. A simple implementation is + provided in package + impl +

. \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/package.html b/src/main/java/org/uic/barcode/ticket/api/utils/package.html index a926c2d..baf156e 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/package.html +++ b/src/main/java/org/uic/barcode/ticket/api/utils/package.html @@ -1,7 +1,8 @@ -Utilities - - Provides utilities for the asn.1 encoding and decoding of ticket data. +Utilities + +Provides utilities for the asn.1 encoding and decoding of + ticket data. \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/ticket/package.html b/src/main/java/org/uic/barcode/ticket/package.html index 993e0c4..6f10316 100644 --- a/src/main/java/org/uic/barcode/ticket/package.html +++ b/src/main/java/org/uic/barcode/ticket/package.html @@ -1,9 +1,13 @@ -UIC ticket data API +UIC ticket data API + - This API provides a specification of ticket data as an interface and an implementation of an encoder/decoder to encode and decode ticket data to an asn.1 PER encoded byte stream according to the UIC specification. -
- Any ticket data implementing the interface defined in package spec can be encoded/decoded. The package impl provides a simple implementation of the ticket. + This API provides a specification of ticket data as an interface and an + implementation of an encoder/decoder to encode and decode ticket data + to an asn.1 PER encoded byte stream according to the UIC specification. +
Any ticket data implementing the interface defined in package + spec can be encoded/decoded. The package + impl provides a simple implementation of the ticket. \ No newline at end of file diff --git a/src/main/java/org/uic/barcode/utils/package.html b/src/main/java/org/uic/barcode/utils/package.html index 45a73a9..73917d7 100644 --- a/src/main/java/org/uic/barcode/utils/package.html +++ b/src/main/java/org/uic/barcode/utils/package.html @@ -3,18 +3,19 @@ -

Implementation of the header frames to bundle all data for a bar code.

+

Implementation of the header frames to bundle all data for a + bar code.

-

+

- Provides a decoding and encoding of the header data frames for:

- -

-

- \ No newline at end of file diff --git a/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestGroup.java b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestGroup.java new file mode 100644 index 0000000..f6ec58b --- /dev/null +++ b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestGroup.java @@ -0,0 +1,220 @@ +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.provider.BouncyCastleProvider; +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.logger.LoggerFactory; +import org.uic.barcode.ssbFrame.SsbFrame; +import org.uic.barcode.test.utils.SsbTicketFactory; +import org.uic.barcode.ticket.EncodingFormatException; + +/** + * The Class StaticFrameBarcodeTest. + */ +public class SsbFrameBarcodeTestGroup { + + /** The algorithm OID. */ + public String algorithmOID = Constants.DSA_SHA224; + + public int keySize = 2048; + + /** The key pair. */ + public KeyPair keyPair = null; + + + public SsbFrame ssbFrame = null; + + + /** + * Initialize. + * + * set the signature algorithm + * generate a key pair + * set the test content + * for ticket and layout + */ + @Before public void initialize() { + + LoggerFactory.setActivateConsoleLog(true); + + algorithmOID = Constants.DSA_SHA224; + keySize = 1024; + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPair = generateDSAKeys(keySize); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + + assert(keyPair != null); + + } + + + + + + /** + * Test ssb pass encoding. + */ + @Test public void testSsbEncoding() { + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 0, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame(SsbTicketFactory.getSsbGroup()); + + assert(enc != null); + + try { + enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + + assert(encoded != null); + + assert(encoded.length == 114); + + } + + /** + * Test ssb barcode decoding. + */ + @Test public void testSsbDecoding() { + + + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 1, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame( SsbTicketFactory.getSsbGroup()); + + assert(enc != null); + + try { + enc.signLevel1("4711", keyPair.getPrivate(), algorithmOID, "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(),algorithmOID); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + assert(dec.getSsbFrame() != null); + + assert(dec.getSsbFrame().getHeader() != null); + + SsbFrame ref = SsbTicketFactory.getSsbGroup(); + + assert(dec.getSsbFrame().getHeader().getKeyId() == 1); + assert(dec.getSsbFrame().getHeader().getIssuer() == 4711); + assert(dec.getSsbFrame().getHeader().getTicketType().equals(ref.getHeader().getTicketType())); + assert(dec.getSsbFrame().getHeader().getVersion() == 1); + + assert(dec.getSsbFrame().getGroupData() != null); + + assert(dec.getSsbFrame().getGroupData().getClassCode().equals(ref.getGroupData().getClassCode())); + assert(dec.getSsbFrame().getGroupData().isSpecimen() == ref.getGroupData().isSpecimen()); + assert(dec.getSsbFrame().getGroupData().getFirstDayOfValidity() == ref.getGroupData().getFirstDayOfValidity()); + assert(dec.getSsbFrame().getGroupData().getLastDayOfValidity() == ref.getGroupData().getLastDayOfValidity()); + + + assert(dec.getSsbFrame().getGroupData().getStations() != null); + + SsbTicketFactory.compareStations(dec.getSsbFrame().getGroupData().getStations(), ref.getGroupData().getStations()); + + SsbTicketFactory.compareCommonTicketPart(dec.getSsbFrame().getGroupData(), ref.getGroupData()); + + + assert(dec.getSsbFrame().getGroupData().getFirstDayOfValidity() == ref.getGroupData().getFirstDayOfValidity()); + assert(dec.getSsbFrame().getGroupData().getLastDayOfValidity() == ref.getGroupData().getLastDayOfValidity()); + + assert(dec.getSsbFrame().getGroupData().getInfoCode() == ref.getGroupData().getInfoCode()); + assert(dec.getSsbFrame().getGroupData().getText().equalsIgnoreCase(ref.getGroupData().getText())); + + assert(dec.getSsbFrame().getGroupData().getCounterMarkNumber() == ref.getGroupData().getCounterMarkNumber()); + assert(dec.getSsbFrame().getGroupData().getGroupName().equalsIgnoreCase(ref.getGroupData().getGroupName())); + + } + + /** + * Generate DSA keys. + * + * @return the key pair + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws NoSuchProviderException the no such provider exception + * @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception + */ + public KeyPair generateDSAKeys(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC"); + g.initialize(keySize, new SecureRandom()); + return g.generateKeyPair(); + } + +} diff --git a/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNonUic.java b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNonUic.java new file mode 100644 index 0000000..2a28d80 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNonUic.java @@ -0,0 +1,207 @@ +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.provider.BouncyCastleProvider; +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.logger.LoggerFactory; +import org.uic.barcode.ssbFrame.SsbFrame; +import org.uic.barcode.test.utils.SsbTicketFactory; +import org.uic.barcode.ticket.EncodingFormatException; + +/** + * The Class StaticFrameBarcodeTest. + */ +public class SsbFrameBarcodeTestNonUic { + + /** The algorithm OID. */ + public String algorithmOID = Constants.DSA_SHA224; + + public int keySize = 2048; + + /** The key pair. */ + public KeyPair keyPair = null; + + + public SsbFrame ssbFrame = null; + + + /** + * Initialize. + * + * set the signature algorithm + * generate a key pair + * set the test content + * for ticket and layout + */ + @Before public void initialize() { + + LoggerFactory.setActivateConsoleLog(true); + + algorithmOID = Constants.DSA_SHA224; + keySize = 1024; + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPair = generateDSAKeys(keySize); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + + assert(keyPair != null); + + } + + + + + + /** + * Test ssb pass encoding. + */ + @Test public void testSsbEncoding() { + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 0, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame(SsbTicketFactory.getSsbNonUic()); + + assert(enc != null); + + try { + enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + + assert(encoded != null); + + assert(encoded.length == 114); + + } + + /** + * Test dynamic header barcode decoding. + */ + @Test public void testSsbDecoding() { + + + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 1, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame( SsbTicketFactory.getSsbNonUic()); + + assert(enc != null); + + try { + enc.signLevel1("4711", keyPair.getPrivate(), algorithmOID, "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(),algorithmOID); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + assert(dec.getSsbFrame() != null); + + assert(dec.getSsbFrame().getHeader() != null); + + SsbFrame ref = SsbTicketFactory.getSsbNonUic(); + + assert(dec.getSsbFrame().getHeader().getKeyId() == 1); + assert(dec.getSsbFrame().getHeader().getIssuer() == 4711); + assert(dec.getSsbFrame().getHeader().getTicketType().equals(ref.getHeader().getTicketType())); + assert(dec.getSsbFrame().getHeader().getVersion() == 1); + + assert(dec.getSsbFrame().getNonUicData() != null); + + assert(dec.getSsbFrame().getNonUicData().getOpenData() != null); + + + + for (int i = 0; i < ref.getNonUicData().getOpenData().length; i++) { + assert (dec.getSsbFrame().getNonUicData().getOpenData()[i] == (ref.getNonUicData().getOpenData())[i] ); + } + + + } + + /** + * Generate DSA keys. + * + * @return the key pair + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws NoSuchProviderException the no such provider exception + * @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception + */ + public KeyPair generateDSAKeys(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC"); + g.initialize(keySize, new SecureRandom()); + return g.generateKeyPair(); + } + +} diff --git a/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNrt.java b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNrt.java new file mode 100644 index 0000000..2000ee1 --- /dev/null +++ b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestNrt.java @@ -0,0 +1,214 @@ +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.provider.BouncyCastleProvider; +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.logger.LoggerFactory; +import org.uic.barcode.ssbFrame.SsbFrame; +import org.uic.barcode.test.utils.SsbTicketFactory; +import org.uic.barcode.ticket.EncodingFormatException; + +/** + * The Class StaticFrameBarcodeTest. + */ +public class SsbFrameBarcodeTestNrt { + + /** The algorithm OID. */ + public String algorithmOID = Constants.DSA_SHA224; + + public int keySize = 1024; + + /** The key pair. */ + public KeyPair keyPair = null; + + + public SsbFrame ssbFrame = null; + + + /** + * Initialize. + * + * set the signature algorithm + * generate a key pair + * set the test content + * for ticket and layout + */ + @Before public void initialize() { + + LoggerFactory.setActivateConsoleLog(true); + + algorithmOID = Constants.DSA_SHA224; + keySize = 1024; + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPair = generateDSAKeys(keySize); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + + assert(keyPair != null); + + } + + + + + + /** + * Test ssb pass encoding. + */ + @Test public void testSsbEncoding() { + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 0, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame(SsbTicketFactory.getSsbNonReservation()); + + assert(enc != null); + + try { + enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + + assert(encoded != null); + + assert(encoded.length == 114); + + } + + /** + * Test dynamic header barcode decoding. + */ + @Test public void testSsbDecoding() { + + + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 1, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame( SsbTicketFactory.getSsbNonReservation()); + + assert(enc != null); + + try { + enc.signLevel1("4711", keyPair.getPrivate(), algorithmOID, "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(),algorithmOID); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + assert(dec.getSsbFrame() != null); + + assert(dec.getSsbFrame().getHeader() != null); + + SsbFrame ref = SsbTicketFactory.getSsbNonReservation(); + + assert(dec.getSsbFrame().getHeader().getKeyId() == 1); + assert(dec.getSsbFrame().getHeader().getIssuer() == 4711); + assert(dec.getSsbFrame().getHeader().getTicketType().equals(ref.getHeader().getTicketType())); + assert(dec.getSsbFrame().getHeader().getVersion() == 1); + + assert(dec.getSsbFrame().getNonReservationData() != null); + + assert(dec.getSsbFrame().getNonReservationData().getClassCode().equals(ref.getNonReservationData().getClassCode())); + assert(dec.getSsbFrame().getNonReservationData().isSpecimen() == ref.getNonReservationData().isSpecimen()); + assert(dec.getSsbFrame().getNonReservationData().getFirstDayOfValidity() == ref.getNonReservationData().getFirstDayOfValidity()); + assert(dec.getSsbFrame().getNonReservationData().getLastDayOfValidity() == ref.getNonReservationData().getLastDayOfValidity()); + + + assert(dec.getSsbFrame().getNonReservationData().getStations() != null); + + SsbTicketFactory.compareStations(dec.getSsbFrame().getNonReservationData().getStations(), ref.getNonReservationData().getStations()); + + SsbTicketFactory.compareCommonTicketPart(dec.getSsbFrame().getNonReservationData(), ref.getNonReservationData()); + + + assert(dec.getSsbFrame().getNonReservationData().getInfoCode() == ref.getNonReservationData().getInfoCode()); + assert(dec.getSsbFrame().getNonReservationData().getText().equalsIgnoreCase(ref.getNonReservationData().getText())); + + } + + /** + * Generate DSA keys. + * + * @return the key pair + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws NoSuchProviderException the no such provider exception + * @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception + */ + public KeyPair generateDSAKeys(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC"); + g.initialize(keySize, new SecureRandom()); + return g.generateKeyPair(); + } + +} diff --git a/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestPass.java b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestPass.java new file mode 100644 index 0000000..dd2101a --- /dev/null +++ b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestPass.java @@ -0,0 +1,215 @@ +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.provider.BouncyCastleProvider; +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.logger.LoggerFactory; +import org.uic.barcode.ssbFrame.SsbFrame; +import org.uic.barcode.test.utils.SsbTicketFactory; +import org.uic.barcode.ticket.EncodingFormatException; + +/** + * The Class StaticFrameBarcodeTest. + */ +public class SsbFrameBarcodeTestPass { + + /** The algorithm OID. */ + public String algorithmOID = Constants.DSA_SHA224; + + public int keySize = 1024; + + /** The key pair. */ + public KeyPair keyPair = null; + + + public SsbFrame ssbFrame = null; + + + /** + * Initialize. + * + * set the signature algorithm + * generate a key pair + * set the test content + * for ticket and layout + */ + @Before public void initialize() { + + LoggerFactory.setActivateConsoleLog(true); + + algorithmOID = Constants.DSA_SHA224; + keySize = 1024; + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPair = generateDSAKeys(keySize); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + + assert(keyPair != null); + + } + + + + + + /** + * Test ssb pass encoding. + */ + @Test public void testSsbPassEncoding() { + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 0, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame(SsbTicketFactory.getSsbPass()); + + assert(enc != null); + + try { + enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + + assert(encoded != null); + + assert(encoded.length == 114); + + } + + /** + * Test dynamic header barcode decoding. + */ + @Test public void testSsbPassDecoding() { + + + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 1, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame( SsbTicketFactory.getSsbPass()); + + assert(enc != null); + + try { + enc.signLevel1("4711", keyPair.getPrivate(), algorithmOID, "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(),algorithmOID); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + assert(dec.getSsbFrame() != null); + + assert(dec.getSsbFrame().getHeader() != null); + + SsbFrame ref = SsbTicketFactory.getSsbPass(); + + assert(dec.getSsbFrame().getHeader().getKeyId() == 1); + assert(dec.getSsbFrame().getHeader().getIssuer() == 4711); + assert(dec.getSsbFrame().getHeader().getTicketType().equals(ref.getHeader().getTicketType())); + assert(dec.getSsbFrame().getHeader().getVersion() == 1); + + assert(dec.getSsbFrame().getPassData() != null); + assert(dec.getSsbFrame().getPassData().getClassCode().equals(ref.getPassData().getClassCode())); + assert(dec.getSsbFrame().getPassData().isSpecimen() == ref.getPassData().isSpecimen()); + assert(dec.getSsbFrame().getPassData().isHasSecondPage() == ref.getPassData().isHasSecondPage()); + assert(dec.getSsbFrame().getPassData().getCountry_1() == ref.getPassData().getCountry_1()); + assert(dec.getSsbFrame().getPassData().getCountry_2() == ref.getPassData().getCountry_2()); + assert(dec.getSsbFrame().getPassData().getCountry_3() == ref.getPassData().getCountry_3()); + assert(dec.getSsbFrame().getPassData().getCountry_4() == ref.getPassData().getCountry_4()); + assert(dec.getSsbFrame().getPassData().getCountry_5() == ref.getPassData().getCountry_5()); + assert(dec.getSsbFrame().getPassData().getDay() == ref.getPassData().getDay()); + assert(dec.getSsbFrame().getPassData().getFirstDayOfValidity() == ref.getPassData().getFirstDayOfValidity()); + assert(dec.getSsbFrame().getPassData().getInfoCode() == ref.getPassData().getInfoCode()); + assert(dec.getSsbFrame().getPassData().getMaximumValidityDuration() == ref.getPassData().getMaximumValidityDuration()); + assert(dec.getSsbFrame().getPassData().getNumberOfAdults() == ref.getPassData().getNumberOfAdults()); + assert(dec.getSsbFrame().getPassData().getNumberOfChildren() == ref.getPassData().getNumberOfChildren()); + assert(dec.getSsbFrame().getPassData().getNumberOfTravels() == ref.getPassData().getNumberOfTravels()); + assert(dec.getSsbFrame().getPassData().getText().equalsIgnoreCase(ref.getPassData().getText())); + assert(dec.getSsbFrame().getPassData().getTicketNumber().equals(ref.getPassData().getTicketNumber())); + assert(dec.getSsbFrame().getPassData().getYear() == ref.getPassData().getYear()); + } + + /** + * Generate DSA keys. + * + * @return the key pair + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws NoSuchProviderException the no such provider exception + * @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception + */ + public KeyPair generateDSAKeys(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC"); + g.initialize(keySize, new SecureRandom()); + return g.generateKeyPair(); + } + +} diff --git a/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestReservation.java b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestReservation.java new file mode 100644 index 0000000..5f9e11e --- /dev/null +++ b/src/test/java/org/uic/barcode/test/SsbFrameBarcodeTestReservation.java @@ -0,0 +1,222 @@ +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.provider.BouncyCastleProvider; +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.logger.LoggerFactory; +import org.uic.barcode.ssbFrame.SsbFrame; +import org.uic.barcode.test.utils.SsbTicketFactory; +import org.uic.barcode.ticket.EncodingFormatException; + +/** + * The Class StaticFrameBarcodeTest. + */ +public class SsbFrameBarcodeTestReservation { + + /** The algorithm OID. */ + public String algorithmOID = Constants.DSA_SHA224; + + public int keySize = 1024; + + /** The key pair. */ + public KeyPair keyPair = null; + + + public SsbFrame ssbFrame = null; + + + /** + * Initialize. + * + * set the signature algorithm + * generate a key pair + * set the test content + * for ticket and layout + */ + @Before public void initialize() { + + LoggerFactory.setActivateConsoleLog(true); + + algorithmOID = Constants.DSA_SHA224; + keySize = 1024; + + Security.addProvider(new BouncyCastleProvider()); + + try { + keyPair = generateDSAKeys(keySize); + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + + assert(keyPair != null); + + } + + + + + + /** + * Test ssb pass encoding. + */ + @Test public void testSsbEncoding() { + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 0, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame(SsbTicketFactory.getSsbReservation()); + + assert(enc != null); + + try { + enc.signLevel1("1080", keyPair.getPrivate(), algorithmOID, "1"); + } catch (Exception e) { + assert(false); + } + + byte[] encoded = null; + try { + encoded = enc.encode(); + } catch (Exception e) { + assert(false); + } + + assert(encoded != null); + + assert(encoded.length == 114); + + } + + /** + * Test dynamic header barcode decoding. + */ + @Test public void testSsbDecoding() { + + + + + Encoder enc = null; + + try { + enc = new Encoder(null, null, Encoder.UIC_BARCODE_TYPE_SSB, 1, 0); + } catch (IOException | EncodingFormatException e1) { + assert(false); + } + + enc.setSsbFrame( SsbTicketFactory.getSsbReservation()); + + assert(enc != null); + + try { + enc.signLevel1("4711", keyPair.getPrivate(), algorithmOID, "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(),algorithmOID); + } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException | IllegalArgumentException + | UnsupportedOperationException | IOException | EncodingFormatException e) { + assert(false); + } + + assert(signatureCheck == Constants.LEVEL1_VALIDATION_OK); + + assert(dec.getSsbFrame() != null); + + assert(dec.getSsbFrame().getHeader() != null); + + SsbFrame ref = SsbTicketFactory.getSsbReservation(); + + assert(dec.getSsbFrame().getHeader().getKeyId() == 1); + assert(dec.getSsbFrame().getHeader().getIssuer() == 4711); + assert(dec.getSsbFrame().getHeader().getTicketType().equals(ref.getHeader().getTicketType())); + assert(dec.getSsbFrame().getHeader().getVersion() == 1); + + assert(dec.getSsbFrame().getReservationData() != null); + + assert(dec.getSsbFrame().getReservationData().getClassCode().equals(ref.getReservationData().getClassCode())); + assert(dec.getSsbFrame().getReservationData().isSpecimen() == ref.getReservationData().isSpecimen()); + assert(dec.getSsbFrame().getReservationData().getCoach() == ref.getReservationData().getCoach()); + assert(dec.getSsbFrame().getReservationData().getDepartureDate() == ref.getReservationData().getDepartureDate()); + assert(dec.getSsbFrame().getReservationData().getDepartureTime() == ref.getReservationData().getDepartureTime()); + + + assert(dec.getSsbFrame().getReservationData().getStations() != null); + + SsbTicketFactory.compareStations(dec.getSsbFrame().getReservationData().getStations(), ref.getReservationData().getStations()); + + SsbTicketFactory.compareCommonTicketPart(dec.getSsbFrame().getReservationData(), ref.getReservationData()); + + + assert(dec.getSsbFrame().getReservationData().getPlace().equals(ref.getReservationData().getPlace())); + assert(dec.getSsbFrame().getReservationData().getTicketSubType() == ref.getReservationData().getTicketSubType()); + assert(dec.getSsbFrame().getReservationData().getTrain().equals(ref.getReservationData().getTrain())); + assert(dec.getSsbFrame().getReservationData().isOverbooking() == ref.getReservationData().isOverbooking()); + + assert(dec.getSsbFrame().getReservationData().getInfoCode() == ref.getReservationData().getInfoCode()); + assert(dec.getSsbFrame().getReservationData().getText().equalsIgnoreCase(ref.getReservationData().getText())); + + + + } + + /** + * Generate DSA keys. + * + * @return the key pair + * @throws NoSuchAlgorithmException the no such algorithm exception + * @throws NoSuchProviderException the no such provider exception + * @throws InvalidAlgorithmParameterException the invalid algorithm parameter exception + */ + public KeyPair generateDSAKeys(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException{ + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "BC"); + g.initialize(keySize, new SecureRandom()); + return g.generateKeyPair(); + } + +} diff --git a/src/test/java/org/uic/barcode/test/utils/SsbTicketFactory.java b/src/test/java/org/uic/barcode/test/utils/SsbTicketFactory.java new file mode 100644 index 0000000..539fced --- /dev/null +++ b/src/test/java/org/uic/barcode/test/utils/SsbTicketFactory.java @@ -0,0 +1,193 @@ +package org.uic.barcode.test.utils; + +import org.uic.barcode.ssbFrame.SsbClass; +import org.uic.barcode.ssbFrame.SsbCommonTicketPart; +import org.uic.barcode.ssbFrame.SsbFrame; +import org.uic.barcode.ssbFrame.SsbGroup; +import org.uic.barcode.ssbFrame.SsbHeader; +import org.uic.barcode.ssbFrame.SsbNonReservation; +import org.uic.barcode.ssbFrame.SsbNonUic; +import org.uic.barcode.ssbFrame.SsbPass; +import org.uic.barcode.ssbFrame.SsbReservation; +import org.uic.barcode.ssbFrame.SsbStationCodeTable; +import org.uic.barcode.ssbFrame.SsbStations; +import org.uic.barcode.ssbFrame.SsbTicketType; + +public class SsbTicketFactory { + + public static SsbFrame getSsbPass() { + + SsbFrame ssbPass = new SsbFrame(); + + ssbPass.setHeader(new SsbHeader()); + ssbPass.getHeader().setIssuer(4711); + ssbPass.getHeader().setTicketType(SsbTicketType.UIC_4_RPT); + ssbPass.getHeader().setVersion(1); + + + ssbPass.setPassData(new SsbPass()); + ssbPass.getPassData().setClassCode(SsbClass.FIRST); + ssbPass.getPassData().setCountry_1(10); + ssbPass.getPassData().setCountry_2(12); + ssbPass.getPassData().setDay(1); + ssbPass.getPassData().setFirstDayOfValidity(120); + ssbPass.getPassData().setHasSecondPage(false); + ssbPass.getPassData().setInfoCode(12); + ssbPass.getPassData().setMaximumValidityDuration(2); + ssbPass.getPassData().setNumberOfAdults(2); + ssbPass.getPassData().setNumberOfChildren(3); + ssbPass.getPassData().setNumberOfTravels(3); + ssbPass.getPassData().setPassSubType(1); + ssbPass.getPassData().setSpecimen(true); + ssbPass.getPassData().setText("Test"); + ssbPass.getPassData().setTicketNumber("SKCTS86"); + ssbPass.getPassData().setYear(3); + + return ssbPass; + } + + public static SsbFrame getSsbGroup() { + + SsbFrame ssb = new SsbFrame(); + + ssb.setHeader(new SsbHeader()); + ssb.getHeader().setIssuer(4711); + ssb.getHeader().setTicketType(SsbTicketType.UIC_3_GRP); + ssb.getHeader().setVersion(1); + + + ssb.setGroupData(new SsbGroup()); + ssb.getGroupData().setClassCode(SsbClass.FIRST); + ssb.getGroupData().setCounterMarkNumber(1); + ssb.getGroupData().setDay(1); + ssb.getGroupData().setFirstDayOfValidity(10); + ssb.getGroupData().setFirstDayOfValidity(120); + ssb.getGroupData().setGroupName("GroupName"); + ssb.getGroupData().setInfoCode(12); + ssb.getGroupData().setLastDayOfValidity(3); + ssb.getGroupData().setNumberOfAdults(2); + ssb.getGroupData().setNumberOfChildren(3); + ssb.getGroupData().setReturnJourney(false); + ssb.getGroupData().setSpecimen(true); + ssb.getGroupData().setText("Test"); + ssb.getGroupData().setTicketNumber("SKCTS86"); + ssb.getGroupData().setYear(3); + + ssb.getGroupData().getStations().setArrivalStationCode("8012345"); + ssb.getGroupData().getStations().setDepartureStationCode("8054321"); + ssb.getGroupData().getStations().setCodeTable(SsbStationCodeTable.NRT); + + return ssb; + } + + public static SsbFrame getSsbNonReservation() { + + SsbFrame ssb = new SsbFrame(); + + ssb.setHeader(new SsbHeader()); + ssb.getHeader().setIssuer(4711); + ssb.getHeader().setTicketType(SsbTicketType.UIC_2_NRT); + ssb.getHeader().setVersion(1); + + + ssb.setNonReservationData(new SsbNonReservation()); + ssb.getNonReservationData().setClassCode(SsbClass.FIRST); + ssb.getNonReservationData().setDay(1); + ssb.getNonReservationData().setFirstDayOfValidity(10); + ssb.getNonReservationData().setFirstDayOfValidity(120); + ssb.getNonReservationData().setInfoCode(12); + ssb.getNonReservationData().setLastDayOfValidity(3); + ssb.getNonReservationData().setNumberOfAdults(2); + ssb.getNonReservationData().setNumberOfChildren(3); + ssb.getNonReservationData().setReturnJourney(false); + ssb.getNonReservationData().setSpecimen(true); + ssb.getNonReservationData().setText("Test"); + ssb.getNonReservationData().setTicketNumber("SKCTS86"); + ssb.getNonReservationData().setYear(3); + + + ssb.getNonReservationData().getStations().setArrivalStationCode("8012345"); + ssb.getNonReservationData().getStations().setDepartureStationCode("8054321"); + ssb.getNonReservationData().getStations().setCodeTable(SsbStationCodeTable.NRT); + + return ssb; + } + + public static SsbFrame getSsbReservation() { + + SsbFrame ssb = new SsbFrame(); + + ssb.setHeader(new SsbHeader()); + ssb.getHeader().setIssuer(4711); + ssb.getHeader().setTicketType(SsbTicketType.UIC_1_IRT_RES_BOA); + ssb.getHeader().setVersion(1); + + + ssb.setReservationData(new SsbReservation()); + ssb.getReservationData().setClassCode(SsbClass.FIRST); + ssb.getReservationData().setDay(1); + ssb.getReservationData().setCoach(123); + ssb.getReservationData().setDepartureDate(120); + ssb.getReservationData().setDepartureTime(500); + ssb.getReservationData().setOverbooking(false); + ssb.getReservationData().setNumberOfAdults(2); + ssb.getReservationData().setNumberOfChildren(3); + ssb.getReservationData().setPlace("05B"); + ssb.getReservationData().setTicketSubType(2); + ssb.getReservationData().setTrain("1234B"); + + ssb.getReservationData().setSpecimen(true); + ssb.getReservationData().setText("Test"); + ssb.getReservationData().setTicketNumber("SKCTS86"); + ssb.getReservationData().setYear(3); + + + ssb.getReservationData().getStations().setArrivalStationCode("8012345"); + ssb.getReservationData().getStations().setDepartureStationCode("8054321"); + ssb.getReservationData().getStations().setCodeTable(SsbStationCodeTable.NRT); + + return ssb; + } + + public static SsbFrame getSsbNonUic() { + + SsbFrame ssb = new SsbFrame(); + + ssb.setHeader(new SsbHeader()); + ssb.getHeader().setIssuer(4711); + ssb.getHeader().setTicketType(SsbTicketType.NONUIC_23_BILATERAL); + ssb.getHeader().setVersion(1); + + + ssb.setNonUicData(new SsbNonUic()); + ssb.getNonUicData().setOpenData("TestData".getBytes()); + + + return ssb; + } + + public static void compareStations(SsbStations stations, SsbStations stations2) { + + assert (stations.getCodeTable().equals(stations2.getCodeTable())); + + assert (stations.getArrivalStationCode().equals(stations2.getArrivalStationCode())); + + assert (stations.getDepartureStationCode().equals(stations2.getDepartureStationCode())); + + } + + public static void compareCommonTicketPart(SsbCommonTicketPart part, SsbCommonTicketPart part2) { + + assert(part.isSpecimen() == part2.isSpecimen()); + assert(part.getDay() == part2.getDay()); + assert(part.getNumberOfAdults() == part2.getNumberOfAdults()); + assert(part.getNumberOfChildren() == part2.getNumberOfChildren()); + assert(part.getTicketNumber().equals(part2.getTicketNumber())); + assert(part.getYear() == part2.getYear()); + + } + + + + +} -- cgit v1.2.3 From 94d0ba8bdd36c6621e2478fdb3bcf1c790369006 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Mon, 13 Mar 2023 13:27:13 +0100 Subject: ssb non-standard signature encoding covered (decode only) --- .../java/org/uic/barcode/ssbFrame/SsbFrame.java | 29 ++++++++++--- .../java/org/uic/barcode/utils/SecurityUtils.java | 48 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java index 1ee68bb..b473c1e 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java @@ -1,5 +1,6 @@ package org.uic.barcode.ssbFrame; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.InvalidKeyException; @@ -76,17 +77,33 @@ public class SsbFrame { offset = offset + nonUicData.decodeContent(bytes,offset); } - - signaturePart1 = new byte[28]; - signaturePart2 = new byte[28]; - for (int i = 0 ; i < 28;i++) { - signaturePart1[i] = bytes[58 + i]; - signaturePart2[i] = bytes[58 + 28 + i]; + byte[] signatureBytes = new byte[56]; + + try { + //check for non-standard signature encoding + BigInteger[] bInts = SecurityUtils.decodeSignatureIntegerSequence(signatureBytes); + byte[] sig = SecurityUtils.encodeSignatureIntegerSequence(bInts[0],bInts[1]); + signaturePart1 = bInts[0].toByteArray(); + signaturePart2 = bInts[1].toByteArray(); + //decoding the entire signature was ok, so there was no split + } catch (Exception e) { + //the signature is correctly implemented, continue with recombination + signaturePart1 = new byte[28]; + signaturePart2 = new byte[28]; + + for (int i = 0 ; i < 28;i++) { + signaturePart1[i] = bytes[58 + i]; + signaturePart2[i] = bytes[58 + 28 + i]; + } } + } + + + public byte[] encode() throws EncodingFormatException { byte[] bytes = new byte[114]; diff --git a/src/main/java/org/uic/barcode/utils/SecurityUtils.java b/src/main/java/org/uic/barcode/utils/SecurityUtils.java index 29a2346..8c981af 100644 --- a/src/main/java/org/uic/barcode/utils/SecurityUtils.java +++ b/src/main/java/org/uic/barcode/utils/SecurityUtils.java @@ -263,4 +263,52 @@ public class SecurityUtils { return out.toByteArray(); } + public static byte[] recombineDsaSignature(byte[] sealdata) throws IOException { + + //check whether the encoding is wrong and the sealdata contain a signature + //remove trailing zeroes from the signature + BigInteger[] bInts = null; + try { + bInts = decodeSignatureIntegerSequence(sealdata); + byte[] sig = encodeSignatureIntegerSequence(bInts[0],bInts[1]); + //decoding the entire signature was ok, so there was no split + return sig; + } catch (Exception e) { + //the signature is correctly implemented, continue with recombination + } + + // split the data into two blocks + int length = sealdata.length / 2; + byte[] rBytes = Arrays.copyOfRange(sealdata, 0, length); + byte[] sBytes = Arrays.copyOfRange(sealdata, length, length + length); + + //convert to BigInteger to get rid of leading zeroes + BigInteger r = new BigInteger(1,rBytes); + BigInteger s = new BigInteger(1,sBytes); + + //encode as DSA signature structure + //SEQUENCE OF --> tag 16 + int sequenceTag = 16 + 32; // (bits 6 = 1 constructed) + //INTEGER --> tag 2 + int integerTag = 2; + + byte[] b1 = r.toByteArray(); + int lb1 = b1.length; + + byte[] b2 = s.toByteArray(); + int lb2 = b2.length; + int sequenceLength = lb1 + lb2 + 4; + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + out.write((byte) sequenceTag); + out.write((byte) sequenceLength); + out.write((byte) integerTag); + out.write((byte) lb1); + out.write(b1); + out.write((byte) integerTag); + out.write((byte) lb2); + out.write(b2); + return out.toByteArray(); + + } } -- cgit v1.2.3 From f1a08e7fb82e813ce6985460cc2606fc7b19ae13 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:15:31 +0100 Subject: SSB encoding format validation --- .../uic/barcode/ssbFrame/SsbCommonTicketPart.java | 28 ++++++++++++++--- .../java/org/uic/barcode/ssbFrame/SsbGroup.java | 21 ++++++++++++- .../java/org/uic/barcode/ssbFrame/SsbHeader.java | 18 ++++++++++- .../uic/barcode/ssbFrame/SsbNonReservation.java | 15 ++++++++- .../java/org/uic/barcode/ssbFrame/SsbPass.java | 36 +++++++++++++++++++++- .../org/uic/barcode/ssbFrame/SsbReservation.java | 27 +++++++++++++++- .../java/org/uic/barcode/ssbFrame/SsbStations.java | 26 +++++++++++++--- .../org/uic/barcode/ssbFrame/SsbTicketPart.java | 2 +- 8 files changed, 158 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java b/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java index 0a158f3..8eef552 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbCommonTicketPart.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public abstract class SsbCommonTicketPart extends SsbTicketPart { @@ -46,22 +47,41 @@ public abstract class SsbCommonTicketPart extends SsbTicketPart { return offset; } - protected int encodeCommonPart(byte[] bytes, int offset) { + protected int encodeCommonPart(byte[] bytes, int offset) throws EncodingFormatException { BitBuffer bits = new ByteBitBuffer(bytes); - + + if (numberOfAdults < 0 || numberOfAdults > 99) { + throw new EncodingFormatException("SSB number of adults too big"); + } bits.putInteger(offset,7, numberOfAdults); offset = offset + 7; + + if (numberOfChildren < 0 || numberOfChildren > 99) { + throw new EncodingFormatException("SSB number of children too big"); + } bits.putInteger(offset, 7, numberOfChildren); offset = offset + 7; + bits.put(offset,specimen); offset++; + bits.putInteger(offset, 6,classCode.ordinal()); offset = offset + 6; + + if (ticketNumber.length() > 14) { + throw new EncodingFormatException("SSB Ticket Number too long"); + } bits.putChar6String(offset, 84, ticketNumber); - offset = offset + 84; - bits.putInteger(offset, 4, year); + offset = offset + 84; + + + bits.putInteger(offset, 4, (year % 10)); offset = offset + 4; + + if (day > 512) { + throw new EncodingFormatException("SSB day too long"); + } bits.putInteger(offset, 9, day); offset = offset + 9; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java b/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java index 1b2f6e7..7751ef6 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbGroup.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public class SsbGroup extends SsbCommonTicketPart { @@ -52,7 +53,7 @@ public class SsbGroup extends SsbCommonTicketPart { } @Override - protected int encodeContent(byte[] bytes, int offset) { + protected int encodeContent(byte[] bytes, int offset) throws EncodingFormatException { offset = offset + encodeCommonPart(bytes, offset); @@ -61,23 +62,41 @@ public class SsbGroup extends SsbCommonTicketPart { bits.put(offset, isReturnJourney); offset = offset++; + if (firstDayOfValidity < 0 || firstDayOfValidity > 511) { + throw new EncodingFormatException("SSB first day of validity too big"); + } bits.putInteger(offset, 9, firstDayOfValidity); offset = offset + 9; + if (lastDayOfValidity < 0 || lastDayOfValidity > 511) { + throw new EncodingFormatException("SSB last day of validity too big"); + } bits.putInteger(offset, 9, lastDayOfValidity); offset = offset + 9; offset = stations.encode(offset, bytes); + if (groupName.length() > 12) { + throw new EncodingFormatException("SSB group name too big"); + } bits.putChar6String(offset, 72,groupName); offset = offset + 72; + if (counterMarkNumber < 0 || counterMarkNumber > 246) { + throw new EncodingFormatException("SSB number of countermark too big"); + } bits.putInteger(offset, 9,counterMarkNumber); offset = offset + 9; + if (infoCode < 0 || infoCode > 9999) { + throw new EncodingFormatException("SSB info code too big"); + } bits.putInteger(offset, 14, infoCode); offset = offset + 14; + if (text.length() > 24) { + throw new EncodingFormatException("SSB text too big"); + } bits.putChar6String(offset, 144, text); offset = offset + 144; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java b/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java index 2ea4a51..48c8eaf 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbHeader.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public class SsbHeader extends SsbTicketPart { @@ -40,13 +41,28 @@ public class SsbHeader extends SsbTicketPart { } - public int encodeContent(byte[] bytes, int offset) { + public int encodeContent(byte[] bytes, int offset) throws EncodingFormatException { BitBuffer bits = new ByteBitBuffer(bytes); + if (version < 0 || version > 15) { + throw new EncodingFormatException("SSB Version too big"); + } + bits.putInteger(0, 4, version); + + if (issuer < 0 || issuer > 9999) { + throw new EncodingFormatException("SSB Issuer code too big"); + } + bits.putInteger(4, 14, issuer); + + if (keyId < 0 || keyId > 15) { + throw new EncodingFormatException("SSB Key Id too big"); + } + bits.putInteger(18, 4, keyId); + bits.putInteger(22, 5, ticketType.ordinal()); return 4 + 14 + 4 + 5; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java b/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java index a1fb3ae..80fc2bc 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbNonReservation.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public class SsbNonReservation extends SsbCommonTicketPart { @@ -42,7 +43,7 @@ public class SsbNonReservation extends SsbCommonTicketPart { } @Override - protected int encodeContent(byte[] bytes, int offset) { + protected int encodeContent(byte[] bytes, int offset) throws EncodingFormatException { offset = offset + encodeCommonPart(bytes, offset); @@ -51,17 +52,29 @@ public class SsbNonReservation extends SsbCommonTicketPart { bits.put(offset, isReturnJourney); offset = offset++; + if (firstDayOfValidity < 0 || firstDayOfValidity > 511) { + throw new EncodingFormatException("SSB first day of validity too big"); + } bits.putInteger(offset, 9, firstDayOfValidity); offset = offset + 9; + if (lastDayOfValidity < 0 || lastDayOfValidity > 511) { + throw new EncodingFormatException("SSB last day of validity too big"); + } bits.putInteger(offset, 9, lastDayOfValidity); offset = offset + 9; offset = stations.encode(offset, bytes); + if (infoCode < 0 || infoCode > 9999) { + throw new EncodingFormatException("SSB info code too big"); + } bits.putInteger(offset, 14, infoCode); offset = offset + 14; + if (text.length() > 37) { + throw new EncodingFormatException("SSB text too big"); + } bits.putChar6String(offset, 222, text); offset = offset + 222; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java b/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java index 3598efd..a26fb61 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbPass.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public class SsbPass extends SsbCommonTicketPart { @@ -81,45 +82,78 @@ public class SsbPass extends SsbCommonTicketPart { } @Override - protected int encodeContent(byte[] bytes, int offset) { + protected int encodeContent(byte[] bytes, int offset) throws EncodingFormatException { offset = offset + encodeCommonPart(bytes, offset); BitBuffer bits = new ByteBitBuffer(bytes); + if (passSubType < 0 || passSubType > 3) { + throw new EncodingFormatException("SSB pass type too big"); + } bits.putInteger(offset, 2,passSubType); offset = offset + 2; + if (firstDayOfValidity < 0 || firstDayOfValidity > 511) { + throw new EncodingFormatException("SSB first day of validity too big"); + } bits.putInteger(offset, 9,firstDayOfValidity); offset = offset + 9; + if (maximumValidityDuration < 0 || maximumValidityDuration > 511) { + throw new EncodingFormatException("SSB validity duration too big"); + } bits.putInteger(offset, 9,maximumValidityDuration); offset = offset + 9; + if (numberOfTravels < 0 || numberOfTravels > 94) { + throw new EncodingFormatException("SSB number of travels too big"); + } bits.putInteger(offset, 7, numberOfTravels); offset = offset + 7; + if (country_1 < 0 || country_1 > 100) { + throw new EncodingFormatException("SSB country 1 too big"); + } bits.putInteger(offset, 7,country_1); offset = offset + 7; + if (country_2 < 0 || country_2 > 99) { + throw new EncodingFormatException("SSB country 2 too big"); + } bits.putInteger(offset, 7,country_2); offset = offset + 7; + if (country_3 < 0 || country_3 > 99) { + throw new EncodingFormatException("SSB country 3 too big"); + } bits.putInteger(offset, 7,country_3); offset = offset + 7; + if (country_4 < 0 || country_4 > 99) { + throw new EncodingFormatException("SSB country 4 too big"); + } bits.putInteger(offset, 7,country_4); offset = offset + 7; + if (country_5 < 0 || country_5 > 99) { + throw new EncodingFormatException("SSB country 5 too big"); + } bits.putInteger(offset, 7,country_5); offset = offset + 7; bits.put(offset, hasSecondPage); offset++; + if (infoCode < 0 || infoCode > 9999) { + throw new EncodingFormatException("SSB info code too big"); + } bits.putInteger(offset, 14, infoCode); offset = offset + 14; + if (text.length() > 40) { + throw new EncodingFormatException("SSB text too big"); + } bits.putChar6String(offset, 240,text); offset = offset + 240; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java b/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java index 73017d7..c70c2d1 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbReservation.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public class SsbReservation extends SsbCommonTicketPart { @@ -81,12 +82,15 @@ public class SsbReservation extends SsbCommonTicketPart { } @Override - protected int encodeContent(byte[] bytes, int offset) { + protected int encodeContent(byte[] bytes, int offset) throws EncodingFormatException { offset = offset + encodeCommonPart(bytes, offset); BitBuffer bits = new ByteBitBuffer(bytes); + if (ticketSubType < 0 || ticketSubType > 3) { + throw new EncodingFormatException("SSB pass type too big"); + } bits.putInteger(offset, 2,ticketSubType); offset = offset + 2; @@ -103,27 +107,48 @@ public class SsbReservation extends SsbCommonTicketPart { Open Tekst 6 Bit ASCII (27 Car) 162,000 */ + if (departureDate < 0 || departureDate > 512) { + throw new EncodingFormatException("SSB departure date too big"); + } bits.putInteger(offset, 9, departureDate); offset = offset + 9; + if (departureTime < 0 || departureTime > 1440) { + throw new EncodingFormatException("SSB departure time too big"); + } bits.putInteger(offset, 11,departureTime); offset = offset + 11; + if (train.length() > 5) { + throw new EncodingFormatException("SSB train too big"); + } bits.putChar6String(offset, 30,train); offset = offset + 30; + if (coach < 0 || coach > 999) { + throw new EncodingFormatException("SSB coach too big"); + } bits.putInteger(offset, 10,coach); offset = offset + 10; + if (place.length() > 3) { + throw new EncodingFormatException("SSB coach too big"); + } bits.putChar6String(offset, 18,place); offset = offset + 18; bits.put(offset, overbooking); offset++; + if (infoCode < 0 || infoCode > 9999) { + throw new EncodingFormatException("SSB info code too big"); + } bits.putInteger(offset, 14, infoCode); offset = offset + 14; + if (text.length() > 27) { + throw new EncodingFormatException("SSB text too big"); + } bits.putChar6String(offset, 162, text); offset = offset + 162; diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java b/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java index 34fbbc3..e3b7654 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbStations.java @@ -2,6 +2,7 @@ package org.uic.barcode.ssbFrame; import org.uic.barcode.asn1.uper.BitBuffer; import org.uic.barcode.asn1.uper.ByteBitBuffer; +import org.uic.barcode.ticket.EncodingFormatException; public class SsbStations { @@ -23,9 +24,7 @@ public class SsbStations { protected String departureStationCode = " "; protected SsbStationCodeTable codeTable = SsbStationCodeTable.NRT; - - - public int encode(int offset, byte[] bytes) { + public int encode(int offset, byte[] bytes) throws EncodingFormatException { boolean isAlphaNumeric = false; @@ -42,16 +41,33 @@ public class SsbStations { offset++; if (isAlphaNumeric) { + if (departureStationCode.length() > 6) { + throw new EncodingFormatException("SSB departure station too long"); + } bits.putChar6String(offset,30, departureStationCode); offset = offset + 30; + + if (arrivalStationCode.length() > 6) { + throw new EncodingFormatException("SSB arrival station too long"); + } bits.putChar6String(offset,30, arrivalStationCode); offset = offset + 30; } else { bits.putInteger(offset, 4, codeTable.ordinal()); offset = offset + 4; - bits.putInteger(offset, 28, Integer.parseInt(departureStationCode)); + + int stationCode = Integer.parseInt(departureStationCode); + if (stationCode < 0 || stationCode > 9999999) { + throw new EncodingFormatException("SSB departure station code too long"); + } + bits.putInteger(offset, 28, stationCode); offset = offset + 28; - bits.putInteger(offset, 28, Integer.parseInt(arrivalStationCode)); + + stationCode = Integer.parseInt(arrivalStationCode); + if (stationCode < 0 || stationCode > 9999999) { + throw new EncodingFormatException("SSB arrival station code too long"); + } + bits.putInteger(offset, 28, stationCode); offset = offset + 28; } diff --git a/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java index 5583e66..717608a 100644 --- a/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java +++ b/src/main/java/org/uic/barcode/ssbFrame/SsbTicketPart.java @@ -22,7 +22,7 @@ public abstract class SsbTicketPart { encodeContent(bytes, 0); } - protected abstract int encodeContent(byte[] bytes, int offset); + protected abstract int encodeContent(byte[] bytes, int offset) throws EncodingFormatException; -- cgit v1.2.3 From 0115a2248613a313a2e245ababedb905c79d1243 Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 14 Mar 2023 10:19:33 +0100 Subject: update version number --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0f6dd62..cdc6c2c 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.uic.barcode org.uic.barcode - 1.3.4 + 1.4.0 jar UIC barcode encoding and decoding of Aztec barcode content according to UIC IRS 90918-9 @@ -89,4 +89,4 @@ repo - + \ No newline at end of file -- cgit v1.2.3