summaryrefslogtreecommitdiffstats
path: root/src/org/uic/barcode/staticFrame/StaticFrame.java
diff options
context:
space:
mode:
authorCGantert345 <57003061+CGantert345@users.noreply.github.com>2021-03-29 14:08:45 +0200
committerCGantert345 <57003061+CGantert345@users.noreply.github.com>2021-03-29 14:08:45 +0200
commite023e674020f1a435f7b8c8b9276704f576ea6e5 (patch)
tree011863c021df3e5356f07b056d30d0e7476061e4 /src/org/uic/barcode/staticFrame/StaticFrame.java
parentMerge pull request #13 from UnionInternationalCheminsdeFer/time_zone_fix_3 (diff)
downloadUIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.tar
UIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.tar.gz
UIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.tar.bz2
UIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.tar.lz
UIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.tar.xz
UIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.tar.zst
UIC-barcode-e023e674020f1a435f7b8c8b9276704f576ea6e5.zip
Diffstat (limited to 'src/org/uic/barcode/staticFrame/StaticFrame.java')
-rw-r--r--src/org/uic/barcode/staticFrame/StaticFrame.java764
1 files changed, 0 insertions, 764 deletions
diff --git a/src/org/uic/barcode/staticFrame/StaticFrame.java b/src/org/uic/barcode/staticFrame/StaticFrame.java
deleted file mode 100644
index 5246ac7..0000000
--- a/src/org/uic/barcode/staticFrame/StaticFrame.java
+++ /dev/null
@@ -1,764 +0,0 @@
-package org.uic.barcode.staticFrame;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.InvalidKeyException;
-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;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.zip.DataFormatException;
-import java.util.zip.Deflater;
-import java.util.zip.Inflater;
-
-import org.uic.barcode.ticket.EncodingFormatException;
-
-
-/**
- * The Class StaticHeader implements the static bar code header frame defined in UIC IRS 90918-9.
- * It allows to decode and encode the bar code content and to add sub-records as defined in the IRS 90918-9 for:
- * - additional header data
- * - Ticket Layout content
- * - Flexible content
- * - bilateral data records
- */
-public class StaticFrame {
-
- /** The additional header record. */
- private UHEADDataRecord headerRecord;
-
- /** The bar code version. */
- private int version;
-
- /** The u_flex. */
- private UFLEXDataRecord uFlex;
-
- /** The u_tlay. */
- private UTLAYDataRecord uTlay;
-
- /** The security provider. */
- private String securityProvider;
-
- /** The signature key. */
- private String signatureKey;
-
- /** The signature. */
- private byte[] signature;
-
- /** The data records. */
- private ArrayList<DataRecord> dataRecords = new ArrayList<DataRecord>();
-
-
- private byte[] signedData = null;
-
- /**
- * Instantiates a new static header frame.
- */
- public StaticFrame (){ }
-
-
-
- /**
- * Instantiates a new static header and decodes the provided data.
- *
- * @param bytes the bar code data
- * @throws EncodingFormatException the encoding format exception
- * @throws DataFormatException the data format exception
- * @throws IOException Signals that an I/O exception has occurred.
- */
- public StaticFrame (byte[] bytes) throws EncodingFormatException, DataFormatException, IOException{
- decode(bytes);
- }
-
-
- /**
- * Encode the barcode data.
- *
- * @param version the barcode version
- * @return byte[] the encoded data as
- * @throws IOException Signals that an I/O exception has occurred.
- * @throws Exception the exception
- */
- /*
- * creates a UIC bar code of version 1
- *
- * limits:
- * - version 1 allows for signatures up to 50 byte length
- * - max data length 2048 Byte
- * input:
- * data to be included
- * provider of the signature
- * processing:
- * 1. create header informations
- * 2. compression of the data content
- * 3. adding a signature
- * output:
- * raw data to be included in an aztec bar code
- *
- */
- public byte[] encode() throws IOException, Exception {
-
- if (headerRecord == null && uFlex == null && uTlay == null
- && (dataRecords == null || dataRecords.isEmpty())) return null;
-
- if (signedData == null) {
- signedData = encodeData();
- }
-
- if (version != 1 && version != 2) {
- throw (new Exception(String.format("UIC Barcode Version %d not supported", version)));
- }
-
- if (signedData.length < 1) {
- throw new IOException("data missing!");
- }
- if (signedData.length > 2048) {
- throw new IOException("too many data!"); //2048 should be enough
- }
-
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-
- //UIC bar code version 1
- String header = "#UT01";
- if (version == 2) {
- header = "#UT02";
- }
- outputStream.write(header.getBytes());
-
- outputStream.write(securityProvider.getBytes());
-
-
- while (signatureKey.length() < 5) {
- signatureKey = "0" + signatureKey;
- }
- outputStream.write(signatureKey.getBytes());
-
- if (signature.length < 1) {
- // signature too small for bar code version 1
- throw new IOException("signature size too small!");
- }
-
- if (version == 1) {
- if (signature.length > 50) {
- // signature too large for bar code version 1
- throw new IOException("signature size too large!");
- }
- outputStream.write(Arrays.copyOfRange(signature, 0, 50));
- } else if (version == 2) {
- BigInteger[] bInts = null;
- byte zeroByte = 0;
-
- bInts = decodeSignatureIntegerSequence(signature);
- byte[] r = toUnsignedBytes(bInts[0]);
-
- byte[] s = toUnsignedBytes(bInts[1]);
-
- if (r.length > 32 || s.length > 32) {
- throw (new EncodingFormatException(String.format("DSA signature too big")));
- }
- for (int i = 0; i < 32 - r.length; i++) {
- outputStream.write(zeroByte);
- }
- outputStream.write(r);
- for (int i = 0; i < 32 - s.length; i++) {
- outputStream.write(zeroByte);
- }
- outputStream.write(s);
- //outputStream.write(Arrays.copyOfRange(signature, 0, 64));
- }
-
- String length = String.format("%04d", signedData.length);
- outputStream.write(length.getBytes());
-
- outputStream.write(signedData);
-
- outputStream.close();
-
- return outputStream.toByteArray();
- }
-
-
- /**
- * Adds a proprietary data record.
- *
- * @param record the record
- */
- public void addDataRecord(DataRecord record) {
- dataRecords.add(record);
- }
-
- /**
- * Gets the version of the header frame.
- *
- * @return the version
- */
- public int getVersion() {
- return version;
- }
-
- /**
- * Sets the version of the header frame.
- * supported values are 1 and 2
- *
- * @param version the new version
- */
- public void setVersion(int version) {
- this.version = version;
- }
-
- /**
- * Gets the security provider.
- *
- * @return the security provider
- */
- public String getSecurityProvider() {
- return securityProvider;
- }
-
- /**
- * Sets the security provider.
- *
- * @param securityProvider the new security provider
- */
- public void setSecurityProvider(String securityProvider) {
- this.securityProvider = securityProvider;
- }
-
- /**
- * Gets the signature key identifier.
- *
- * @return the signature key
- */
- public String getSignatureKey() {
- return signatureKey;
- }
-
- /**
- * Sets the signature key identifier.
- *
- * @param signatureKey the new signature key
- */
- public void setSignatureKey(String signatureKey) {
- this.signatureKey = signatureKey;
- }
-
- /**
- * Gets the signature.
- *
- * @return the signature
- */
- public byte[] getSignature() {
- return signature;
- }
-
- /**
- * Sets the signature.
- *
- * @param signature the new signature
- */
- public void setSignature(byte[] signature) {
- this.signature = signature;
- }
-
- /**
- * Gets the additional header record.
- *
- * @return the header record
- */
- public UHEADDataRecord getHeaderRecord() {
- return headerRecord;
- }
-
- /**
- * Gets the list of bilateral data records.
- *
- * @return the data records
- */
- public ArrayList<DataRecord> getDataRecords() {
- return dataRecords;
- }
-
- /**
- * Gets the data for signing.
- *
- * @return the data to be signed
- * @throws IOException Signals that an I/O exception has occurred.
- * @throws EncodingFormatException the encoding format exception
- */
- public byte[] getDataForSignature() throws IOException, EncodingFormatException {
- // data compression
- if (signedData != null) return signedData;
-
- Deflater deflater = new Deflater();
- byte[] data = encodeData();
- deflater.setInput(data);
- ByteArrayOutputStream compressStream = new ByteArrayOutputStream(data.length);
- byte[] buffer = new byte[2048];
- deflater.finish();
- while (!deflater.finished()) {
- int count = deflater.deflate(buffer); // returns the number of result bytes
- compressStream.write(buffer, 0, count);
- }
- compressStream.close();
-
- return compressStream.toByteArray();
- }
-
- /**
- * Get the encoded data for the bar code.
- *
- * @return the byte[]
- * @throws IOException Signals that an I/O exception has occurred.
- * @throws EncodingFormatException the encoding format exception
- */
- private byte[] encodeData() throws IOException, EncodingFormatException {
-
- if (this.uFlex == null && this.uTlay == null && this.headerRecord == null &&
- (dataRecords == null || dataRecords.isEmpty())) return null;
-
- ByteArrayOutputStream totalStream = new ByteArrayOutputStream();
-
- //encode header for layout
- if (headerRecord != null) {
- byte[] header = headerRecord.encode();
-
- if (header != null && header.length > 0) {
- totalStream.write(header);
- }
- }
-
- //encode layout
- if (uTlay != null) {
- byte[] layout = uTlay.encode();
- if (layout != null && layout.length > 0) {
- totalStream.write(layout);
- }
- }
-
- if (uFlex != null) {
- byte[] content = uFlex.encode();
- if (content != null && content.length > 0){
- totalStream.write(content);
- }
- }
-
- //third party content
- for (DataRecord dataRecord : dataRecords){
-
- byte[] content = dataRecord.encode();
- if (content != null && content.length > 0){
- totalStream.write(content);
- }
- }
- return totalStream.toByteArray();
- }
-
- /**
- * 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();
- }
-
- /**
- * 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;
- }
-
- /**
- * Decode.
- *
- * @param inputData the input data
- * @throws EncodingFormatException the encoding format exception
- * @throws DataFormatException the data format exception
- * @throws IOException Signals that an I/O exception has occurred.
- */
- public void decode(byte[] inputData) throws EncodingFormatException, DataFormatException, IOException {
-
-
- int offset = 0;
- String headerTag = new String( Arrays.copyOfRange(inputData,offset,offset + 3));
- offset = offset + 3;
- if (!headerTag.equals("#UT")) {
- throw (new EncodingFormatException("not a UIC barcode"));
- }
-
-
- String versionValue = new String(Arrays.copyOfRange(inputData,offset,offset + 2));
- offset = offset + 2;
- int barcodeVersion = 0;
- try {
- barcodeVersion = Integer.parseInt(versionValue);
- this.setVersion(barcodeVersion);
- } catch (NumberFormatException e2) {
- throw (new EncodingFormatException(String.format("UIC Barcode Version %s not supported", versionValue)));
- }
-
- String providerValue = new String( Arrays.copyOfRange(inputData,offset,offset + 4));
- this.setSecurityProvider(providerValue);
- offset = offset + 4;
-
- String signatureKeyIdValue = new String( Arrays.copyOfRange(inputData,offset,offset + 5));
- this.setSignatureKey(signatureKeyIdValue);
- offset = offset + 5;
-
- byte[] sealdata = null;
-
- if (barcodeVersion == 1) {
- sealdata = Arrays.copyOfRange(inputData, offset, offset + 50);
- signature = trimDsaSignature(sealdata);
- offset = offset + 50;
- } else if (barcodeVersion == 2) {
- sealdata = Arrays.copyOfRange(inputData, offset, offset + 64);
- signature = recombineDsaSignature(sealdata);
- offset = offset + 64;
- } else {
- throw (new EncodingFormatException(String.format("UIC Barcode Version %s not supported", versionValue)));
- }
-
-
- String lengthValue = new String( Arrays.copyOfRange(inputData,offset,offset + 4));
- offset = offset + 4;
-
- int dataLength = 0;
- dataLength = Integer.parseInt(lengthValue);
-
- signedData = Arrays.copyOfRange(inputData, offset, offset + dataLength);
-
- ByteBuffer containedDataBuffer = ByteBuffer.allocate(dataLength);
- containedDataBuffer.put(signedData);
-
- byte[] inflatedDataBuffer = new byte[2000];
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- Inflater inflater = new Inflater();
- byte[] inflaterInput = containedDataBuffer.array();
- inflater.setInput(inflaterInput);
- while (!inflater.finished()) {
- int count = inflater.inflate(inflatedDataBuffer,0,2000);
- if (inflater.needsDictionary()) {
- break;
- }
- outputStream.write(inflatedDataBuffer, 0, count);
- }
-
- outputStream.close();
-
- byte[] byteData = outputStream.toByteArray();
-
- offset = 0;
- int remainingBytes = byteData.length;
-
- while (remainingBytes > 0) {
-
- String tag = new String(Arrays.copyOfRange(byteData, offset, offset + 6));
- int length = 0;
-
- if (tag.startsWith("U_TLAY")) {
- UTLAYDataRecord record = new UTLAYDataRecord();
- length = record.decode(Arrays.copyOfRange(byteData, offset, byteData.length));
- this.uTlay = record;
- } else if (tag.startsWith("U_FLEX")) {
- UFLEXDataRecord record = new UFLEXDataRecord();
- length = record.decode(Arrays.copyOfRange(byteData, offset, byteData.length));
- this.uFlex = record;
- } else if (tag.startsWith("U_HEAD")) {
- UHEADDataRecord record = new UHEADDataRecord();
- length = record.decode(Arrays.copyOfRange(byteData, offset, byteData.length));
- this.headerRecord = record;
- } else {
- DataRecord record = new GENERICDataRecord(tag);
- length = record.decode(Arrays.copyOfRange(byteData, offset, byteData.length));
- addDataRecord(record);
- }
- offset = offset + length;
- remainingBytes = remainingBytes - length;
- }
- }
-
-
- private 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();
-
-
- }
-
- 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;
- }
-
-
- private byte[] trimDsaSignature(byte[] sealdata) throws EncodingFormatException {
- //remove trailing zeroes from the signature
- BigInteger[] bInts = null;
- try {
- bInts = decodeSignatureIntegerSequence(sealdata);
- return encodeSignatureIntegerSequence(bInts[0],bInts[1]);
- } catch (Exception e) {
- throw (new EncodingFormatException(String.format("Invalid DSA signature")));
- }
- }
-
-
-
- /**
- * Verify the signature
- *
- * Note: an appropriate security provider (e.g. BC) must be registered before
- *
- * @param key the key
- * @param algo the algorithm name
- * @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 operation exception
- * @throws EncodingFormatException
- * @throws IOException
- */
- public boolean ByAlgorithmName(PublicKey key, String algo) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException {
- Signature sig = Signature.getInstance(algo);
- sig.initVerify(key);
- sig.update(this.getDataForSignature());
- return sig.verify(this.getSignature());
- }
-
- /**
- * 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
- * @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 operatign exception
- * @throws EncodingFormatException
- * @throws IOException
- */
- public boolean verifyByAlgorithmOid(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException {
- //find the algorithm name for the signature OID
- String algo = null;
- Provider[] provs = Security.getProviders();
- for (Provider prov : provs) {
- Service service = prov.getService("Signature",signingAlg);
- if (service != null) {
- algo = service.getAlgorithm();
- }
- }
- Signature sig = Signature.getInstance(algo);
- sig.initVerify(key);
- sig.update(getDataForSignature());
- return sig.verify(this.getSignature());
- }
-
- /**
- * Sign the contained data block.
- *
- * 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
- * @return
- * @throws NoSuchAlgorithmException the no such algorithm exception
- * @throws InvalidKeyException the invalid key exception
- * @throws SignatureException the signature exception
- * @throws EncodingFormatException
- * @throws IOException
- */
- public void signByAlgorithmOID(PrivateKey key,String signingAlg) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException, EncodingFormatException {
- //find the algorithm name for the signature OID
- String algo = null;
- Provider[] provs = Security.getProviders();
- for (Provider prov : provs) {
- Service service = prov.getService("Signature",signingAlg);
- if (service != null) {
- algo = service.getAlgorithm();
- }
- }
- Signature sig = Signature.getInstance(algo);
- sig.initSign(key);
- signedData = getDataForSignature();
- sig.update(signedData);
- signature = sig.sign();
- }
-
- /**
- * Sign the contained data block.
- *
- * Note: an appropriate security provider (e.g. BC) must be registered before
- *
- * @param key the key
- * @param algo the name of the signing algorithm
- * @return
- * @throws NoSuchAlgorithmException the no such algorithm exception
- * @throws InvalidKeyException the invalid key exception
- * @throws SignatureException the signature exception
- * @throws EncodingFormatException
- * @throws IOException
- */
- public void signUsingAlgorithmName(PrivateKey key,String algo) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException, EncodingFormatException {
- Signature sig = Signature.getInstance(algo);
- sig.initSign(key);
- sig.update(getDataForSignature());
- signature = sig.sign();
- }
-
-
-
- public UFLEXDataRecord getuFlex() {
- return uFlex;
- }
-
-
-
- public UTLAYDataRecord getuTlay() {
- return uTlay;
- }
-
-
-
- public void setuFlex(UFLEXDataRecord uFlex) {
- this.uFlex = uFlex;
- }
-
-
-
- public void setuTlay(UTLAYDataRecord uTlay) {
- this.uTlay = uTlay;
- }
-
-
-
- public void setHeaderRecord(UHEADDataRecord headerRecord) {
- this.headerRecord = headerRecord;
- }
-
-
-
-
-}