From 67bd1413dc47ec37a9ba042949973eff0a5045fd Mon Sep 17 00:00:00 2001 From: CGantert345 <57003061+CGantert345@users.noreply.github.com> Date: Tue, 29 Jun 2021 14:59:45 +0200 Subject: - test for FCB version 3 --- src/main/java/org/uic/barcode/Decoder.java | 2 +- .../org/uic/barcode/dynamicFrame/DynamicFrame.java | 50 ++++-- .../ticket/api/asn/omv3/OpenTicketData.java | 2 +- .../uic/barcode/ticket/api/asn/omv3/PassData.java | 2 +- .../ticket/api/asn/omv3/TrainValidityType.java | 2 + .../barcode/ticket/api/utils/Api2AsnEncoder.java | 13 ++ .../ticket/api/utils/Api2OpenAsnEncoder.java | 2 +- .../ticket/api/utils/Api2OpenAsnEncoderV2.java | 10 +- .../ticket/api/utils/Api2OpenAsnEncoderV3.java | 13 +- .../barcode/ticket/api/utils/Asn2ApiDecoder.java | 13 ++ .../ticket/api/utils/OpenAsn2ApiDecoder.java | 2 +- .../ticket/api/utils/OpenAsn2ApiDecoderV2.java | 2 +- .../ticket/api/utils/OpenAsn2ApiDecoderV3.java | 2 +- .../uic/barcode/utils/AlgorithmNameResolver.java | 167 +++------------------ 14 files changed, 108 insertions(+), 174 deletions(-) create mode 100644 src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java create mode 100644 src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java (limited to 'src/main') diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java index e9dd4b0..09ee839 100644 --- a/src/main/java/org/uic/barcode/Decoder.java +++ b/src/main/java/org/uic/barcode/Decoder.java @@ -108,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) ; + return dynamicFrame.validateLevel1(key, provider) ; } else { if (staticFrame.verifyByAlgorithmOid(key,signingAlg, provider)) { return Constants.LEVEL1_VALIDATION_OK; diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java index 1d96d05..6cc1eaa 100644 --- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java +++ b/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java @@ -127,6 +127,7 @@ public class DynamicFrame extends Object{ String level2KeyAlg = this.getLevel2SignedData().getLevel1Data().level2KeyAlg; + if (level2KeyAlg == null || level2KeyAlg.length() == 0) { return Constants.LEVEL2_VALIDATION_NO_KEY; @@ -135,9 +136,7 @@ public class DynamicFrame extends Object{ if (this.level2Signature.toByteArray() == null || this.level2Signature.toByteArray().length == 0) { return Constants.LEVEL2_VALIDATION_NO_SIGNATURE; } - - - + String keyAlgName = null; try { keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg); @@ -147,31 +146,35 @@ public class DynamicFrame extends Object{ if (keyAlgName == null || keyAlgName.length() == 0) { return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED; } - + PublicKey key = null; try { - key = KeyFactory.getInstance(keyAlgName).generatePublic(new X509EncodedKeySpec(this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray())); + byte[] keyBytes = this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray(); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec); } catch (InvalidKeySpecException | NoSuchAlgorithmException e1) { return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED; } //find the algorithm name for the signature OID - String algo = null; + String level2SigAlg = this.getLevel2SignedData().getLevel1Data().level2SigningAlg; + + String sigAlgName = null; try { - algo = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,this.getLevel2SignedData().getLevel1Data().level2SigningAlg); + sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg); } catch (Exception e1) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } - if (algo == null) { + if (sigAlgName == null) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } Signature sig; try { if (prov == null) { - sig = Signature.getInstance(algo); + sig = Signature.getInstance(sigAlgName); } else { - sig = Signature.getInstance(algo, prov); + sig = Signature.getInstance(sigAlgName, prov); } } catch (NoSuchAlgorithmException e) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; @@ -183,7 +186,8 @@ public class DynamicFrame extends Object{ } try { - sig.update(UperEncoder.encode(level2SignedData)); + byte[] data = UperEncoder.encode(level2SignedData); + sig.update(data); } catch (SignatureException e) { return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } catch (IllegalArgumentException e) { @@ -210,7 +214,7 @@ public class DynamicFrame extends Object{ * Note: an appropriate security provider (e.g. BC) must be registered before * */ - public int validateLevel1(PublicKey key) { + public int validateLevel1(PublicKey key, Provider prov) { if (this.level2SignedData == null) { return Constants.LEVEL1_VALIDATION_NO_SIGNATURE; @@ -236,7 +240,12 @@ public class DynamicFrame extends Object{ Signature sig; try { - sig = Signature.getInstance(algo); + if (prov != null) { + sig = Signature.getInstance(algo, prov); + } else { + sig = Signature.getInstance(algo); + + } } catch (NoSuchAlgorithmException e) { return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED; } @@ -268,6 +277,18 @@ public class DynamicFrame extends Object{ } } + /** + * Verify the level 1 signature + * + * Note: an appropriate security provider (e.g. BC) must be registered before + * + */ + public int validateLevel1(PublicKey key) { + + return validateLevel1(key, null); + + } + public void signLevel2(PrivateKey key) throws Exception { //find the algorithm name for the signature OID @@ -276,7 +297,8 @@ public class DynamicFrame extends Object{ sig.initSign(key); byte[] data = level2SignedData.encode(); sig.update(data); - this.level2Signature = new OctetString(sig.sign()); + byte[] signature = sig.sign(); + this.level2Signature = new OctetString(signature); } diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java index 87e3f36..fa4208c 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java +++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/OpenTicketData.java @@ -35,7 +35,7 @@ import org.uic.barcode.asn1.datatypes.RestrictedString; import org.uic.barcode.asn1.datatypes.Sequence; import org.uic.barcode.asn1.datatypes.SizeRange; import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5; -import org.uic.barcode.ticket.api.asn.omv2.SequenceOfActivatedDays; +import org.uic.barcode.ticket.api.asn.omv3.SequenceOfActivatedDays; import org.uic.barcode.ticket.api.utils.DateTimeUtils; @Sequence diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java index 5334761..e4c42a6 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java +++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/PassData.java @@ -34,7 +34,7 @@ import org.uic.barcode.asn1.datatypes.IntRange; import org.uic.barcode.asn1.datatypes.RestrictedString; import org.uic.barcode.asn1.datatypes.Sequence; import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5; -import org.uic.barcode.ticket.api.asn.omv2.SequenceOfActivatedDays; +import org.uic.barcode.ticket.api.asn.omv3.SequenceOfActivatedDays; import org.uic.barcode.ticket.api.utils.DateTimeUtils; @Sequence diff --git a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java index 8f75dc9..88e5614 100644 --- a/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java +++ b/src/main/java/org/uic/barcode/ticket/api/asn/omv3/TrainValidityType.java @@ -25,12 +25,14 @@ import java.util.List; import org.uic.barcode.asn1.datatypes.Asn1Default; import org.uic.barcode.asn1.datatypes.Asn1Optional; import org.uic.barcode.asn1.datatypes.FieldOrder; +import org.uic.barcode.asn1.datatypes.HasExtensionMarker; import org.uic.barcode.asn1.datatypes.IntRange; import org.uic.barcode.asn1.datatypes.Sequence; import org.uic.barcode.asn1.datatypesimpl.SequenceOfStringIA5; import org.uic.barcode.ticket.api.utils.DateTimeUtils; @Sequence +@HasExtensionMarker public class TrainValidityType extends Object { public TrainValidityType() { } diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java new file mode 100644 index 0000000..11052b0 --- /dev/null +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2AsnEncoder.java @@ -0,0 +1,13 @@ +package org.uic.barcode.ticket.api.utils; + +import org.uic.barcode.ticket.EncodingFormatException; +import org.uic.barcode.ticket.api.asn.omv1.UicRailTicketData; +import org.uic.barcode.ticket.api.spec.IUicRailTicket; + +public abstract interface Api2AsnEncoder { + + + public byte[] encode(IUicRailTicket uicTicket) throws EncodingFormatException; + + +} diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java index 3f781ef..cab9b53 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoder.java @@ -151,7 +151,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /** * The Class Api2OpenAsnEncoder. */ -public class Api2OpenAsnEncoder { +public class Api2OpenAsnEncoder implements Api2AsnEncoder { /** diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java index 61bdba1..184dfd7 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV2.java @@ -152,7 +152,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /** * The Class Api2OpenAsnEncoder. */ -public class Api2OpenAsnEncoderV2 { +public class Api2OpenAsnEncoderV2 implements Api2AsnEncoder { /** * encode to asn1 model. @@ -1512,9 +1512,13 @@ public class Api2OpenAsnEncoderV2 { asnData.setValidity(document.getValidFrom(), document.getValidUntil()); - asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,9999)); + if (document.getType() != null) { + asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,32000)); + } - asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999)); + if (document.getAmount() != null) { + asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999)); + } return asnDocument; } diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java index 83406e8..9084d7a 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Api2OpenAsnEncoderV3.java @@ -155,7 +155,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /** * The Class Api2OpenAsnEncoder. */ -public class Api2OpenAsnEncoderV3 { +public class Api2OpenAsnEncoderV3 implements Api2AsnEncoder { /** * encode to asn1 model. @@ -1500,8 +1500,7 @@ public class Api2OpenAsnEncoderV3 { DocumentData asnDocument = new DocumentData(); TicketDetailData asnTicket = new TicketDetailData(); asnDocument.setTicket(asnTicket); - - + VoucherData asnData = new VoucherData(); asnDocument.getTicket().setVoucher(asnData); @@ -1518,9 +1517,13 @@ public class Api2OpenAsnEncoderV3 { asnData.setValidity(document.getValidFrom(), document.getValidUntil()); - asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,9999)); + if (document.getType() != null) { + asnData.setType(UicEncoderUtils.getRestrictedInt(document.getType(), 1,32000)); + } - asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999)); + if (document.getAmount() != null) { + asnData.setValue(UicEncoderUtils.getRestrictedInt(document.getAmount(),1,9999999)); + } return asnDocument; } diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java new file mode 100644 index 0000000..e751f48 --- /dev/null +++ b/src/main/java/org/uic/barcode/ticket/api/utils/Asn2ApiDecoder.java @@ -0,0 +1,13 @@ +package org.uic.barcode.ticket.api.utils; + +import java.io.IOException; + +import org.uic.barcode.ticket.api.spec.IUicRailTicket; + +public interface Asn2ApiDecoder { + + + public IUicRailTicket decodeFromAsn (byte[] data) throws IOException; + + +} diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java index d203487..bf3918c 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoder.java @@ -118,7 +118,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /** * The Class OpenAsn2ApiDecoder. */ -public class OpenAsn2ApiDecoder { +public class OpenAsn2ApiDecoder implements Asn2ApiDecoder { IUicTicketObjectFactory factory = SimpleUicTicketObjectFactory.getInstance(); diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java index b8ee363..fc68f91 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV2.java @@ -118,7 +118,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /** * The Class OpenAsn2ApiDecoder. */ -public class OpenAsn2ApiDecoderV2 { +public class OpenAsn2ApiDecoderV2 implements Asn2ApiDecoder { IUicTicketObjectFactory factory = SimpleUicTicketObjectFactory.getInstance(); diff --git a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java index 36622fc..56efcb1 100644 --- a/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java +++ b/src/main/java/org/uic/barcode/ticket/api/utils/OpenAsn2ApiDecoderV3.java @@ -121,7 +121,7 @@ import org.uic.barcode.ticket.api.spec.IZone; /** * The Class OpenAsn2ApiDecoder. */ -public class OpenAsn2ApiDecoderV3 { +public class OpenAsn2ApiDecoderV3 implements Asn2ApiDecoder { IUicTicketObjectFactory factory = SimpleUicTicketObjectFactory.getInstance(); diff --git a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java index 1671ba9..4491358 100644 --- a/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java +++ b/src/main/java/org/uic/barcode/utils/AlgorithmNameResolver.java @@ -3,11 +3,6 @@ package org.uic.barcode.utils; import java.security.Provider; import java.security.Provider.Service; import java.security.Security; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class AlgorithmNameResolver { @@ -16,10 +11,6 @@ public class AlgorithmNameResolver { public static final String TYPE_SIGNATURE_ALG = "Signature"; - private static final Pattern KEY_TYPE_PATTERN = Pattern.compile("^(\\w+)[.].*$"); - private static final Pattern KEY_ALIAS_TYPE_PATTERN = Pattern.compile("^Alg[.]Alias[.](\\w+).*$"); - private static final Pattern KEY_OID_PATTERN = Pattern.compile(".*?(\\d+(?:[.]\\d+){3,})$"); - public static String getSignatureAlgorithmName (String oid) throws Exception { Provider[] provs = Security.getProviders(); @@ -32,85 +23,35 @@ public class AlgorithmNameResolver { return null; } + + public static String getName (String type, String oid) throws Exception { - - public static String getName(String type, String oid) throws Exception { - - Provider[] provs = Security.getProviders(); - - for (Provider prov : provs) { - - String name = getName(type, oid, prov); - if (name != null) return name; - - } - - if (oid.startsWith("1.2.840.10045")) { - return "ECDSA"; - } else if (oid.startsWith("1.2.840.10040")) { - return "DSA"; + Provider[] provs = Security.getProviders(); + for (Provider prov : provs) { + Service service = prov.getService(type,oid); + if (service != null) { + return service.getAlgorithm(); + } } - return null; - - } - - public static String getName(String type, String oid, Provider prov) throws Exception { - - SortedSet typeAndOID = getTypeAndOIDStrings(prov); - - for (String entry : typeAndOID) { - String[] typeAndOIDArray = entry.split("-"); - String ptype = typeAndOIDArray[0]; - if (ptype.equalsIgnoreCase(type)) { - String poid = typeAndOIDArray[1]; - Service pservice = prov.getService(ptype, poid); - String palgo = pservice.getAlgorithm(); - - if (poid != null && ptype.equalsIgnoreCase(type) && poid.equals(oid)) { - return palgo; - } - } - } - - if (oid.startsWith("1.2.840.10045")) { return "ECDSA"; } else if (oid.startsWith("1.2.840.10040")) { return "DSA"; } - - return null; - - } - - public static String getName(String type, String oid, String providerName) throws Exception { - - Provider[] provs = Security.getProviders(); - - for (Provider prov : provs) { - - if (providerName == null || prov.getName().equals(providerName)) { - - SortedSet typeAndOID = getTypeAndOIDStrings(prov); - for (String entry : typeAndOID) { - String[] typeAndOIDArray = entry.split("-"); - String ptype = typeAndOIDArray[0]; - if (ptype.equalsIgnoreCase(type)) { - String poid = typeAndOIDArray[1]; - Service pservice = prov.getService(ptype, poid); - String palgo = pservice.getAlgorithm(); - - if (ptype.equalsIgnoreCase(type) && poid.equals(oid)) { - return palgo; - } - } - } - } - } - - + return null; + + } + + + public static String getName(String type, String oid, Provider prov) throws Exception { + + Service service = prov.getService(type,oid); + if (service != null) { + return service.getAlgorithm(); + } + if (oid.startsWith("1.2.840.10045")) { return "ECDSA"; } else if (oid.startsWith("1.2.840.10040")) { @@ -119,73 +60,9 @@ public class AlgorithmNameResolver { return null; - } - - - - private static SortedSet getTypeAndOIDStrings(Provider prov) { - - SortedSet typeAndOID = new TreeSet<>(); - - Set keys = prov.keySet(); - for (Object key : keys) { - String keyString = key.toString(); - Matcher oidMatcher = KEY_OID_PATTERN.matcher(keyString); - if (oidMatcher.matches()) { - // get OID from matched keyString - String oid = oidMatcher.group(1); - - // determine type - String type; - Matcher aliasTypeMatcher = KEY_ALIAS_TYPE_PATTERN.matcher(keyString); - if (aliasTypeMatcher.matches()) { - type = aliasTypeMatcher.group(1); - } else { - Matcher typeMatcher = KEY_TYPE_PATTERN.matcher(keyString); - typeMatcher.matches(); - type = typeMatcher.group(1); - } - // algorithm parameters are not algorithms, so skip them - if (type.equals("AlgorithmParameters")) { - continue; - } - - // auto-removes dupes - typeAndOID.add(type + "-" + oid); - } - } - return typeAndOID; - } + } + - public static String getSecurityNames() throws Exception { - - Provider[] provs = Security.getProviders(); - - StringBuilder sb = new StringBuilder(); - - for (Provider prov : provs) { - - SortedSet typeAndOID = getTypeAndOIDStrings(prov); - - for (String entry : typeAndOID) { - String[] typeAndOIDArray = entry.split("-"); - String ptype = typeAndOIDArray[0]; - String poid = typeAndOIDArray[1]; - Service pservice = prov.getService(ptype, poid); - String palgo = ""; - if ( pservice != null) { - palgo = pservice.getAlgorithm(); - } - sb.append(prov).append(";"); - sb.append(ptype).append(";"); - sb.append(poid).append(";"); - sb.append(palgo).append(";"); - sb.append("\r\n"); - } - } - return sb.toString(); - - } } -- cgit v1.2.3