From 09f0f9449a10b713207126348105fafec4781bed Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Mon, 24 Jan 2022 16:51:04 +0100 Subject: signature validation changed to work with teh dynamic header version 2. --- src/main/java/org/uic/barcode/Decoder.java | 9 +- .../org/uic/barcode/asn1/uper/AsnExtractor.java | 80 +++++++++++++++ .../java/org/uic/barcode/asn1/uper/AsnUtils.java | 59 +++++++++++ .../java/org/uic/barcode/asn1/uper/BitBuffer.java | 1 + .../org/uic/barcode/asn1/uper/BitStringCoder.java | 2 +- .../org/uic/barcode/asn1/uper/BooleanCoder.java | 2 +- .../org/uic/barcode/asn1/uper/ByteBitBuffer.java | 30 ++++-- .../java/org/uic/barcode/asn1/uper/ByteCoder.java | 2 +- .../org/uic/barcode/asn1/uper/ChoiceCoder.java | 6 +- .../java/org/uic/barcode/asn1/uper/Decoder.java | 2 +- .../java/org/uic/barcode/asn1/uper/EnumCoder.java | 2 +- .../java/org/uic/barcode/asn1/uper/IntCoder.java | 2 +- .../java/org/uic/barcode/asn1/uper/SeqOfCoder.java | 4 +- .../org/uic/barcode/asn1/uper/SequenceCoder.java | 29 +++++- .../org/uic/barcode/asn1/uper/StringCoder.java | 2 +- .../org/uic/barcode/asn1/uper/UperEncoder.java | 46 +++++++-- .../barcode/dynamicFrame/api/IDynamicFrame.java | 26 ++--- .../dynamicFrame/api/SimpleDynamicFrame.java | 109 ++++++++++++--------- .../dynamicFrame/v1/DynamicFrameCoderV1.java | 15 +++ .../dynamicFrame/v2/DynamicFrameCoderV2.java | 11 +++ .../uic/barcode/utils/AlgorithmNameResolver.java | 37 ++++++- .../org/uic/barcode/test/BinaryStringTest.java | 61 ++++++++++++ .../test/DynamicFrameDynamicContentApiTest.java | 2 - 23 files changed, 443 insertions(+), 96 deletions(-) create mode 100644 src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java create mode 100644 src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java create mode 100644 src/test/java/org/uic/barcode/test/BinaryStringTest.java diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index b980f19..5cb0546 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -81,7 +81,7 @@ public class Decoder { */ public int validateLevel1(PublicKey key, String signingAlg) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel1(key) ; + return dynamicFrame.validateLevel1(key, data) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg)) { return Constants.LEVEL1_VALIDATION_OK; @@ -91,7 +91,6 @@ public class Decoder { } } - /** * Validate level 1. * @@ -109,7 +108,7 @@ public class Decoder { */ public int validateLevel1(PublicKey key, String signingAlg, Provider provider) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException, IllegalArgumentException, UnsupportedOperationException, IOException, EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel1(key, provider) ; + return dynamicFrame.validateLevel1(key, provider, data) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg, provider)) { return Constants.LEVEL1_VALIDATION_OK; @@ -127,7 +126,7 @@ public class Decoder { */ public int validateLevel2() throws EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel2() ; + return dynamicFrame.validateLevel2(null, data) ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } @@ -140,7 +139,7 @@ public class Decoder { */ public int validateLevel2(Provider prov) throws EncodingFormatException { if (!isStaticHeader(data)) { - return dynamicFrame.validateLevel2(prov) ; + return dynamicFrame.validateLevel2(prov,data) ; } else { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } diff --git a/src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java b/src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java new file mode 100644 index 0000000..0d5d1da --- /dev/null +++ b/src/main/java/org/uic/barcode/asn1/uper/AsnExtractor.java @@ -0,0 +1,80 @@ +package org.uic.barcode.asn1.uper; + +public class AsnExtractor { + + private String path = null; + + private boolean extractionStarted = false; + private boolean extractionCompleted = false; + + private BitBuffer bitBuffer = null; + private int startBit = 0; + private int endBit = 0; + + AsnExtractor(String path, BitBuffer bitBuffer) { + this.path = path; + this.bitBuffer = bitBuffer; + } + + public byte[] getResult() { + + if (!extractionCompleted) { + return null; + } + + if (!(endBit > startBit)) { + return null; + } + + String bitString = bitBuffer.toBooleanString(startBit, endBit - startBit); + + while (bitString.length() % 8 != 0) { + bitString = bitString + "0"; + } + + return AsnUtils.fromBooleanString(bitString); + + } + + + + public boolean found(String className) { + + if (extractionStarted || extractionCompleted) return false; + + if (path != null && path.length() > 0 && className != null & className.length() > 0) { + if (className.endsWith(path)){ + return true; + } + } + + return false; + } + + public void startExtraction(int position) { + + if (path == null || path.length() == 0 || bitBuffer == null) { + return; + } + + if (!extractionCompleted && !extractionStarted) { + extractionStarted = true; + startBit = position; + } + } + + public void endExtraction(int position) { + if (extractionStarted) { + extractionCompleted = true; + endBit = position; + } + + } + + public boolean isStarted() { + return extractionStarted; + } + + + +} diff --git a/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java new file mode 100644 index 0000000..dbb95c9 --- /dev/null +++ b/src/main/java/org/uic/barcode/asn1/uper/AsnUtils.java @@ -0,0 +1,59 @@ +package org.uic.barcode.asn1.uper; + +public class AsnUtils { + + + private static byte[] mask = new byte[] { + (byte) 0b1000_0000, + 0b0100_0000, + 0b0010_0000, + 0b0001_0000, + 0b0000_1000, + 0b0000_0100, + 0b0000_0010, + 0b0000_0001, + }; + + + public static byte[] fromBooleanString(final String s) { + + char[] ascii = s.toCharArray(); + if (ascii == null || ascii.length == 0) { + return null; + } + // get length/8 times bytes with 3 bit shifts to the right of the length + final byte[] l_raw = new byte[ascii.length >> 3]; + /* + * We decr index jj by 8 as we go along to not recompute indices using multiplication every time inside the + * loop. + */ + for (int ii = 0, jj = 0; ii < l_raw.length; ii++, jj += 8) { + for (int bits = 0; bits < mask.length; ++bits) { + if (ascii[jj + bits] == '1') { + l_raw[ii] |= mask[bits]; + } + } + } + return l_raw; + } + + public static String toBooleanString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length); + for (int i = 0; i < bytes.length*8;i++) { + sb.append(AsnUtils.get(bytes,i) ? "1" : "0"); + } + return sb.toString(); + } + + public static boolean get(byte[] bytes, int index) { + + if (index < 0) { + throw new IndexOutOfBoundsException("Index " + index + " is less than 0"); + } else if (index >= bytes.length * 8) { + throw new IndexOutOfBoundsException("Index " + index + " violates the limit " + bytes.length*8); + } + boolean result = (bytes[index / 8] & mask[index % 8]) != 0; + return result; + } + +} diff --git a/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java b/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java index bba0de7..21d0e03 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java +++ b/src/main/java/org/uic/barcode/asn1/uper/BitBuffer.java @@ -19,6 +19,7 @@ public interface BitBuffer { BitBuffer flip(); String toBooleanString(int startIndex, int length); String toBooleanStringFromPosition(int startIndex); + byte[] fromBooleanString(String s); byte[] array(); BitBuffer putByte(byte element); byte getByte(); diff --git a/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java b/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java index 19aac9b..6f435c4 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/BitStringCoder.java @@ -97,7 +97,7 @@ class BitStringCoder implements Decoder, Encoder { @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); if (!Asn1VarSizeBitstring.class.isAssignableFrom(classOfT)) { diff --git a/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java b/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java index 3bd7a38..892f851 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/BooleanCoder.java @@ -22,7 +22,7 @@ class BooleanCoder implements Decoder, Encoder { @SuppressWarnings("unchecked") @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { Boolean result = new Boolean(bitbuffer.get()); UperEncoder.logger.debug(String.format("BOOL: decoded as %s",result)); return (T) result; diff --git a/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java b/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java index 3ed3eed..e409005 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java +++ b/src/main/java/org/uic/barcode/asn1/uper/ByteBitBuffer.java @@ -3,7 +3,7 @@ package org.uic.barcode.asn1.uper; public class ByteBitBuffer implements BitBuffer { - + byte[] bytes; byte[] mask = new byte[] { (byte) 0b1000_0000, @@ -45,7 +45,8 @@ public class ByteBitBuffer implements BitBuffer { bytes = newbytes; } - @Override public BitBuffer put(int index, boolean element) { + @Override + public BitBuffer put(int index, boolean element) { if (bytes.length <= index / 8) { if (isFinite) { throw new IndexOutOfBoundsException(); } else { grow(); } @@ -58,21 +59,24 @@ public class ByteBitBuffer implements BitBuffer { return this; } - @Override public BitBuffer put(boolean element) { + @Override + public BitBuffer put(boolean element) { put(position, element); position++; limit = limit < position ? position : limit; // TODO: should it be here? return this; } - @Override public BitBuffer putByte(byte element) { + @Override + public BitBuffer putByte(byte element) { for (int i = 0; i < 8; i++) { put((element & mask[i]) != 0); } return this; } - @Override public BitBuffer putByteArray(int index, byte[] data) { + @Override + public BitBuffer putByteArray(int index, byte[] data) { for (int l = 0; l < data.length;l++) { for (int i = 0; i < 8; i++) { @@ -83,7 +87,8 @@ public class ByteBitBuffer implements BitBuffer { } - @Override public byte getByte() { + @Override + public byte getByte() { byte result = 0; for (int i = 0; i < 8; i++) { result |= (get() ? 1 : 0) << (7 - i); @@ -91,11 +96,13 @@ public class ByteBitBuffer implements BitBuffer { return result; } - @Override public int limit() { + @Override + public int limit() { return limit; } - @Override public String toBooleanString(int startIndex, int length) { + @Override + public String toBooleanString(int startIndex, int length) { StringBuilder sb = new StringBuilder(length); for (int i = startIndex; i < startIndex + length; i++) { sb.append(get(i) ? "1" : "0"); @@ -267,5 +274,12 @@ public class ByteBitBuffer implements BitBuffer { return stringBuilder.toString().trim(); } + + public byte[] fromBooleanString(final String s) { + + return AsnUtils.fromBooleanString(s); + + } + } diff --git a/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java b/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java index f26a598..5ecb925 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/ByteCoder.java @@ -21,7 +21,7 @@ class ByteCoder implements Decoder, Encoder { @SuppressWarnings("unchecked") @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { UperEncoder.logger.debug("BYTE"); return (T) new Byte((byte) UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, 255, false))); } diff --git a/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java b/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java index d17a813..0bbce73 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/ChoiceCoder.java @@ -95,7 +95,7 @@ class ChoiceCoder implements Decoder, Encoder { @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field1, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),extraAnnotations); UperEncoder.logger.debug(String.format("CHOICE: %s", classOfT.getName())); T result = UperEncoder.instantiate(classOfT); @@ -120,7 +120,7 @@ class ChoiceCoder implements Decoder, Encoder { Class classOfElement = field != null ? field.getType() : null; if (field != null) { try { - Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations()); + Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations(),extractor); if (field != null) { field.set(result, decodedValue); } @@ -144,7 +144,7 @@ class ChoiceCoder implements Decoder, Encoder { UperEncoder.newRange(0, sorter.ordinaryFields.size() - 1, false)); Field f = sorter.ordinaryFields.get(index); UperEncoder.logger.debug(String.format("CHOICE: selected %s", f.getName())); - Object fieldValue = UperEncoder.decodeAny(bitbuffer, f.getType(),f, f.getAnnotations()); + Object fieldValue = UperEncoder.decodeAny(bitbuffer, f.getType(),f, f.getAnnotations(),extractor); try { f.set(result, fieldValue); } catch (IllegalArgumentException | IllegalAccessException e) { diff --git a/src/main/java/org/uic/barcode/asn1/uper/Decoder.java b/src/main/java/org/uic/barcode/asn1/uper/Decoder.java index 947a752..3140443 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/Decoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/Decoder.java @@ -5,6 +5,6 @@ import java.lang.reflect.Field; public interface Decoder { boolean canDecode(Class classOfT, Annotation[] extraAnnotations); - T decode(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations); + T decode(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations,AsnExtractor extractor); T getDefault(Class classOfT, Annotation[] extraAnnotations); } diff --git a/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java b/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java index 5d78bc7..3bfdec9 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/EnumCoder.java @@ -82,7 +82,7 @@ class EnumCoder implements Decoder, Encoder { @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); UperEncoder.logger.debug("ENUM"); boolean extensionPresent = false; diff --git a/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java b/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java index 5964a64..e5e48c1 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/IntCoder.java @@ -27,7 +27,7 @@ class IntCoder implements Encoder, Decoder { @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),extraAnnotations); String pos = String.format("Position: %d.%d", bitbuffer.position()/8 , bitbuffer.position() % 8); UperEncoder.logger.debug(String.format("%s: INTEGER",pos)); diff --git a/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java b/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java index a7ae7ba..d0ce782 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/SeqOfCoder.java @@ -96,7 +96,7 @@ class SeqOfCoder implements Decoder, Encoder { @SuppressWarnings("unchecked") @Override public T decode(BitBuffer bitbuffer, Class classOfT,Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); UperEncoder.logger.debug(String.format("SEQUENCE OF for %s", classOfT)); @@ -135,7 +135,7 @@ class SeqOfCoder implements Decoder, Encoder { } } for (int i = 0; i < size; i++) { - coll.add(UperEncoder.decodeAny(bitbuffer, classOfElements,field, annotationArray)); + coll.add(UperEncoder.decodeAny(bitbuffer, classOfElements,field, annotationArray, extractor)); } T result = null; diff --git a/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java b/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java index ce89a3e..3af7217 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/SequenceCoder.java @@ -150,13 +150,24 @@ class SequenceCoder implements Decoder, Encoder { @Override public T decode(BitBuffer bitbuffer, Class classOfT,Field f1, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, + AsnExtractor extractor) { UperEncoder.logger.debug(String.format("decode SEQUENCE %s",classOfT.getSimpleName())); AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),extraAnnotations); T result = UperEncoder.instantiate(classOfT); - Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT); + Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT); boolean hasExtensionMarker = UperEncoder.hasExtensionMarker(annotations); boolean extensionPresent = false; + + //check Extraction + boolean extract = false; + if (extractor != null && !extractor.isStarted() && extractor.found(classOfT.getCanonicalName())) { + extractor.startExtraction(bitbuffer.position()); + extract = true; + } + + + //start decodong if (hasExtensionMarker) { extensionPresent = bitbuffer.get(); UperEncoder.logger.debug(String.format("with extension marker, extension %s", extensionPresent ? "present!" : "absent")); @@ -175,7 +186,7 @@ class SequenceCoder implements Decoder, Encoder { (UperEncoder.isOptional(f) && optionalFieldsMask.pop()))) { UperEncoder.logger.debug(String.format("Field : %s", f.getName())); try { - f.set(result, UperEncoder.decodeAny(bitbuffer,f.getType(),f, f.getAnnotations())); + f.set(result, UperEncoder.decodeAny(bitbuffer,f.getType(),f, f.getAnnotations(),extractor)); } catch (IllegalAccessException e) { throw new IllegalArgumentException("can't access 'set method' for field " + f + " of class " + classOfT + " " + e, e); } @@ -196,6 +207,11 @@ class SequenceCoder implements Decoder, Encoder { if (!hasExtensionMarker) { //done sorter.revertAccess(); + + if (extract) { + extractor.endExtraction(bitbuffer.position()); + } + return result; } @@ -222,7 +238,7 @@ class SequenceCoder implements Decoder, Encoder { Class classOfElement = field != null ? field.getType() : null; if (field != null) { try { - Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations()); + Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement,field, field.getAnnotations(),extractor); if (field != null) { field.set(result, decodedValue); } @@ -269,6 +285,11 @@ class SequenceCoder implements Decoder, Encoder { } // end of extension handling } sorter.revertAccess(); + + if (extract) { + extractor.endExtraction(bitbuffer.position()); + } + return result; } diff --git a/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java b/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java index 349e988..a504096 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/StringCoder.java @@ -150,7 +150,7 @@ class StringCoder implements Decoder, Encoder { @Override public T decode(BitBuffer bitbuffer, Class classOfT, Field field, - Annotation[] extraAnnotations) { + Annotation[] extraAnnotations, AsnExtractor extractor) { UperEncoder.logger.debug("decode String"); AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); RestrictedString restrictionAnnotation = annotations.getAnnotation(RestrictedString.class); diff --git a/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java b/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java index d5c5d1e..c256b4f 100644 --- a/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java +++ b/src/main/java/org/uic/barcode/asn1/uper/UperEncoder.java @@ -66,7 +66,7 @@ public final class UperEncoder { public static T decode(byte[] bytes, Class classOfT) throws IllegalArgumentException, UnsupportedOperationException { BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes)); - T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}); + T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}, null); if (bitQueue.remaining() > 7) { throw new IllegalArgumentException("Can't fully decode " + classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result @@ -74,11 +74,43 @@ public final class UperEncoder { } return result; } + + public static T decode(byte[] bytes, Class classOfT,AsnExtractor extractor) throws IllegalArgumentException, + UnsupportedOperationException { + BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes)); + T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}, extractor); + if (bitQueue.remaining() > 7) { + throw new IllegalArgumentException("Can't fully decode " + + classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result + + "; remaining " + bitQueue.remaining() + " bits: " + bitQueue); + } + return result; + } + + + public static byte[] extract(byte[] bytes,String path,Class classOfT) throws IllegalArgumentException, UnsupportedOperationException { + + BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes)); + + AsnExtractor extractor = new AsnExtractor(path,bitQueue); + + T result = decodeAny(bitQueue, classOfT,null, new Annotation[] {}, extractor); + if (bitQueue.remaining() > 7) { + throw new IllegalArgumentException("Can't fully decode " + + classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result + + "; remaining " + bitQueue.remaining() + " bits: " + bitQueue); + } + return extractor.getResult(); + } + + + + - public static T decode(byte[] bytes, Class classOfT, Field f) throws IllegalArgumentException, + public static T decode(byte[] bytes, Class classOfT, Field f,AsnExtractor extractor) throws IllegalArgumentException, UnsupportedOperationException { BitBuffer bitQueue = bitBufferFromBinaryString(binaryStringFromBytes(bytes)); - T result = decodeAny(bitQueue, classOfT, f, new Annotation[] {}); + T result = decodeAny(bitQueue, classOfT, f, new Annotation[] {}, extractor); if (bitQueue.remaining() > 7) { throw new IllegalArgumentException("Can't fully decode " + classOfT.getName() + ", got (" + result.getClass().getName() + "): " + result @@ -108,13 +140,13 @@ public final class UperEncoder { + " with extra annotations " + Arrays.asList(extraAnnotations)); } - static T decodeAny(BitBuffer bitbuffer,Class classOfT, Field f, Annotation[] extraAnnotations) { + static T decodeAny(BitBuffer bitbuffer,Class classOfT, Field f, Annotation[] extraAnnotations, AsnExtractor extractor) { logger.debug(String.format(String.format("Decoding classOfT : %s",classOfT.getCanonicalName()))); for (Decoder e : decoders) { if (e.canDecode(classOfT, extraAnnotations)) { - return e.decode(bitbuffer, classOfT,f, extraAnnotations); + return e.decode(bitbuffer, classOfT,f, extraAnnotations,extractor); } } @@ -216,7 +248,7 @@ public final class UperEncoder { } - static T decodeAsOpenType(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations) { + static T decodeAsOpenType(BitBuffer bitbuffer, Class classOfT,Field f, Annotation[] extraAnnotations,AsnExtractor extractor) { logger.debug(String.format("OPEN TYPE for %s. Encoding preceedes length determinant", classOfT != null ? classOfT.getName() : "null")); long numBytes = decodeLengthDeterminant(bitbuffer); BitBuffer openTypeBitBuffer = ByteBitBuffer.allocate((int)numBytes * 8); @@ -225,7 +257,7 @@ public final class UperEncoder { } openTypeBitBuffer.flip(); if (classOfT != null) { - T result = decodeAny(openTypeBitBuffer, classOfT, f, extraAnnotations); + T result = decodeAny(openTypeBitBuffer, classOfT, f, extraAnnotations, extractor); // Assert that padding bits are all 0. logger.debug(String.format("open type had padding bits")); for (int i = 0; i < openTypeBitBuffer.remaining(); i++) { diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java index f357c4d..1e8a0ff 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java @@ -89,21 +89,23 @@ public interface IDynamicFrame{ * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @return the int + * @param data the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2() throws EncodingFormatException; + public int validateLevel2(byte[] data) throws EncodingFormatException; /** * Verify the level 2 signature * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @param prov the prov - * @return the int + * @param prov the registered security provider + * @param data the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2(Provider prov) throws EncodingFormatException; + public int validateLevel2(Provider prov, byte[] data) throws EncodingFormatException; /** * Verify the level 1 signature @@ -111,23 +113,25 @@ public interface IDynamicFrame{ * Note: an appropriate security provider (e.g. BC) must be registered before * * @param key the key - * @param prov the prov - * @return the int + * @param data the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException; + public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException; - /** * Verify the level 1 signature * * Note: an appropriate security provider (e.g. BC) must be registered before * * @param key the key - * @return the int + * @param prov the registered security provider + * @param the data content + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key) throws EncodingFormatException; + public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException; + /** * Sign level 2 data without a specific security provider. diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java index 4c5c879..ec52758 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java @@ -12,6 +12,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Date; +import org.uic.barcode.asn1.uper.AsnUtils; import org.uic.barcode.dynamicContent.api.DynamicContentCoder; import org.uic.barcode.dynamicContent.api.IUicDynamicContent; import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1; @@ -143,6 +144,22 @@ public class SimpleDynamicFrame implements IDynamicFrame { return null; } + private byte[] getEncoded(String path, byte[] data) throws EncodingFormatException { + + if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV1.getEncoded(path, data); + + } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { + + return DynamicFrameCoderV2.getEncoded(path, data); + + } + + return null; + } + + private byte[] encode(ILevel2Data level2SignedData2) throws EncodingFormatException { if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) { @@ -213,9 +230,9 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel2() throws EncodingFormatException { + public int validateLevel2(byte[] data) throws EncodingFormatException { - return validateLevel2(null); + return validateLevel2(null, data); } @@ -224,11 +241,11 @@ public class SimpleDynamicFrame implements IDynamicFrame { * * Note: an appropriate security provider (e.g. BC) must be registered before * - * @param prov the prov - * @return the int + * @param prov the registered security provider + * @return the return error code * @throws EncodingFormatException */ - public int validateLevel2(Provider prov) throws EncodingFormatException { + public int validateLevel2(Provider prov, byte[] data) throws EncodingFormatException { String level2KeyAlg = this.getLevel2Data().getLevel1Data().getLevel2KeyAlg(); @@ -244,7 +261,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { String keyAlgName = null; try { - keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg); + keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg,prov); } catch (Exception e1) { return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED; } @@ -268,7 +285,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { String sigAlgName = null; try { - sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg); + sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg,prov); } catch (Exception e1) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } @@ -293,8 +310,14 @@ public class SimpleDynamicFrame implements IDynamicFrame { } try { - byte[] data = encode(level2Data); - sig.update(data); + //TODO + //byte[] signedData = encode(level2Data); + //String s1 = AsnUtils.toBooleanString(signedData); + + byte[] signedData2 = getEncoded("Level2Data", data); + //String s2 = AsnUtils.toBooleanString(signedData); + + sig.update(signedData2); } catch (SignatureException e) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } catch (IllegalArgumentException e) { @@ -325,7 +348,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException { + public int validateLevel1(PublicKey key, Provider prov, byte[] data) throws EncodingFormatException { if (level2Data == null) { return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; @@ -342,7 +365,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { //find the algorithm name for the signature OID String algo = null; try { - algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2Data().getLevel1Data().getLevel1SigningAlg()); + algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2Data().getLevel1Data().getLevel1SigningAlg(), prov); } catch (Exception e1) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } @@ -368,7 +391,15 @@ public class SimpleDynamicFrame implements IDynamicFrame { } try { - sig.update(encode(level2Data.getLevel1Data())); + + //byte[] encodedData = encode(level2Data.getLevel1Data()); + //String s1 = AsnUtils.toBooleanString(encodedData); + //TODO + byte[] encodedData2 = getEncoded("Level1Data", data); + //String s2 = AsnUtils.toBooleanString(encodedData2); + + sig.update(encodedData2); + } catch (SignatureException e) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } catch (IllegalArgumentException e) { @@ -402,9 +433,9 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @return the int * @throws EncodingFormatException */ - public int validateLevel1(PublicKey key) throws EncodingFormatException { + public int validateLevel1(PublicKey key, byte[] data) throws EncodingFormatException { - return validateLevel1(key, null); + return validateLevel1(key, null,data); } @@ -416,13 +447,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { */ public void signLevel2(PrivateKey key) throws Exception { - //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level2Data.getLevel1Data().getLevel2SigningAlg()); - Signature sig = Signature.getInstance(algo); - sig.initSign(key); - byte[] data = encode(level2Data); - sig.update(data); - level2Signature = sig.sign(); + signLevel2(key, null); } @@ -430,17 +455,22 @@ public class SimpleDynamicFrame implements IDynamicFrame { * Sign level 2 data. * * @param key the key - * @param prov the security Provider + * @param prov the registered security provider * @throws Exception the exception */ public void signLevel2(PrivateKey key, Provider prov) throws Exception { //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2Data().getLevel1Data().getLevel2SigningAlg()); - Signature sig = Signature.getInstance(algo,prov); + String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2Data().getLevel1Data().getLevel2SigningAlg(), prov); + Signature sig = null; + if (prov != null) { + sig = Signature.getInstance(algo,prov); + } else { + sig = Signature.getInstance(algo); + } sig.initSign(key); - byte[] data = encode(level2Data); - sig.update(data); + byte[] signedData = encode(level2Data); + sig.update(signedData); level2Signature = sig.sign(); } @@ -453,8 +483,7 @@ public class SimpleDynamicFrame implements IDynamicFrame { * @throws EncodingFormatException the encoding format exception */ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException { - - + level2Data.setLevel2Data(new SimpleData()); level2Data.getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1); @@ -501,19 +530,8 @@ public class SimpleDynamicFrame implements IDynamicFrame { */ public void signLevel1(PrivateKey key) throws Exception { - if (level2Data == null) return; - - ILevel1Data level1Data = level2Data.getLevel1Data(); - - if (level1Data == null) return; + signLevel1(key, null); - //find the algorithm name for the signature OID - String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg()); - Signature sig = Signature.getInstance(algo); - sig.initSign(key); - byte[] data = encode(level1Data); - sig.update(data); - level2Data.setLevel1Signature(sig.sign()); } /** @@ -538,16 +556,17 @@ public class SimpleDynamicFrame implements IDynamicFrame { //find the algorithm name for the signature OID String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg()); - Signature sig = Signature.getInstance(algo, prov); + Signature sig = null; + if (prov != null) { + sig = Signature.getInstance(algo, prov); + } else { + sig = Signature.getInstance(algo); + } sig.initSign(key); byte[] data = encode(level1Data); sig.update(data); level2Data.setLevel1Signature(sig.sign()); } - - - - } diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java index f7b3f3d..1cffa12 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java @@ -100,6 +100,19 @@ public class DynamicFrameCoderV1 { return UperEncoder.encode(asn); } + + public static byte[] getEncoded(String path, byte[] data) { + + if (path.endsWith("Level1Data")){ + return UperEncoder.extract(data, "Level1DataType" ,DynamicFrame.class ); + } else if (path.endsWith("Level2Data")){ + return UperEncoder.extract(data, "Level2DataType" ,DynamicFrame.class ); + } + + return null; + } + + public static byte[] encode(ILevel2Data level2SignedData) throws EncodingFormatException { Level2DataType asn = populateAsn(level2SignedData); @@ -183,6 +196,8 @@ public class DynamicFrameCoderV1 { return asnLevel1; } + + diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java index 8987f59..bdaa31a 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java @@ -197,6 +197,17 @@ public class DynamicFrameCoderV2 { return asnLevel1; } + + public static byte[] getEncoded(String path, byte[] data) { + + if (path.endsWith("Level1Data")){ + return UperEncoder.extract(data, "Level1DataType" ,DynamicFrame.class ); + } else if (path.endsWith("Level2Data")){ + return UperEncoder.extract(data, "Level2DataType" ,DynamicFrame.class ); + } + + return null; + } diff --git a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java index 4491358..a3154f3 100644 --- a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java +++ b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java @@ -24,6 +24,26 @@ public class AlgorithmNameResolver { } + public static String getSignatureAlgorithmName (String oid, Provider provider) throws Exception { + + if (provider != null) { + Service service = provider.getService(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,oid); + return service.getAlgorithm(); + } + + + Provider[] provs = Security.getProviders(); + for (Provider prov : provs) { + Service service = prov.getService(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,oid); + if (service != null) { + return service.getAlgorithm(); + } + } + return null; + + } + + public static String getName (String type, String oid) throws Exception { Provider[] provs = Security.getProviders(); @@ -45,9 +65,22 @@ public class AlgorithmNameResolver { } - public static String getName(String type, String oid, Provider prov) throws Exception { + public static String getName(String type, String oid, Provider provider) throws Exception { + + Service service = null; + if (provider == null) { + + Provider[] provs = Security.getProviders(); + for (Provider prov : provs) { + service = prov.getService(type,oid); + } + + } else { + service = provider.getService(type,oid); + } + - Service service = prov.getService(type,oid); + if (service != null) { return service.getAlgorithm(); } diff --git a/src/test/java/org/uic/barcode/test/BinaryStringTest.java b/src/test/java/org/uic/barcode/test/BinaryStringTest.java new file mode 100644 index 0000000..d5533fa --- /dev/null +++ b/src/test/java/org/uic/barcode/test/BinaryStringTest.java @@ -0,0 +1,61 @@ +package org.uic.barcode.test; + +import java.io.IOException; +import org.junit.Test; +import org.uic.barcode.asn1.uper.AsnUtils; +import org.uic.barcode.ticket.EncodingFormatException; + +public class BinaryStringTest { + + + + + @Test public void testBinaryString() throws IOException, EncodingFormatException{ + + String bs1 = "01000000"; + String ms1 = "1000000001000000001000000001000000001000000001000000001000000001"; + String ms2 = "10000000010000000010000000010000"; + + + //String bs1 = "1011111100001000011011100000000000000001000000010000010010000000"; + + byte[] bytes = AsnUtils.fromBooleanString(bs1); + + String bs2 = AsnUtils.toBooleanString(bytes); + + + + byte[] mask = new byte[] { + (byte) 0b1000_0000, + 0b0100_0000, + 0b0010_0000, + 0b0001_0000, + 0b0000_1000, + 0b0000_0100, + 0b0000_0010, + 0b0000_0001, + }; + String bs3 = AsnUtils.toBooleanString(mask); + byte[] bytes2 = AsnUtils.fromBooleanString(bs3); + + + byte[] mask2 = new byte[] { + (byte) 0b1000_0000, + 0b0100_0000, + 0b0010_0000, + 0b0001_0000, + }; + String bs4 = AsnUtils.toBooleanString(mask2); + byte[] bytes3 = AsnUtils.fromBooleanString(bs4); + + + assert(bs4.equals(ms2)); + + assert(bs3.equals(ms1)); + + assert(bs1.equals(bs2)); + + } + + +} \ No newline at end of file diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java index 5a70841..4d34c1b 100644 --- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java +++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentApiTest.java @@ -10,8 +10,6 @@ import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.Security; import java.security.SignatureException; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; -- cgit v1.2.3