diff options
23 files changed, 443 insertions, 96 deletions
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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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 { <T> boolean canDecode(Class<T> classOfT, Annotation[] extraAnnotations); - <T> T decode(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations); + <T> T decode(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations,AsnExtractor extractor); <T> T getDefault(Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(BitBuffer bitbuffer, Class<T> 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> T decode(byte[] bytes, Class<T> 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> T decode(byte[] bytes, Class<T> 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 <T> byte[] extract(byte[] bytes,String path,Class<T> 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> T decode(byte[] bytes, Class<T> classOfT, Field f) throws IllegalArgumentException, + public static <T> T decode(byte[] bytes, Class<T> 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> T decodeAny(BitBuffer bitbuffer,Class<T> classOfT, Field f, Annotation[] extraAnnotations) { + static <T> T decodeAny(BitBuffer bitbuffer,Class<T> 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> T decodeAsOpenType(BitBuffer bitbuffer, Class<T> classOfT,Field f, Annotation[] extraAnnotations) { + static <T> T decodeAsOpenType(BitBuffer bitbuffer, Class<T> 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;
|