summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java')
-rw-r--r--src/main/java/org/uic/barcode/ssbFrame/SsbFrame.java282
1 files changed, 282 insertions, 0 deletions
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);
+ }
+}