summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCGantert345 <57003061+CGantert345@users.noreply.github.com>2022-01-21 18:19:36 +0100
committerCGantert345 <57003061+CGantert345@users.noreply.github.com>2022-01-21 18:19:36 +0100
commit17f05b763d70f350bad482df9378c571c2ebddf6 (patch)
treeb388db6cdf2906fab3dd5a1dc2f79fbfe3f903ea
parentextended api for dynamic content (diff)
downloadUIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.tar
UIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.tar.gz
UIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.tar.bz2
UIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.tar.lz
UIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.tar.xz
UIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.tar.zst
UIC-barcode-17f05b763d70f350bad482df9378c571c2ebddf6.zip
-rw-r--r--misc/uicBarcodeHeader_v2.0.0.asn126
-rw-r--r--misc/uicRailTicketData_v1.3.1.data793
-rw-r--r--misc/uicRailTicketData_v1.3.1_a.data245
-rw-r--r--pom.xml2
-rw-r--r--src/main/java/org/uic/barcode/Decoder.java44
-rw-r--r--src/main/java/org/uic/barcode/Encoder.java102
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java7
-rw-r--r--src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java12
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/Constants.java2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/IData.java39
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java202
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java164
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java25
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java59
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java553
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java254
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java75
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/package.html9
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/DataType.java)2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java432
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java189
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java)2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java74
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java)2
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java95
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java)11
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java203
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java374
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java (renamed from src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java)4
-rw-r--r--src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java25
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java2
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java10
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java10
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java7
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java8
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java6
-rw-r--r--src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java2
-rw-r--r--src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java10
-rw-r--r--src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java24
39 files changed, 4075 insertions, 130 deletions
diff --git a/misc/uicBarcodeHeader_v2.0.0.asn b/misc/uicBarcodeHeader_v2.0.0.asn
new file mode 100644
index 0000000..79d104d
--- /dev/null
+++ b/misc/uicBarcodeHeader_v2.0.0.asn
@@ -0,0 +1,126 @@
+-- Author: ClemensGantert
+-- Created: Thu Jun 04 17:19:28 CEST 2020
+ASN-Module DEFINITIONS AUTOMATIC TAGS ::= BEGIN
+
+-- imports and exports
+-- EXPORTS ALL;
+
+
+-- ##############################################################################################
+-- #
+-- # UIC barcode header - version 2.0.0
+-- #
+-- ##############################################################################################
+
+
+-- ##############################################################################################
+-- #
+-- # Naming and encoding conventions
+-- #
+-- # - A bar code which is only static (printed on a paper), and for which the security is in the system,
+-- # does not need any of these elements.
+-- # - A bar code which is only static, and includes its own security, needs:
+-- # level1Signature
+-- # level1KeyAlg if the associated key does not include the complete certificate in keys.xml but only the public key
+-- # (but level1SigningAlg is not necessary as it is in keys.xml)
+-- # - A dynamic bar code including static and dynamic signatures needs:
+-- # The same elements as a static bar code above,
+-- # level2SigningAlg, level2keyAlg, level2PublicKey, and level2Signature.
+-- #
+-- # Changes to Version 1:
+-- #
+-- # - endOfValidity added in Level1Data
+-- # - extension option added on all structures
+-- #
+-- #########################################################################################
+
+
+-- ############################################################################################
+
+
+-- type assignments
+
+ -- #########################################################################################
+ -- the basic entry point of the data structure
+ -- ##########################################################################################
+ UicBarcodeHeader ::= SEQUENCE {
+ -- barcode format type
+ format IA5String,
+ -- "U2" = UIC ticket
+
+
+ level2SignedData Level2DataType,
+
+ -- signature is calculated on the PER unaligned encoding of level2 signature data
+ level2Signature OCTET STRING OPTIONAL,
+ ...
+
+
+ }
+
+ Level2DataType ::= SEQUENCE {
+
+ level1Data Level1DataType,
+
+ -- signature is calculated on the PER unaligned encoding of level1 signature data
+ level1Signature OCTET STRING OPTIONAL,
+
+ level2Data DataType OPTIONAL,
+ ...
+
+ }
+
+
+ Level1DataType ::= SEQUENCE {
+
+ -- provider of the level1 signature (RICS code)
+ securityProviderNum INTEGER (1..32000) OPTIONAL,
+ securityProviderIA5 IA5String OPTIONAL,
+
+ keyId INTEGER(0..99999) OPTIONAL,
+
+ dataSequence SEQUENCE OF DataType,
+
+
+ -- object identifier of the key algorithms
+ -- e.g.
+ -- ECC P-256 1.2.840.10045.3.1.7
+ level1KeyAlg OBJECT IDENTIFIER OPTIONAL,
+ level2KeyAlg OBJECT IDENTIFIER OPTIONAL,
+
+ -- object identifier of the signing algorithm
+ -- e.g.
+ -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ -- ECDSA-256 1.2.840.10045.4.3.2
+ -- algorithm used for signing
+ level1SigningAlg OBJECT IDENTIFIER OPTIONAL,
+ level2SigningAlg OBJECT IDENTIFIER OPTIONAL,
+ level2PublicKey OCTET STRING OPTIONAL,
+
+ -- end of the validity of the bar code, after this date and time the bar code needs to be regenerated
+ -- if end of validity is provided year day and time must be provided.
+ -- year, day, time are in UTC
+ -- the provider of the bar code must ensure that the end of validity of the bar code is
+ -- before the end of validity of the key pair used on level 2
+ endOfValidityYear INTEGER (2016..2269) OPTIONAL,
+ -- number of the day in the year (1.1. = 1)
+ endOfValidityDay INTEGER (1..366) OPTIONAL,
+ -- The number of the minutes of the day
+ endOfValidityTime INTEGER (0..1439) OPTIONAL,
+ ...
+ }
+
+ DataType ::= SEQUENCE {
+ -- Content of data format:
+ -- FCBn (FCB1 = FCB version 1, FCB2 = FCB version 2)
+ -- FDCn dynamic content
+ -- or proprietary:
+ -- _RICS company code + addon
+ dataFormat IA5String,
+ data OCTET STRING,
+ ...
+ }
+
+
+END \ No newline at end of file
diff --git a/misc/uicRailTicketData_v1.3.1.data b/misc/uicRailTicketData_v1.3.1.data
new file mode 100644
index 0000000..e0ee943
--- /dev/null
+++ b/misc/uicRailTicketData_v1.3.1.data
@@ -0,0 +1,793 @@
+value UicRailTicketData ::= {
+ issuingDetail {
+ securityProviderNum 1,
+ securityProviderIA5 "1",
+ issuerNum 32000,
+ issuerIA5 "1",
+ issuingYear 2018,
+ issuingDay 1,
+ issuingTime 600,
+ issuerName "name",
+ specimen TRUE,
+ securePaperTicket FALSE,
+ activated TRUE,
+ currency "SRF",
+ currencyFract 3,
+ issuerPNR "issuerTestPNR",
+ extension { extensionId "1", extensionData '82DA'H },
+ issuedOnTrainNum 123,
+ issuedOnTrainIA5 "123",
+ issuedOnLine 12,
+ pointOfSale {
+ geoUnit microDegree,
+ coordinateSystem wgs84
+ hemisphereLongitude north,
+ hemisphereLatitude east,
+ longitude 12345,
+ latitude 56789,
+ accuracy microDegree
+ }
+ },
+ travelerDetail{
+ traveler {
+ {
+ firstName "John",
+ secondName "Little",
+ lastName "Dow",
+ idCard "12345",
+ passportId "JDTS",
+ title "PhD",
+ gender male,
+ customerIdIA5 "DZE5gT",
+ customerIdNum 12345,
+ yearOfBirth 1901,
+ monthOfBirth 12,
+ dayOfBirthInMonth 31,
+ ticketHolder TRUE,
+ passengerType senior,
+ passengerWithReducedMobility FALSE,
+ countryOfResidence 101,
+ countryOfPassport 102,
+ countryOfIdCard 103,
+ status {
+ {customerStatus 1, customerStatusDescr "senior" }
+ }
+ }
+ },
+ preferredLanguage "EN",
+ groupName "myGroup"
+ },
+ transportDocument {
+ {
+ ticket reservation : {
+ trainNum 12345,
+ trainIA5 "12345",
+ departureDate 2,
+ referenceIA5 "810123456789",
+ referenceNum 80123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ serviceBrand 12,
+ serviceBrandAbrUTF8 "TGV",
+ serviceBrandNameUTF8 "Lyria",
+ service couchette,
+ stationCodeTable stationUIC,
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ departureTime 1439,
+ departureUTCOffset -60,
+ arrivalDate 20,
+ arrivalTime 0,
+ arrivalUTCOffset 10,
+ carrierNum {1080, 1181},
+ carrierIA5 {"1080", "1181"},
+ classCode first,
+ serviceLevel "A",
+ places {
+ coach "31A",
+ placeString "31-47",
+ placeDescription "Window",
+ placeIA5 {"31A", "31B"},
+ placeNum {31, 32}
+ },
+ additionalPlaces {
+ coach "31A",
+ placeString "31-47",
+ placeDescription "Window",
+ placeIA5 {"31A", "31B"},
+ placeNum {31, 32}
+ },
+ bicyclePlaces {
+ coach "31A",
+ placeString "31-47",
+ placeDescription "Window",
+ placeIA5 {"31A", "31B"},
+ placeNum {31, 32}
+ },
+ compartmentDetails {
+ coachType 1,
+ compartmentType 99,
+ specialAllocation 50,
+ coachTypeDescr "xwz",
+ compartmentTypeDescr "xwz",
+ specialAllocationDescr "xwz",
+ position upperLevel
+ },
+ numberOfOverbooked 200,
+ berth {
+ {
+ berthType single,
+ numberOfBerths 999,
+ gender female
+ }
+ },
+ tariff {
+ {
+ numberOfPassengers 1,
+ passengerType senior,
+ ageBelow 64,
+ ageAbove 60,
+ travelerid { 1 },
+ restrictedToCountryOfResidence FALSE,
+ restrictedToRouteSection {
+ stationCodeTable stationERA,
+ fromStationNum 123,
+ fromStationIA5 "123",
+ toStationNum 234,
+ toStationIA5 "234",
+ fromStationNameUTF8 "A",
+ toStationNameUTF8 "B"
+ },
+ seriesDataDetails {
+ supplyingCarrier 12345,
+ offerIdentification 99,
+ series 23456
+ },
+ tariffIdNum 72,
+ tariffIdIA5 "72",
+ tariffDesc "Leasure Fare",
+ reductionCard {
+ {
+ cardIssuerNum 1234,
+ cardIssuerIA5 "1234",
+ cardIdNum 5678,
+ cardIdIA5 "5678",
+ cardName "testcard",
+ cardType 123,
+ leadingCardIdNum 3456,
+ leadingCardIdIA5 "3456",
+ trailingCardIdNum 100,
+ trailingCardIdIA5 "100"
+ }
+ }
+ }
+ },
+ priceType travelPrice,
+ price 12345,
+ vatDetail {
+ {
+ country 80,
+ percentage 70,
+ amount 10,
+ vatId "IUDGTE"
+ }
+ },
+ typeOfSupplement 9,
+ numberOfSupplements 2,
+ luggage {
+ maxHandLuggagePieces 2,
+ maxNonHandLuggagePieces 1,
+ registeredLuggage {
+ {
+ registrationId "IODHUV",
+ maxWeight 20,
+ maxSize 100
+ },
+ {
+ registrationId "XXDHUV",
+ maxWeight 21,
+ maxSize 101
+ }
+ }
+ },
+ infoText "reservation",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ token {
+ tokenProviderNum 123,
+ tokenProviderIA5 "VDV",
+ tokenSpecification "TEST",
+ token '82DA'H },
+ ticket carCarriageReservation : {
+ trainNum 123,
+ trainIA5 "123",
+ beginLoadingDate 10,
+ beginLoadingTime 0,
+ endLoadingTime 500,
+ loadingUTCOffset 30,
+ referenceIA5 "810123456789",
+ referenceNum 810123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ serviceBrand 100,
+ serviceBrandAbrUTF8 "AZ",
+ serviceBrandNameUTF8 "special train",
+ stationCodeTable stationERA,
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ coach "21",
+ place "41",
+ compartmentDetails {
+ coachType 1,
+ compartmentType 99,
+ specialAllocation 50,
+ coachTypeDescr "xwz",
+ compartmentTypeDescr "xwz",
+ specialAllocationDescr "xwz",
+ position upperLevel
+ },
+ numberPlate "AD-DE-123",
+ trailerPlate "DX-AB-123",
+ carCategory 3,
+ boatCategory 5,
+ textileRoof FALSE,
+ roofRackType bicycleRack,
+ roofRackHeight 20,
+ attachedBoats 2,
+ attachedBicycles 1,
+ attachedSurfboards 2,
+ loadingListEntry 421,
+ loadingDeck upper,
+ carrierNum { 1080, 1181 },
+ carrierIA5 { "1080", "1181" },
+ tariff {
+ numberOfPassengers 1,
+ restrictedToCountryOfResidence FALSE,
+ tariffIdNum 72,
+ tariffDesc "Large Car Full Fare"
+ },
+ priceType travelPrice,
+ price 12345,
+ vatDetail {
+ {
+ country 80,
+ percentage 70,
+ amount 10,
+ vatId "IUDGTE"
+ }
+ },
+ infoText "car carriage",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket openTicket : {
+ referenceNum 810123456789,
+ referenceIA5 "810123456789",
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ extIssuerId 12,
+ issuerAutorizationId 13,
+ returnIncluded FALSE,
+ stationCodeTable stationERA,
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ validRegionDesc "From A to B via C",
+ validRegion
+ {
+ viaStations {
+ route {
+ {
+ stationNum 123455,
+ stationIA5 "123455",
+ border FALSE
+ },
+ { stationNum 123456, border FALSE },
+ { alternativeRoutes {
+ { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE },
+ { route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE }
+ },
+ border FALSE
+ },
+ { stationNum 123457, border FALSE }
+ },
+ border FALSE,
+ seriesId 999,
+ routeId 21,
+ includedServiceBrands { 108, 118 },
+ excludedServiceBrands { 108, 118 }
+ },
+ zones {
+ carrierNum 1080,
+ carrierIA5 "1080",
+ stationCodeTable stationERA,
+ entryStationNum 1234,
+ entryStationIA5 "1234",
+ terminatingStationNum 2345,
+ terminatingStationIA5 "2345",
+ city 123456,
+ zoneId {100,200},
+ binaryZoneId '82DA'H,
+ nutsCode "DE4711"
+ },
+ lines {
+ carrierNum 1080,
+ carrierIA5 "1080",
+ lineId {100,200},
+ stationCodeTable stationERA,
+ entryStationNum 1234,
+ entryStationIA5 "1234",
+ terminatingStationNum 2345,
+ terminatingStationIA5 "2345",
+ city 123456
+ },
+ trainLink {
+ trainNum 12345,
+ trainIA5 "12345",
+ travelDate 2,
+ departureTime 1439,
+ departureUTCOffset -60,
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION"
+ },
+ polygone {
+ firstEdge {
+ longitude 12345,
+ latitude 56789
+ }
+ edges {
+ {longitude 12345, latitude 56789 },
+ {longitude 12345, latitude 56789 }
+ }
+ }
+ },
+ returnDescription {
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ validReturnRegionDesc "return",
+ validReturnRegion
+ {
+ zones {
+ carrierNum 1080,
+ carrierIA5 "1080",
+ stationCodeTable stationERA,
+ zoneId {100,200}
+ }
+ }
+ },
+ validFromDay 700,
+ validFromTime 0,
+ validFromUTCOffset 60,
+ validUntilDay 370,
+ validUntilTime 1439,
+ validUntilUTCOffset 10,
+ activatedDay { 1 , 2 },
+ classCode first
+ serviceLevel "A",
+ carrierNum { 1080, 1181 },
+ carrierIA5 { "1080", "1181" },
+ includedServiceBrands { 108, 118 },
+ excludedServiceBrands { 108, 118 },
+ tariffs {
+ {
+ numberOfPassengers 1,
+ restrictedToCountryOfResidence FALSE,
+ tariffIdNum 72,
+ tariffDesc "Large Car Full Fare"
+ }
+ },
+ price 12345,
+ vatDetail {{ country 80, percentage 70 }},
+ infoText "openTicketInfo"
+ includedAddOns {
+ {
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ externalIssuerId 12,
+ issuerAutorizationId 13,
+ stationCodeTable stationERA,
+ validRegion { zones { zoneId { 100 } } },
+ validFromDay 0,
+ validFromTime 1000,
+ validUntilDay 1,
+ validUntilTime 1000,
+ classCode second,
+ serviceLevel "A",
+ carrierNum { 1080, 1181 },
+ carrierIA5 { "1080", "1181" },
+ includedServiceBrands { 108, 118 },
+ excludedServiceBrands { 108, 118 },
+ tariffs {
+ {
+ numberOfPassengers 1,
+ restrictedToCountryOfResidence FALSE,
+ tariffIdNum 72,
+ tariffDesc "Large Car Full Fare"
+ }
+ },
+ infoText "included ticket",
+ includedTransportType { 10, 11 },
+ excludedTransportType { 10, 18 },
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ luggage { maxHandLuggagePieces 2, maxNonHandLuggagePieces 1},
+ includedTransportType { 10, 11 },
+ excludedTransportType { 10, 18 },
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket pass : {
+ referenceNum 810123456789,
+ referenceIA5 "810123456789",
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ passType 2,
+ passDescription "Eurail FlexPass",
+ classCode first,
+ validFromDay 0,
+ validFromTime 1000,
+ validFromUTCOffset 1,
+ validUntilDay 1,
+ validUntilTime 1000,
+ validUntilUTCOffset 1,
+ validityPeriodDetails {
+ validityPeriod {
+ {
+ validFromDay 0,
+ validFromTime 1000,
+ validFromUTCOffset 1,
+ validUntilDay 1,
+ validUntilTime 1000,
+ validUntilUTCOffset 1
+ }
+ },
+ excludedTimeRange {
+ {
+ fromTime 6,
+ untilTime 9
+ }
+ }
+ },
+ numberOfValidityDays 5,
+ numberOfPossibleTrips 3,
+ numberOfDaysOfTravel 10,
+ activatedDay {200, 201},
+ countries {10, 20},
+ includedCarrierNum { 1080, 1181 },
+ includedCarrierIA5 { "1080", "1181" },
+ excludedCarrierNum { 1080, 1181 },
+ excludedCarrierIA5 { "1080", "1181" },
+ includedServiceBrands { 108, 118 },
+ excludedServiceBrands { 108, 118 },
+ validRegion { zones { zoneId { 100 } } },
+ tariffs {
+ {
+ numberOfPassengers 1,
+ restrictedToCountryOfResidence FALSE,
+ tariffIdNum 72,
+ tariffDesc "Large Car Full Fare"
+ }
+ },
+ price 10000,
+ vatDetail {
+ { country 80,
+ percentage 70,
+ amount 10,
+ vatId "IUDGTE"
+ }
+ },
+ infoText "pass info",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket voucher : {
+ referenceIA5 "810123456789",
+ referenceNum 810123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "COFFEEMACHINE",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ validFromYear 2022,
+ validFromDay 1,
+ validUntilYear 2022,
+ validUntilDay 1,
+ value 500,
+ type 123,
+ infoText "coffee voucher",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket customerCard : {
+ customer {
+ customerIdIA5 "1234",
+ ticketHolder FALSE,
+ passengerType senior
+ },
+ cardIdIA5 "2345",
+ cardIdNum 123456,
+ validFromYear 2269,
+ validFromDay 2,
+ validUntilYear 1,
+ validUntilDay 5,
+ classCode second,
+ cardType 15,
+ cardTypeDescr "RAILPLUS",
+ customerStatus 1,
+ customerStatusDescr "gold",
+ includedServices { 1 , 2 },
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket counterMark : {
+ referenceIA5 "810123456789",
+ referenceNum 810123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ ticketReferenceIA5 "810123456789",
+ ticketReferenceNum 810123456789,
+ numberOfCountermark 12,
+ totalOfCountermarks 24,
+ groupName "groupName",
+ stationCodeTable stationERA,
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ validRegionDesc "From A to B via C",
+ validRegion {
+ viaStations {
+ route {
+ {
+ stationNum 123455,
+ stationIA5 "123455",
+ border FALSE
+ },
+ { stationNum 123456, border FALSE },
+ { alternativeRoutes {
+ { route { {stationNum 23455, border FALSE},{stationNum 23456, border FALSE }}, border FALSE },
+ { route { {stationNum 3455, border FALSE },{stationNum 3456, border FALSE }}, border FALSE }
+ },
+ border FALSE
+ },
+ { stationNum 123457, border FALSE }
+ },
+ border FALSE,
+ carrierNum { 1080, 1181 },
+ carrierIA5 { "1080", "1181" },
+ seriesId 999,
+ routeId 21
+ }
+ },
+ returnIncluded FALSE,
+ returnDescription {
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ validReturnRegionDesc "return",
+ validReturnRegion {
+ zones {
+ carrierNum 1080,
+ carrierIA5 "1181",
+ stationCodeTable stationERA,
+ zoneId {100,200}
+ }
+ }
+ },
+ validFromDay 700,
+ validFromTime 0,
+ validFromUTCOffset 60,
+ validUntilDay 370,
+ validUntilTime 1439,
+ validUntilUTCOffset 10,
+ classCode first
+ carrierNum { 1080, 1181 },
+ carrierIA5 { "1080", "1181" },
+ includedServiceBrands { 108, 118 },
+ excludedServiceBrands { 108, 118 },
+ infoText "counterMark",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket parkingGround : {
+ referenceIA5 "810123456789",
+ referenceNum 810123456789,
+ parkingGroundId "IA5",
+ fromParkingDate 370,
+ untilParkingDate 370,
+
+
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ accessCode "4ga"
+ location "Parking Frankfurt Main West",
+ stationCodeTable stationUIC,
+ stationNum 8000001,
+ stationIA5 "8000001",
+ specialInformation "outdoor parking",
+ entryTrack "left",
+ numberPlate "AA-DE-12345",
+ price 500,
+ vatDetail {
+ { country 80,
+ percentage 70,
+ amount 10,
+ vatId "IUDGTE"
+ }
+ },
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket fipTicket : {
+ referenceIA5 "810123456789",
+ referenceNum 810123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ validFromDay -367,
+ validUntilDay -1,
+ activatedDay {1,13,14,15},
+ carrierNum { 1080, 1181 },
+ carrierIA5 { "1080", "1181" },
+ numberOfTravelDays 8,
+ includesSupplements TRUE,
+ classCode first,
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket stationPassage : {
+ referenceIA5 "810123456789",
+ referenceNum 810123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ productName "passage",
+ stationCodeTable stationUIC,
+ stationNum {8200001},
+ stationIA5 {"AMS"},
+ stationNameUTF8 {"Amsterdam"},
+ areaCodeNum {8200001},
+ areaCodeIA5 {"AMS"},
+ areaNameUTF8 {"Amsterdam"},
+ validFromDay 5,
+ validFromTime 0,
+ validFromUTCOffset 1,
+ validUntilDay 5,
+ validUntilTime 1000,
+ validUntilUTCOffset 1,
+ numberOfDaysValid 5
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ },
+ {
+ ticket extension : {
+ extensionId "1",
+ extensionData '82DA'H
+ }
+ },
+ {
+ ticket delayConfirmation : {
+ referenceIA5 "ABDJ12345",
+ referenceNum 12345,
+ trainNum 100,
+ trainIA5 "100",
+ departureYear 2022,
+ departureDay 12,
+ departureTime 1000,
+ departureUTCOffset 30,
+ stationCodeTable stationUIC,
+ stationNum 8000001,
+ stationIA5 "DJE"
+ delay 31,
+ trainCancelled FALSE,
+ confirmationType travelerDelayConfirmation,
+ affectedTickets {
+ {
+ referenceIA5 "KDJET",
+ referenceNum 801234567890,
+ issuerName "XYZ",
+ issuerPNR "LDWDUR45",
+ productOwnerNum 1080,
+ productOwnerIA5 "IEFHU",
+ ticketType openTicket,
+ linkMode issuedTogether
+ }
+ },
+ infoText "delay confirmation",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ }
+ },
+ controlDetail {
+ identificationByCardReference {
+ {
+ cardIssuerNum 1234,
+ cardIssuerIA5 "1234",
+ cardIdNum 5678,
+ cardIdIA5 "5678",
+ cardName "testcard",
+ cardType 123,
+ leadingCardIdNum 3456,
+ leadingCardIdIA5 "3456",
+ trailingCardIdNum 100,
+ trailingCardIdIA5 "100"
+ }
+ },
+ identificationByIdCard FALSE,
+ identificationByPassportId FALSE
+ identificationItem 12,
+ passportValidationRequired FALSE,
+ onlineValidationRequired FALSE,
+ randomDetailedValidationRequired 50,
+ ageCheckRequired FALSE ,
+ reductionCardCheckRequired FALSE,
+ infoText "control",
+ includedTickets {
+ {
+ referenceIA5 "KDJET",
+ referenceNum 801234567890,
+ issuerName "XYZ",
+ issuerPNR "LDWDUR45",
+ productOwnerNum 1080,
+ productOwnerIA5 "IEFHU",
+ ticketType openTicket,
+ linkMode issuedTogether
+ }
+ },
+ extension {extensionId "1", extensionData '82DA'H}
+ },
+ extension {
+ { extensionId "1", extensionData '82DA'H },
+ { extensionId "2", extensionData '83DA'H }
+ }
+ } \ No newline at end of file
diff --git a/misc/uicRailTicketData_v1.3.1_a.data b/misc/uicRailTicketData_v1.3.1_a.data
new file mode 100644
index 0000000..49729eb
--- /dev/null
+++ b/misc/uicRailTicketData_v1.3.1_a.data
@@ -0,0 +1,245 @@
+value UicRailTicketData ::= {
+ issuingDetail {
+ securityProviderNum 1,
+ securityProviderIA5 "1",
+ issuerNum 32000,
+ issuerIA5 "1",
+ issuingYear 2018,
+ issuingDay 1,
+ issuingTime 600,
+ issuerName "name",
+ specimen TRUE,
+ securePaperTicket FALSE,
+ activated TRUE,
+ currency "SRF",
+ currencyFract 3,
+ issuerPNR "issuerTestPNR",
+ extension { extensionId "1", extensionData '82DA'H },
+ issuedOnTrainNum 123,
+ issuedOnTrainIA5 "123",
+ issuedOnLine 12,
+ pointOfSale {
+ geoUnit microDegree,
+ coordinateSystem wgs84
+ hemisphereLongitude north,
+ hemisphereLatitude east,
+ longitude 12345,
+ latitude 56789,
+ accuracy microDegree
+ }
+ },
+ travelerDetail{
+ traveler {
+ {
+ firstName "John",
+ secondName "Little",
+ lastName "Dow",
+ idCard "12345",
+ passportId "JDTS",
+ title "PhD",
+ gender male,
+ customerIdIA5 "DZE5gT",
+ customerIdNum 12345,
+ yearOfBirth 1901,
+ dayOfBirth 331,
+ ticketHolder TRUE,
+ passengerType senior,
+ passengerWithReducedMobility FALSE,
+ countryOfResidence 101,
+ countryOfPassport 102,
+ countryOfIdCard 103,
+ status {
+ {customerStatus 1, customerStatusDescr "senior" }
+ }
+ }
+ },
+ preferredLanguage "EN",
+ groupName "myGroup"
+ },
+ transportDocument {
+ {
+ ticket reservation : {
+ trainNum 12345,
+ trainIA5 "12345",
+ departureDate 2,
+ referenceIA5 "810123456789",
+ referenceNum 80123456789,
+ productOwnerNum 23456,
+ productOwnerIA5 "23456",
+ productIdNum 32000,
+ productIdIA5 "123456",
+ serviceBrand 12,
+ serviceBrandAbrUTF8 "TGV",
+ serviceBrandNameUTF8 "Lyria",
+ service couchette,
+ stationCodeTable stationUIC,
+ fromStationNum 8100001,
+ fromStationIA5 "8100001",
+ toStationNum 8000002,
+ toStationIA5 "8100002",
+ fromStationNameUTF8 "A-STATION",
+ toStationNameUTF8 "B-STATION",
+ departureTime 1439,
+ departureUTCOffset -60,
+ arrivalDate 20,
+ arrivalTime 0,
+ arrivalUTCOffset 10,
+ carrierNum {1080, 1181},
+ carrierIA5 {"1080", "1181"},
+ classCode first,
+ serviceLevel "A",
+ places {
+ coach "31A",
+ placeString "31-47",
+ placeDescription "Window",
+ placeIA5 {"31A", "31B"},
+ placeNum {31, 32}
+ },
+ additionalPlaces {
+ coach "31A",
+ placeString "31-47",
+ placeDescription "Window",
+ placeIA5 {"31A", "31B"},
+ placeNum {31, 32}
+ },
+ bicyclePlaces {
+ coach "31A",
+ placeString "31-47",
+ placeDescription "Window",
+ placeIA5 {"31A", "31B"},
+ placeNum {31, 32}
+ },
+ compartmentDetails {
+ coachType 1,
+ compartmentType 99,
+ specialAllocation 50,
+ coachTypeDescr "xwz",
+ compartmentTypeDescr "xwz",
+ specialAllocationDescr "xwz",
+ position upperLevel
+ },
+ numberOfOverbooked 200,
+ berth {
+ {
+ berthType single,
+ numberOfBerths 999,
+ gender female
+ }
+ },
+ tariff {
+ {
+ numberOfPassengers 1,
+ passengerType senior,
+ ageBelow 64,
+ ageAbove 60,
+ travelerid { 1 },
+ restrictedToCountryOfResidence FALSE,
+ restrictedToRouteSection {
+ stationCodeTable stationERA,
+ fromStationNum 123,
+ fromStationIA5 "123",
+ toStationNum 234,
+ toStationIA5 "234",
+ fromStationNameUTF8 "A",
+ toStationNameUTF8 "B"
+ },
+ seriesDataDetails {
+ supplyingCarrier 12345,
+ offerIdentification 99,
+ series 23456
+ },
+ tariffIdNum 72,
+ tariffIdIA5 "72",
+ tariffDesc "Leasure Fare",
+ reductionCard {
+ {
+ cardIssuerNum 1234,
+ cardIssuerIA5 "1234",
+ cardIdNum 5678,
+ cardIdIA5 "5678",
+ cardName "testcard",
+ cardType 123,
+ leadingCardIdNum 3456,
+ leadingCardIdIA5 "3456",
+ trailingCardIdNum 100,
+ trailingCardIdIA5 "100"
+ }
+ }
+ }
+ },
+ priceType travelPrice,
+ price 12345,
+ vatDetail {
+ {
+ country 80,
+ percentage 70,
+ amount 10,
+ vatId "IUDGTE"
+ }
+ },
+ typeOfSupplement 9,
+ numberOfSupplements 2,
+ luggage {
+ maxHandLuggagePieces 2,
+ maxNonHandLuggagePieces 1,
+ registeredLuggage {
+ {
+ registrationId "IODHUV",
+ maxWeight 20,
+ maxSize 100
+ },
+ {
+ registrationId "XXDHUV",
+ maxWeight 21,
+ maxSize 101
+ }
+ }
+ },
+ infoText "reservation",
+ extension {extensionId "1", extensionData '82DA'H}
+ }
+ }
+ },
+ controlDetail {
+ identificationByCardReference {
+ {
+ cardIssuerNum 1234,
+ cardIssuerIA5 "1234",
+ cardIdNum 5678,
+ cardIdIA5 "5678",
+ cardName "testcard",
+ cardType 123,
+ leadingCardIdNum 3456,
+ leadingCardIdIA5 "3456",
+ trailingCardIdNum 100,
+ trailingCardIdIA5 "100"
+ }
+ },
+ identificationByIdCard FALSE,
+ identificationByPassportId FALSE
+ identificationItem 12,
+ passportValidationRequired FALSE,
+ onlineValidationRequired FALSE,
+ randomDetailedValidationRequired 50,
+ ageCheckRequired FALSE ,
+ reductionCardCheckRequired FALSE,
+ infoText "control",
+ includedTickets {
+ {
+ referenceIA5 "KDJET",
+ referenceNum 801234567890,
+ issuerName "XYZ",
+ issuerPNR "LDWDUR45",
+ productOwnerNum 1080,
+ productOwnerIA5 "IEFHU",
+ ticketType openTicket,
+ linkMode issuedTogether
+ }
+ },
+ extension {extensionId "1", extensionData '82DA'H}
+ },
+ extension {
+ { extensionId "1", extensionData '82DA'H },
+ { extensionId "2", extensionData '83DA'H }
+ }
+ } \ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 033cd38..d4ef4cc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.uic.barcode</groupId>
<artifactId>org.uic.barcode</artifactId>
- <version>1.2.13-SNAPSHOT</version>
+ <version>1.3.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>UIC barcode</name>
<description>encoding and decoding of bar code content according to UIC IRS 90918-9</description>
diff --git a/src/main/java/org/uic/barcode/Decoder.java b/src/main/java/org/uic/barcode/Decoder.java
index 4c8b044..b980f19 100644
--- a/src/main/java/org/uic/barcode/Decoder.java
+++ b/src/main/java/org/uic/barcode/Decoder.java
@@ -10,11 +10,11 @@ import java.util.zip.DataFormatException;
import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
-import org.uic.barcode.dynamicFrame.Level1DataType;
-import org.uic.barcode.dynamicFrame.Level2DataType;
-import org.uic.barcode.dynamicFrame.SequenceOfDataType;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.ILevel2Data;
+import org.uic.barcode.dynamicFrame.api.SimpleDynamicFrame;
import org.uic.barcode.staticFrame.StaticFrame;
import org.uic.barcode.staticFrame.UFLEXDataRecord;
import org.uic.barcode.staticFrame.UTLAYDataRecord;
@@ -34,7 +34,7 @@ public class Decoder {
/** The dynamic frame. */
- private DynamicFrame dynamicFrame = null;
+ private IDynamicFrame dynamicFrame = null;
/** The static frame. */
private StaticFrame staticFrame = null;
@@ -123,8 +123,9 @@ public class Decoder {
* Validate level 2.
*
* @return the return code indicating errors
+ * @throws EncodingFormatException
*/
- public int validateLevel2() {
+ public int validateLevel2() throws EncodingFormatException {
if (!isStaticHeader(data)) {
return dynamicFrame.validateLevel2() ;
} else {
@@ -137,7 +138,7 @@ public class Decoder {
* @param prov - provider of the java security implementation in case a dedicated provider must be used
* @return the return code indicating errors
*/
- public int validateLevel2(Provider prov) {
+ public int validateLevel2(Provider prov) throws EncodingFormatException {
if (!isStaticHeader(data)) {
return dynamicFrame.validateLevel2(prov) ;
} else {
@@ -157,24 +158,25 @@ public class Decoder {
public void decode(byte[] data) throws IOException, EncodingFormatException, DataFormatException {
if (!isStaticHeader(data)) {
+
+ dynamicFrame = new SimpleDynamicFrame();
- dynamicFrame = DynamicFrame.decode(data);
+ dynamicFrame.decode(data);
- Level2DataType level2 = dynamicFrame.getLevel2SignedData();
+ ILevel2Data level2 = dynamicFrame.getLevel2Data();
- Level1DataType level1 = level2.getLevel1Data();
+ ILevel1Data level1 = level2.getLevel1Data();
- SequenceOfDataType dataList = level1.getData();
- for (DataType level1Content : dataList) {
+ for (IData level1Content : level1.getData()) {
uicTicketCoder = new UicRailTicketCoder();
if (level1Content.getFormat().equals("FCB1")) {
- uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 1);
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 1);
} else if (level1Content.getFormat().equals("FCB2")) {
- uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 2);
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 2);
} else if (level1Content.getFormat().equals("FCB3")) {
- uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getByteData(), 3);
+ uicTicket = uicTicketCoder.decodeFromAsn(level1Content.getData(), 3);
}
}
@@ -234,7 +236,7 @@ public class Decoder {
*
* @return the dynamic header
*/
- public DynamicFrame getDynamicHeader() {
+ public IDynamicFrame getDynamicHeader() {
return dynamicFrame;
}
@@ -254,7 +256,7 @@ public class Decoder {
*
* @param dynamicHeader the new dynamic header
*/
- public void setDynamicHeader(DynamicFrame dynamicHeader) {
+ public void setDynamicHeader(IDynamicFrame dynamicHeader) {
this.dynamicFrame = dynamicHeader;
}
@@ -276,9 +278,9 @@ public class Decoder {
this.staticFrame = staticFrame;
}
- public DataType getLevel2Data() {
- if (!isStaticHeader(data) && dynamicFrame.getLevel2SignedData() != null) {
- return dynamicFrame.getLevel2SignedData().getLevel2Data();
+ public IData getLevel2Data() {
+ if (!isStaticHeader(data) && dynamicFrame.getLevel2Data() != null) {
+ return dynamicFrame.getLevel2Data().getLevel2Data();
}
return null;
}
diff --git a/src/main/java/org/uic/barcode/Encoder.java b/src/main/java/org/uic/barcode/Encoder.java
index 3b30e8a..5f10806 100644
--- a/src/main/java/org/uic/barcode/Encoder.java
+++ b/src/main/java/org/uic/barcode/Encoder.java
@@ -5,15 +5,15 @@ import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
-import org.uic.barcode.asn1.datatypesimpl.OctetString;
import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
-import org.uic.barcode.dynamicFrame.Level1DataType;
-import org.uic.barcode.dynamicFrame.Level2DataType;
-import org.uic.barcode.dynamicFrame.SequenceOfDataType;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.api.SimpleDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel2Data;
import org.uic.barcode.staticFrame.StaticFrame;
import org.uic.barcode.staticFrame.UFLEXDataRecord;
import org.uic.barcode.staticFrame.UHEADDataRecord;
@@ -34,7 +34,7 @@ import org.uic.barcode.ticket.api.spec.IUicRailTicket;
public class Encoder {
/** The dynamic frame. */
- private DynamicFrame dynamicFrame = null;
+ private IDynamicFrame dynamicFrame = null;
/** The static frame. */
private StaticFrame staticFrame = null;
@@ -87,18 +87,19 @@ public class Encoder {
} else if (barcodeType == UIC_BARCODE_TYPE_DOSIPAS) {
- dynamicFrame = new DynamicFrame();
- dynamicFrame.setLevel2SignedData(new Level2DataType());
- dynamicFrame.getLevel2SignedData().setLevel1Data(new Level1DataType());
- dynamicFrame.getLevel2SignedData().getLevel1Data().setData(new SequenceOfDataType());
+ dynamicFrame = new SimpleDynamicFrame();
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
+ dynamicFrame.getLevel2Data().setLevel1Data(new SimpleLevel1Data());
if (ticket != null) {
if (version == 1) {
- dynamicFrame.setFormat("U1");
- }
+ dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1);
+ } else if (version == 2) {
+ dynamicFrame.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2);
+ }
- DataType ticketData = new DataType();
+ IData ticketData = new SimpleData();
UicRailTicketCoder uicTicketCoder = new UicRailTicketCoder();
if (fcbVersion == 1 || fcbVersion == 13) {
@@ -108,8 +109,8 @@ public class Encoder {
} else if (fcbVersion == 3) {
ticketData.setFormat(Constants.DATA_TYPE_FCB_VERSION_3);
}
- ticketData.setData(new OctetString(uicTicketCoder.encode(ticket, fcbVersion)));
- dynamicFrame.getLevel2SignedData().getLevel1Data().getData().add(ticketData);
+ ticketData.setData(uicTicketCoder.encode(ticket, fcbVersion));
+ dynamicFrame.getLevel2Data().getLevel1Data().addData(ticketData);
}
}
@@ -151,8 +152,8 @@ public class Encoder {
*/
public void setLevel1Algs(String level1SigningAlg, String level1KeyAlg) {
if (dynamicFrame != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1SigningAlg(level1SigningAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1KeyAlg(level1KeyAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(level1SigningAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1KeyAlg(level1KeyAlg);
}
}
@@ -165,68 +166,62 @@ public class Encoder {
*/
public void setLevel2Algs(String level2SigningAlg, String level2KeyAlg, PublicKey publicKey) {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
- if (dynamicFrame.getLevel2SignedData().getLevel1Data() == null) {
- dynamicFrame.getLevel2SignedData().setLevel1Data(new Level1DataType());
+ if (dynamicFrame.getLevel2Data().getLevel1Data() == null) {
+ dynamicFrame.getLevel2Data().setLevel1Data(new SimpleLevel1Data());
}
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel2SigningAlg(level2SigningAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel2KeyAlg(level2KeyAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel2SigningAlg(level2SigningAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel2KeyAlg(level2KeyAlg);
if (publicKey != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel2publicKey(new OctetString(publicKey.getEncoded()));
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel2publicKey(publicKey.getEncoded());
}
}
}
public void setDynamicData(IUicDynamicContent content) throws EncodingFormatException {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
dynamicFrame.addDynamicContent(content);
}
}
- public void setLevel2Data(DataType level2data) {
+ public void setLevel2Data(IData level2data) {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
- dynamicFrame.getLevel2SignedData().setLevel2Data(level2data);
+ dynamicFrame.getLevel2Data().setLevel2Data(level2data);
}
}
public void setDynamicContentDataUIC1(UicDynamicContentDataFDC1 dcd) {
if (dynamicFrame != null) {
- if (dynamicFrame.getLevel2SignedData() == null) {
- dynamicFrame.setLevel2SignedData(new Level2DataType());
+ if (dynamicFrame.getLevel2Data() == null) {
+ dynamicFrame.setLevel2Data(new SimpleLevel2Data());
}
- dynamicFrame.getLevel2SignedData().setLevel2Data(dcd.getDataType());
+ dynamicFrame.getLevel2Data().setLevel2Data(dcd.getApiDataType());
}
}
- public DataType getLevel2Data() {
- if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) {
- return dynamicFrame.getLevel2SignedData().getLevel2Data();
+ public IData getLevel2Data() {
+ if (dynamicFrame != null && dynamicFrame.getLevel2Data() != null) {
+ return dynamicFrame.getLevel2Data().getLevel2Data();
}
return null;
}
public IUicDynamicContent getDynamicContent() {
- if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) {
+ if (dynamicFrame != null && dynamicFrame.getLevel2Data() != null) {
return dynamicFrame.getDynamicContent();
}
return null;
}
- public UicDynamicContentDataFDC1 getDynamicContentDataUIC1() {
- if (dynamicFrame != null && dynamicFrame.getLevel2SignedData() != null) {
- return dynamicFrame.getDynamicDataFDC1();
- }
- return null;
- }
/**
@@ -240,10 +235,10 @@ public class Encoder {
*/
public void signLevel1(String securityProvider,PrivateKey key,String signingAlg, String keyId) throws Exception {
if (dynamicFrame != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setSecurityProvider(securityProvider);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1SigningAlg(signingAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setKeyId(Long.parseLong(keyId));
- dynamicFrame.getLevel2SignedData().signLevel1(key);
+ dynamicFrame.getLevel2Data().getLevel1Data().setSecurityProvider(securityProvider);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(signingAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setKeyId(Long.parseLong(keyId));
+ dynamicFrame.signLevel1(key);
} else if (staticFrame != null) {
staticFrame.setSignatureKey(keyId);
staticFrame.setSecurityProvider(securityProvider);
@@ -266,10 +261,11 @@ public class Encoder {
*/
public void signLevel1(String securityProvider,PrivateKey key,String signingAlg, String keyId, Provider prov) throws Exception {
if (dynamicFrame != null) {
- dynamicFrame.getLevel2SignedData().getLevel1Data().setSecurityProvider(securityProvider);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setLevel1SigningAlg(signingAlg);
- dynamicFrame.getLevel2SignedData().getLevel1Data().setKeyId(Long.parseLong(keyId));
- dynamicFrame.getLevel2SignedData().signLevel1(key, prov);
+ dynamicFrame.getLevel2Data().getLevel1Data().setSecurityProvider(securityProvider);
+ dynamicFrame.getLevel2Data().getLevel1Data().setLevel1SigningAlg(signingAlg);
+ dynamicFrame.getLevel2Data().getLevel1Data().setKeyId(Long.parseLong(keyId));
+ dynamicFrame.signLevel1(key,prov);
+ //dynamicFrame.getLevel2Data().signLevel1(key, prov);
} else if (staticFrame != null) {
staticFrame.setSignatureKey(keyId);
staticFrame.setSecurityProvider(securityProvider);
@@ -299,7 +295,7 @@ public class Encoder {
*
* @return the dynamic frame
*/
- public DynamicFrame getDynamicFrame() {
+ public IDynamicFrame getDynamicFrame() {
return dynamicFrame;
}
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
index a1b9581..c2cd8fa 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/TimeStamp.java
@@ -105,17 +105,18 @@ public class TimeStamp {
int dayOfYear = now.getDayOfYear();
if (dayOfYear - day.intValue() > 250) {
- now = now.plusDays(1);
+ now = now.plusYears(1);
}
if (day.intValue() - dayOfYear > 250) {
- now = now.minusDays(1);
+ now = now.minusYears(1);
}
now = now.withDayOfYear(1);
now = now.withSecond(0);
now = now.withHour(0);
now = now.withMinute(0);
- now = now.withDayOfYear(dayOfYear);
+ now = now.withNano(0);
+ now = now.withDayOfYear(day.intValue());
now = now.plusSeconds(secondOfDay);
return Date.from(now.toInstant());
diff --git a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
index 3ced173..9957ede 100644
--- a/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
+++ b/src/main/java/org/uic/barcode/dynamicContent/fdc1/UicDynamicContentDataFDC1.java
@@ -11,7 +11,9 @@ import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.uper.UperEncoder;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.v1.DataType;
/**
@@ -94,6 +96,14 @@ public class UicDynamicContentDataFDC1 {
return "FDC1";
}
+ public IData getApiDataType() {
+ IData data = new SimpleData();
+ data.setFormat(getFormat());
+ data.setData(UperEncoder.encode(this));
+ return data;
+ }
+
+
public DataType getDataType() {
DataType data = new DataType();
data.setFormat(getFormat());
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
index 8f47986..ba15f3f 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/Constants.java
@@ -36,4 +36,6 @@ public class Constants {
public static int LEVEL1_VALIDATION_KEY_ALG_NOT_IMPLEMENTED = 5;
public static int LEVEL1_VALIDATION_ENCODING_ERROR = 6;
+ public static String DYNAMIC_BARCODE_FORMAT_VERSION_1 = "U1";
+ public static String DYNAMIC_BARCODE_FORMAT_VERSION_2 = "U2";
}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/IData.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IData.java
new file mode 100644
index 0000000..51f9c7b
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IData.java
@@ -0,0 +1,39 @@
+package org.uic.barcode.dynamicFrame.api;
+
+/**
+ * The Class DataType.
+ */
+public interface IData {
+
+
+
+
+ /**
+ * Gets the data format.
+ *
+ * @return the data format
+ */
+ public String getFormat();
+
+ /**
+ * Sets the data format.
+ *
+ * @param dataFormat the new data format
+ */
+ public void setFormat(String format);
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public byte[] getData();
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(byte[] data);
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java
new file mode 100644
index 0000000..f357c4d
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/IDynamicFrame.java
@@ -0,0 +1,202 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.ticket.EncodingFormatException;
+
+
+/**
+ * The DynamicHeader for bar codes
+ *
+ */
+public interface IDynamicFrame{
+
+
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ public String getFormat();
+
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ public void setFormat(String format);
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ public ILevel2Data getLevel2Data();
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2SignedData the new level 2 signed data
+ */
+ public void setLevel2Data(ILevel2Data level2Data);
+
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ public byte[] getLevel2Signature();
+
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ public void setLevel2Signature(byte[] level2Signature);
+
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ * @throws EncodingFormatException
+ */
+ public byte[] encode() throws EncodingFormatException;
+
+ /**
+ * Decode.
+ *
+ * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
+ *
+ * @param bytes the bytes
+ * @return the dynamic header
+ */
+ public void decode(byte[] bytes);
+
+
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ public int validateLevel2() 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
+ * @throws EncodingFormatException
+ */
+ public int validateLevel2(Provider prov) throws EncodingFormatException;
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param prov the prov
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ public int validateLevel1(PublicKey key, Provider prov) 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
+ * @throws EncodingFormatException
+ */
+ public int validateLevel1(PublicKey key) throws EncodingFormatException;
+
+ /**
+ * Sign level 2 data without a specific security provider.
+ *
+ * @param key the key
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key) throws Exception;
+
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the security Provider
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key, Provider prov) throws Exception;
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException;
+
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData);
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ public IUicDynamicContent getDynamicContent();
+
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @return
+ * @return the byte[]
+ * @throws Exception
+ */
+ public void signLevel1(PrivateKey key) throws Exception;
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param security provider - security provider that must be sued to create the signature
+ * @return
+ * @return the byte[]
+ * @throws Exception
+ */
+ public void signLevel1(PrivateKey key, Provider prov) throws Exception;
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java
new file mode 100644
index 0000000..206d613
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel1Data.java
@@ -0,0 +1,164 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.util.Collection;
+import java.util.Date;
+
+/**
+ * The Class SignedDataType.
+ */
+public interface ILevel1Data {
+
+
+
+ /**
+ * Sets the security provider
+ *
+ * @param securityProviderNum the new security provider
+ */
+ public void setSecurityProvider(String securityProvider);
+
+
+ /**
+ * Gets the security provider
+ *
+ * @return the security provider
+ */
+ public String getSecurityProvider();
+
+
+
+
+
+
+ /**
+ * Gets the key id.
+ *
+ * @return the key id
+ */
+ public Long getKeyId();
+
+
+ /**
+ * Sets the key id.
+ *
+ * @param keyId the new key id
+ */
+ public void setKeyId(Long keyId);
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public Collection<IData> getData();
+
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(Collection<IData> data);
+
+ /**
+ * Adds data.
+ *
+ * @param data the new data
+ */
+ public void addData(IData data);
+
+ /**
+ * Gets the level 2 key alg.
+ *
+ * @return the level 2 key alg
+ */
+ public String getLevel2KeyAlg();
+
+
+ /**
+ * Sets the level 2 key alg.
+ *
+ * @param level2KeyAlg the new level 2 key alg
+ */
+ public void setLevel2KeyAlg(String level2KeyAlg);
+
+
+ /**
+ * Gets the level 1 signing alg.
+ *
+ * @return the level 1 signing alg
+ */
+ public String getLevel1SigningAlg();
+
+
+ /**
+ * Sets the level 1 signing alg.
+ *
+ * @param level1SigningAlg the new level 1 signing alg
+ */
+ public void setLevel1SigningAlg(String level1SigningAlg);
+
+
+ /**
+ * Gets the level 2 signing alg.
+ *
+ * @return the level 2 signing alg
+ */
+ public String getLevel2SigningAlg();
+
+
+ /**
+ * Sets the level 2 signing alg.
+ *
+ * @param level2SigningAlg the new level 2 signing alg
+ */
+ public void setLevel2SigningAlg(String level2SigningAlg);
+
+
+ /**
+ * Gets the level 2 public key.
+ *
+ * @return the level 2 public key
+ */
+ public byte[] getLevel2publicKey();
+
+
+ /**
+ * Sets the level 2 public key.
+ *
+ * @param level2publicKey the new level 2 public key
+ */
+ public void setLevel2publicKey(byte[] level2publicKey);
+
+
+
+ /**
+ * Gets the level 1 key alg.
+ *
+ * @return the level 1 key alg
+ */
+ public String getLevel1KeyAlg();
+
+ /**
+ * Sets the level 1 key alg.
+ *
+ * @param level1KeyAlg the new level 1 key alg
+ */
+ public void setLevel1KeyAlg(String level1KeyAlg);
+
+
+ /**
+ * Sets the end of validity date. The validity date has to be provided in UTC.
+ *
+ * @param date the new end of validity date
+ */
+ public void setEndOfBarcodeValidity(Date date);
+
+
+ /**
+ * Gets the end of validity date.
+ *
+ * @return the end of validity date
+ */
+ public Date getEndOfBarcodeValidity();
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java
new file mode 100644
index 0000000..cc28422
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/ILevel2Data.java
@@ -0,0 +1,25 @@
+package org.uic.barcode.dynamicFrame.api;
+
+/**
+ * The Level 2 data.
+ */
+
+public interface ILevel2Data {
+
+
+
+ public ILevel1Data getLevel1Data();
+
+ public void setLevel1Data(ILevel1Data level1Data);
+
+ public byte[] getLevel1Signature();
+
+ public byte[] getLevel1SignatureBytes();
+
+ public void setLevel1Signature(byte[] level1Signature);
+
+ public IData getLevel2Data();
+
+ public void setLevel2Data(IData level2Data);
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java
new file mode 100644
index 0000000..cb762de
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleData.java
@@ -0,0 +1,59 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class DataType.
+ */
+public class SimpleData implements IData{
+
+
+ /** The data format.
+ *
+ * -- FCB1 FCB version 1
+ * -- FCB2 FCB version 2
+ * -- RICS company code + ...
+ **/
+ public String format;
+
+ /** The data. */
+ public byte[] data;
+
+ /**
+ * Gets the data format.
+ *
+ * @return the data format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the data format.
+ *
+ * @param dataFormat the new data format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public byte[] getData() {
+ return data;
+ }
+
+ @Override
+ public void setData(byte[] data) {
+ this.data = data;
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java
new file mode 100644
index 0000000..4c5c879
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleDynamicFrame.java
@@ -0,0 +1,553 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Date;
+
+import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrameCoderV1;
+import org.uic.barcode.dynamicFrame.v2.DynamicFrameCoderV2;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.utils.AlgorithmNameResolver;
+
+
+
+/**
+ * The DynamicHeader for bar codes
+ *
+ */
+public class SimpleDynamicFrame implements IDynamicFrame {
+
+ /**
+ * Instantiates a new dynamic frame.
+ */
+ public SimpleDynamicFrame() {}
+
+ public SimpleDynamicFrame(String format) {
+ this.format = format;
+ }
+
+ /** The format. */
+ public String format = Constants.DYNAMIC_BARCODE_FORMAT_DEFAULT;
+
+ /** The level 2 signed data. */
+ /*level 2 data*/
+ public ILevel2Data level2Data;
+
+
+ /** The signature of level 2 data. */
+ public byte[] level2Signature;
+
+ public Date endOfValidity = null;
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ public ILevel2Data getLevel2Data() {
+ return level2Data;
+ }
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2SignedData the new level 2 signed data
+ */
+ public void setLevel2Data(ILevel2Data level2SignedData) {
+ this.level2Data = level2SignedData;
+ }
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ public byte[] getLevel2Signature() {
+ return level2Signature;
+ }
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ public void setLevel2Signature(byte[] level2Signature) {
+ this.level2Signature = level2Signature;
+ }
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ * @throws EncodingFormatException
+ */
+ public byte[] encode() throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV1.encode(this);
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV2.encode(this);
+
+ }
+
+ return null;
+ }
+
+ private byte[] encode(ILevel1Data level1Data) throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV1.encode(level1Data);
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV2.encode(level1Data);
+
+ }
+
+ return null;
+ }
+
+ private byte[] encode(ILevel2Data level2SignedData2) throws EncodingFormatException {
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV1.encode(level2SignedData2);
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ return DynamicFrameCoderV2.encode(level2SignedData2);
+
+ }
+
+ return null;
+ }
+
+ /**
+ * Decode.
+ *
+ * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
+ *
+ * @param bytes the bytes
+ * @return the dynamic header
+ */
+ public void decode(byte[] bytes) {
+
+ String format = getFormat(bytes);
+
+ if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1.equals(format)) {
+
+ DynamicFrameCoderV1.decode(this,bytes);
+
+ } else if (Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2.equals(format)) {
+
+ DynamicFrameCoderV2.decode(this,bytes);
+
+ }
+
+
+
+ }
+
+
+
+
+ /**
+ * Checks if is static header.
+ *
+ * @param data the data
+ * @return true, if is static header
+ */
+ private static String getFormat(byte[] data) {
+ byte[] start = "U1".getBytes();
+ if (start[0] != data[0] || start[1]!= start[1]) {
+ return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_1;
+ }
+ start = "U2".getBytes();
+ if (start[0] != data[0] || start[1]!= start[1]) {
+ return Constants.DYNAMIC_BARCODE_FORMAT_VERSION_2;
+ }
+ return null;
+ }
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ public int validateLevel2() throws EncodingFormatException {
+
+ return validateLevel2(null);
+
+ }
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param prov the prov
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ public int validateLevel2(Provider prov) throws EncodingFormatException {
+
+
+ String level2KeyAlg = this.getLevel2Data().getLevel1Data().getLevel2KeyAlg();
+
+
+ if (level2KeyAlg == null || level2KeyAlg.length() == 0) {
+ return Constants.LEVEL2_VALIDATION_NO_KEY;
+ }
+
+ if (level2Signature == null || level2Signature.length == 0) {
+ return Constants.LEVEL2_VALIDATION_NO_SIGNATURE;
+ }
+
+ String keyAlgName = null;
+ try {
+ keyAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_KEY_GENERATOR_ALG, level2KeyAlg);
+ } catch (Exception e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+ if (keyAlgName == null || keyAlgName.length() == 0) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+
+ PublicKey key = null;
+ try {
+ byte[] keyBytes = this.getLevel2Data().getLevel1Data().getLevel2publicKey();
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+ key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
+ } catch (InvalidKeySpecException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ } catch (NoSuchAlgorithmException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+
+ //find the algorithm name for the signature OID
+ String level2SigAlg = this.getLevel2Data().getLevel1Data().getLevel2SigningAlg();
+
+ String sigAlgName = null;
+ try {
+ sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg);
+ } catch (Exception e1) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ if (sigAlgName == null) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ Signature sig;
+ try {
+ if (prov == null) {
+ sig = Signature.getInstance(sigAlgName);
+ } else {
+ sig = Signature.getInstance(sigAlgName, prov);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ try {
+ sig.initVerify(key);
+ } catch (InvalidKeyException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ try {
+ byte[] data = encode(level2Data);
+ sig.update(data);
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } catch (IllegalArgumentException e) {
+ return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
+ } catch (UnsupportedOperationException e) {
+ return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
+ }
+
+ byte[] signature = level2Signature;
+ try {
+ if (sig.verify(signature)){
+ return Constants.LEVEL2_VALIDATION_OK;
+ } else {
+ return Constants.LEVEL2_VALIDATION_FRAUD;
+ }
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ }
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param prov the prov
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ public int validateLevel1(PublicKey key, Provider prov) throws EncodingFormatException {
+
+ if (level2Data == null) {
+ return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
+ }
+
+
+ if (level2Data == null ||
+ level2Data.getLevel1Signature().length == 0) {
+ return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
+ }
+
+ byte[] signature = this.getLevel2Data().getLevel1Signature();
+
+ //find the algorithm name for the signature OID
+ String algo = null;
+ try {
+ algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2Data().getLevel1Data().getLevel1SigningAlg());
+ } catch (Exception e1) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ if (algo == null) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ Signature sig;
+ try {
+ if (prov != null) {
+ sig = Signature.getInstance(algo, prov);
+ } else {
+ sig = Signature.getInstance(algo);
+
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ try {
+ sig.initVerify(key);
+ } catch (InvalidKeyException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ try {
+ sig.update(encode(level2Data.getLevel1Data()));
+ } catch (SignatureException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } catch (IllegalArgumentException e) {
+ return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
+ } catch (UnsupportedOperationException e) {
+ return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
+ }
+
+
+ try {
+ if (sig.verify(signature)){
+ return Constants.LEVEL2_VALIDATION_OK;
+ } else {
+ return Constants.LEVEL2_VALIDATION_FRAUD;
+ }
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ }
+
+
+
+
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @return the int
+ * @throws EncodingFormatException
+ */
+ public int validateLevel1(PublicKey key) throws EncodingFormatException {
+
+ return validateLevel1(key, null);
+
+ }
+
+ /**
+ * Sign level 2 data without a specific security provider.
+ *
+ * @param key the key
+ * @throws Exception the exception
+ */
+ 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();
+
+ }
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the 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);
+ sig.initSign(key);
+ byte[] data = encode(level2Data);
+ sig.update(data);
+ level2Signature = sig.sign();
+
+ }
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException {
+
+
+ level2Data.setLevel2Data(new SimpleData());
+
+ level2Data.getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1);
+
+ level2Data.getLevel2Data().setData(DynamicContentCoder.encode(content, DynamicContentCoder.dynamicContentDataFDC1));
+
+ }
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
+ this.getLevel2Data().setLevel2Data(dynamicData.getApiDataType());
+ }
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ public IUicDynamicContent getDynamicContent() {
+
+ if (this.getLevel2Data() == null ||
+ this.getLevel2Data().getLevel2Data() == null){
+ return null;
+ }
+
+ return DynamicContentCoder.decode(level2Data.getLevel2Data().getData());
+
+ }
+
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @return
+ * @return the byte[]
+ * @throws Exception
+ */
+ public void signLevel1(PrivateKey key) throws Exception {
+
+ if (level2Data == null) return;
+
+ ILevel1Data level1Data = level2Data.getLevel1Data();
+
+ if (level1Data == null) return;
+
+ //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());
+ }
+
+ /**
+ * Sign the contained data block.
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param security provider - security provider that must be sued to create the signature
+ * @return
+ * @return the byte[]
+ * @throws Exception
+ */
+ @Override
+ public void signLevel1(PrivateKey key, Provider prov) throws Exception {
+
+ if (level2Data == null) return;
+
+ ILevel1Data level1Data = level2Data.getLevel1Data();
+
+ if (level1Data == null) return;
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg());
+ Signature sig = Signature.getInstance(algo, prov);
+ sig.initSign(key);
+
+ byte[] data = encode(level1Data);
+ sig.update(data);
+ level2Data.setLevel1Signature(sig.sign());
+ }
+
+
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java
new file mode 100644
index 0000000..241cf6d
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel1Data.java
@@ -0,0 +1,254 @@
+package org.uic.barcode.dynamicFrame.api;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class SignedDataType.
+ */
+
+public class SimpleLevel1Data implements ILevel1Data {
+
+ /** The security provider */
+ public String securityProvider;
+
+
+ /** The key id. */
+ public Long keyId;
+
+
+ /** The data. */
+ public Collection<IData> dataList;
+
+ /**
+ * The key generator algorithms
+ * Object Identifier of the Algorithm
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ public String level1KeyAlg;
+
+ /** The level 2 key alg. */
+ public String level2KeyAlg;
+
+ /**
+ * The signing algorithm
+ * Object Identifier of the Algorithms
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ public String level1SigningAlg;
+
+ /** The level 2 signing alg. */
+ public String level2SigningAlg;
+
+
+ /** The level 2 public key. */
+ public byte[] level2publicKey;
+
+
+ public Date endOfBarcodeValidity = null;
+
+
+
+
+
+ /**
+ * Gets the security provider .
+ *
+ * @return the security provider
+ */
+ public String getSecurityProvider() {
+ return securityProvider;
+ }
+
+ /**
+ * Sets the security provider.
+ *
+ * in case the security provider code is encoded in IA5 this will return null
+ *
+ * @param securityProviderNum the new security provider
+ */
+ public void setSecurityProvider(String securityProvider) {
+ this.securityProvider = securityProvider;
+ }
+
+
+
+
+
+ /**
+ * Gets the key id.
+ *
+ * @return the key id
+ */
+ public Long getKeyId() {
+ return keyId;
+ }
+
+ /**
+ * Sets the key id.
+ *
+ * @param keyId the new key id
+ */
+ public void setKeyId(Long keyId) {
+ this.keyId = keyId;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public Collection<IData> getData() {
+ return dataList;
+ }
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(Collection<IData> data) {
+ this.dataList = data;
+ }
+
+ /**
+ * Gets the level 2 key alg.
+ *
+ * @return the level 2 key alg
+ */
+ public String getLevel2KeyAlg() {
+ return level2KeyAlg;
+ }
+
+ /**
+ * Sets the level 2 key alg.
+ *
+ * @param level2KeyAlg the new level 2 key alg
+ */
+ public void setLevel2KeyAlg(String level2KeyAlg) {
+ this.level2KeyAlg = level2KeyAlg;
+ }
+
+ /**
+ * Gets the level 1 signing alg.
+ *
+ * @return the level 1 signing alg
+ */
+ public String getLevel1SigningAlg() {
+ return level1SigningAlg;
+ }
+
+ /**
+ * Sets the level 1 signing alg.
+ *
+ * @param level1SigningAlg the new level 1 signing alg
+ */
+ public void setLevel1SigningAlg(String level1SigningAlg) {
+ this.level1SigningAlg = level1SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 signing alg.
+ *
+ * @return the level 2 signing alg
+ */
+ public String getLevel2SigningAlg() {
+ return level2SigningAlg;
+ }
+
+ /**
+ * Sets the level 2 signing alg.
+ *
+ * @param level2SigningAlg the new level 2 signing alg
+ */
+ public void setLevel2SigningAlg(String level2SigningAlg) {
+ this.level2SigningAlg = level2SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 public key.
+ *
+ * @return the level 2 public key
+ */
+ public byte[] getLevel2publicKey() {
+ return level2publicKey;
+ }
+
+ /**
+ * Sets the level 2 public key.
+ *
+ * @param level2publicKey the new level 2 public key
+ */
+ public void setLevel2publicKey(byte[] level2publicKey) {
+ this.level2publicKey = level2publicKey;
+ }
+
+
+
+ /**
+ * Gets the level 1 key alg.
+ *
+ * @return the level 1 key alg
+ */
+ public String getLevel1KeyAlg() {
+ return level1KeyAlg;
+ }
+
+ /**
+ * Sets the level 1 key alg.
+ *
+ * @param level1KeyAlg the new level 1 key alg
+ */
+ public void setLevel1KeyAlg(String level1KeyAlg) {
+ this.level1KeyAlg = level1KeyAlg;
+ }
+
+ /**
+ * Sets the end of validity date. The validity date has to be provided in UTC.
+ *
+ * @param date the new end of validity date
+ */
+ public void setEndOfBarcodeValidity(Date date){
+
+ endOfBarcodeValidity = date;
+
+
+ }
+
+ /**
+ * Gets the end of validity date.
+ *
+ * @return the end of validity date
+ */
+ public Date getEndOfBarcodeValidity() {
+
+ return endOfBarcodeValidity;
+ }
+
+ @Override
+ public void addData(IData data) {
+
+ if (dataList == null) {
+ dataList = new ArrayList<IData>();
+ }
+
+ dataList.add(data);
+
+ }
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java
new file mode 100644
index 0000000..395db4d
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/api/SimpleLevel2Data.java
@@ -0,0 +1,75 @@
+package org.uic.barcode.dynamicFrame.api;
+
+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.Sequence;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class DataType.
+ */
+@Sequence
+@HasExtensionMarker
+public class SimpleLevel2Data implements ILevel2Data {
+
+ @FieldOrder(order = 0)
+ ILevel1Data level1Data;
+
+ /** The data. */
+ @FieldOrder(order = 1)
+ @Asn1Optional public byte[] level1Signature;
+
+ @FieldOrder(order = 2)
+ @Asn1Optional IData level2Data;
+
+
+ public ILevel1Data getLevel1Data() {
+ return level1Data;
+ }
+
+
+ public void setLevel1Data(ILevel1Data level1Data) {
+ this.level1Data = level1Data;
+ }
+
+
+ public byte[] getLevel1Signature() {
+ return level1Signature;
+ }
+
+ public byte[] getLevel1SignatureBytes() {
+ return level1Signature;
+ }
+
+
+ public void setLevel1Signature(byte[] level1Signature) {
+ this.level1Signature = level1Signature;
+ }
+
+
+ public IData getLevel2Data() {
+ return level2Data;
+ }
+
+
+ public void setLevel2Data(IData level2Data) {
+ this.level2Data = level2Data;
+ }
+
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/package.html b/src/main/java/org/uic/barcode/dynamicFrame/package.html
deleted file mode 100644
index dbe6c06..0000000
--- a/src/main/java/org/uic/barcode/dynamicFrame/package.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head></head>
-<body>
-
-<h1>drafted new header for dynamic content </h1>
-<p>Provides a decoding and encoding of the header data frame. (Draft for UIC IRS 90918-9).</p>
-</body>
-</html> \ No newline at end of file
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java
index 2ea63ca..6195b3c 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v1;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
import org.uic.barcode.asn1.datatypes.RestrictedString;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java
new file mode 100644
index 0000000..3af9c8f
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrame.java
@@ -0,0 +1,432 @@
+package org.uic.barcode.dynamicFrame.v1;
+
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
+import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.utils.AlgorithmNameResolver;
+
+
+/**
+ * The DynamicHeader for bar codes
+ *
+ * Implementation of the Draft under discussion, not final.
+ */
+@Sequence
+public class DynamicFrame extends Object{
+
+ /**
+ * Instantiates a new dynamic frame.
+ */
+ public DynamicFrame() {}
+
+ /** The format. */
+ @FieldOrder(order = 0)
+ @RestrictedString(CharacterRestriction.IA5String)
+ public String format;
+
+ /** The level 2 signed data. */
+ /*level 2 data*/
+ @FieldOrder(order = 1)
+ Level2DataType level2SignedData;
+
+
+ /** The signature of level 2 data. */
+ @FieldOrder(order = 2)
+ @Asn1Optional public OctetString level2Signature;
+
+ /**
+ * Gets the format.
+ *
+ * @return the format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the format.
+ *
+ * @param format the new format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the level 2 signed data.
+ *
+ * @return the level 2 signed data
+ */
+ public Level2DataType getLevel2SignedData() {
+ return level2SignedData;
+ }
+
+ /**
+ * Sets the level 2 signed data.
+ *
+ * @param level2SignedData the new level 2 signed data
+ */
+ public void setLevel2SignedData(Level2DataType level2SignedData) {
+ this.level2SignedData = level2SignedData;
+ }
+
+ /**
+ * Gets the level 2 signature.
+ *
+ * @return the level 2 signature
+ */
+ public OctetString getLevel2Signature() {
+ return level2Signature;
+ }
+
+ /**
+ * Sets the level 2 signature.
+ *
+ * @param level2Signature the new level 2 signature
+ */
+ public void setLevel2Signature(OctetString level2Signature) {
+ this.level2Signature = level2Signature;
+ }
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+ /**
+ * Decode.
+ *
+ * Decode the header from an ASN.1 PER UNALIGNED encoded byte array
+ *
+ * @param bytes the bytes
+ * @return the dynamic header
+ */
+ public static DynamicFrame decode(byte[] bytes) {
+ return UperEncoder.decode(bytes, DynamicFrame.class);
+ }
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @return the int
+ */
+ public int validateLevel2() {
+
+ return validateLevel2(null);
+
+ }
+
+ /**
+ * Verify the level 2 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param prov the prov
+ * @return the int
+ */
+ public int validateLevel2(Provider prov) {
+
+
+ String level2KeyAlg = this.getLevel2SignedData().getLevel1Data().level2KeyAlg;
+
+
+ if (level2KeyAlg == null || level2KeyAlg.length() == 0) {
+ return Constants.LEVEL2_VALIDATION_NO_KEY;
+ }
+
+ 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);
+ } catch (Exception e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+ if (keyAlgName == null || keyAlgName.length() == 0) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+
+ PublicKey key = null;
+ try {
+ byte[] keyBytes = this.getLevel2SignedData().getLevel1Data().level2publicKey.toByteArray();
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+ key = KeyFactory.getInstance(keyAlgName).generatePublic(keySpec);
+ } catch (InvalidKeySpecException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ } catch (NoSuchAlgorithmException e1) {
+ return Constants.LEVEL2_VALIDATION_KEY_ALG_NOT_IMPLEMENTED;
+ }
+
+ //find the algorithm name for the signature OID
+ String level2SigAlg = this.getLevel2SignedData().getLevel1Data().level2SigningAlg;
+
+ String sigAlgName = null;
+ try {
+ sigAlgName = AlgorithmNameResolver.getName(AlgorithmNameResolver.TYPE_SIGNATURE_ALG,level2SigAlg);
+ } catch (Exception e1) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ if (sigAlgName == null) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ Signature sig;
+ try {
+ if (prov == null) {
+ sig = Signature.getInstance(sigAlgName);
+ } else {
+ sig = Signature.getInstance(sigAlgName, prov);
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ try {
+ sig.initVerify(key);
+ } catch (InvalidKeyException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ try {
+ byte[] data = UperEncoder.encode(level2SignedData);
+ sig.update(data);
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } catch (IllegalArgumentException e) {
+ return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
+ } catch (UnsupportedOperationException e) {
+ return Constants.LEVEL2_VALIDATION_ENCODING_ERROR;
+ }
+
+ byte[] signature = level2Signature.toByteArray();
+ try {
+ if (sig.verify(signature)){
+ return Constants.LEVEL2_VALIDATION_OK;
+ } else {
+ return Constants.LEVEL2_VALIDATION_FRAUD;
+ }
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ }
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @param prov the prov
+ * @return the int
+ */
+ public int validateLevel1(PublicKey key, Provider prov) {
+
+ if (this.level2SignedData == null) {
+ return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
+ }
+
+
+ if (this.level2SignedData.level1Signature == null || this.level2SignedData.level1Signature.toByteArray().length == 0) {
+ return Constants.LEVEL1_VALIDATION_NO_SIGNATURE;
+ }
+
+ byte[] signature = this.getLevel2SignedData().level1Signature.toByteArray();
+
+ //find the algorithm name for the signature OID
+ String algo = null;
+ try {
+ algo = AlgorithmNameResolver.getSignatureAlgorithmName(getLevel2SignedData().getLevel1Data().level1SigningAlg);
+ } catch (Exception e1) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ if (algo == null) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ Signature sig;
+ try {
+ if (prov != null) {
+ sig = Signature.getInstance(algo, prov);
+ } else {
+ sig = Signature.getInstance(algo);
+
+ }
+ } catch (NoSuchAlgorithmException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ try {
+ sig.initVerify(key);
+ } catch (InvalidKeyException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+
+ try {
+ sig.update(this.level2SignedData.level1Data.encode());
+ } catch (SignatureException e) {
+ return Constants.LEVEL1_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ } catch (IllegalArgumentException e) {
+ return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
+ } catch (UnsupportedOperationException e) {
+ return Constants.LEVEL1_VALIDATION_ENCODING_ERROR;
+ }
+
+
+ try {
+ if (sig.verify(signature)){
+ return Constants.LEVEL2_VALIDATION_OK;
+ } else {
+ return Constants.LEVEL2_VALIDATION_FRAUD;
+ }
+ } catch (SignatureException e) {
+ return Constants.LEVEL2_VALIDATION_SIG_ALG_NOT_IMPLEMENTED;
+ }
+ }
+
+ /**
+ * Verify the level 1 signature
+ *
+ * Note: an appropriate security provider (e.g. BC) must be registered before
+ *
+ * @param key the key
+ * @return the int
+ */
+ public int validateLevel1(PublicKey key) {
+
+ return validateLevel1(key, null);
+
+ }
+
+ /**
+ * Sign level 2 data without a specific security provider.
+ *
+ * @param key the key
+ * @throws Exception the exception
+ */
+ public void signLevel2(PrivateKey key) throws Exception {
+
+ //find the algorithm name for the signature OID
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(this.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ Signature sig = Signature.getInstance(algo);
+ sig.initSign(key);
+ byte[] data = level2SignedData.encode();
+ sig.update(data);
+ byte[] signature = sig.sign();
+ this.level2Signature = new OctetString(signature);
+
+ }
+
+ /**
+ * Sign level 2 data.
+ *
+ * @param key the key
+ * @param prov the 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.getLevel2SignedData().getLevel1Data().level2SigningAlg);
+ Signature sig = Signature.getInstance(algo,prov);
+ sig.initSign(key);
+ byte[] data = level2SignedData.encode();
+ sig.update(data);
+ this.level2Signature = new OctetString(sig.sign());
+
+ }
+
+
+ /**
+ * Adds the dynamic content and encodes it. (API level)
+ *
+ * @param content the dynamic content
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void addDynamicContent(IUicDynamicContent content) throws EncodingFormatException {
+
+
+ level2SignedData.setLevel2Data(new DataType());
+
+ level2SignedData.getLevel2Data().setFormat(DynamicContentCoder.dynamicContentDataFDC1);
+
+ level2SignedData.getLevel2Data().setByteData(DynamicContentCoder.encode(content, DynamicContentCoder.dynamicContentDataFDC1));
+
+ }
+
+ /**
+ * Adds the level 2 dynamic data. (ASN level)
+ *
+ * @param dynamicData the dynamic data
+ */
+ public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
+ DataType dt = new DataType();
+ dt.setByteData(dynamicData.getDataType().getByteData());
+ dt.setFormat(dynamicData.getDataType().getFormat());
+ level2SignedData.setLevel2Data(dt);
+ }
+
+ /**
+ * Gets the dynamic content.
+ *
+ * @return the dynamic content
+ */
+ public IUicDynamicContent getDynamicContent() {
+
+ if (level2SignedData == null ||
+ level2SignedData.getLevel2Data() == null){
+ return null;
+ }
+
+ return DynamicContentCoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData());
+
+ }
+
+ /**
+ * Gets the dynamic data FDC 1.
+ *
+ * @return the dynamic data FDC 1
+ */
+ public UicDynamicContentDataFDC1 getDynamicDataFDC1() {
+
+ if (level2SignedData == null ||
+ level2SignedData.getLevel2Data() == null){
+ return null;
+ }
+
+ if ( UicDynamicContentDataFDC1.getFormat().equals(this.getLevel2SignedData().getLevel2Data().getFormat())) {
+ return UperEncoder.decode(this.getLevel2SignedData().getLevel2Data().getByteData(), UicDynamicContentDataFDC1.class);
+ }
+ return null;
+
+ }
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java
new file mode 100644
index 0000000..f7b3f3d
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/DynamicFrameCoderV1.java
@@ -0,0 +1,189 @@
+package org.uic.barcode.dynamicFrame.v1;
+
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrame;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.ILevel2Data;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel2Data;
+
+public class DynamicFrameCoderV1 {
+
+ public static void decode(IDynamicFrame frame, byte[] bytes) {
+
+ DynamicFrame asnFrame = UperEncoder.decode(bytes,DynamicFrame.class);
+
+ frame.setFormat(asnFrame.getFormat());
+
+ if (asnFrame.getLevel2Signature() != null) {
+ frame.setLevel2Signature(asnFrame.getLevel2Signature().toByteArray());
+ }
+
+ if (asnFrame.getLevel2SignedData() != null) {
+ frame.setLevel2Data(new SimpleLevel2Data());
+ populateApi(frame.getLevel2Data(), asnFrame.getLevel2SignedData());
+ }
+
+ }
+
+ private static void populateApi(ILevel2Data level2, Level2DataType asnLevel2) {
+
+ if (asnLevel2 == null) return;
+
+
+ level2.setLevel1Signature(asnLevel2.getLevel1SignatureBytes());
+
+ if (asnLevel2.getLevel1Data() != null) {
+ level2.setLevel1Data(new SimpleLevel1Data());
+ level2.setLevel1Data(populateApi(asnLevel2.getLevel1Data()));
+ }
+
+ if (asnLevel2.getLevel2Data() != null) {
+ level2.setLevel2Data(new SimpleData());
+ level2.setLevel2Data(populateApi(asnLevel2.getLevel2Data()));
+ }
+ }
+
+ private static IData populateApi(DataType asnData) {
+
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ return data;
+ }
+
+ private static ILevel1Data populateApi(Level1DataType asnLevel1) {
+
+ ILevel1Data level1 = new SimpleLevel1Data();
+
+ level1.setKeyId(asnLevel1.getKeyId());
+ level1.setSecurityProvider(asnLevel1.getSecurityProvider());
+ level1.setLevel1KeyAlg(asnLevel1.getLevel1KeyAlg());
+ level1.setLevel1SigningAlg(asnLevel1.getLevel1SigningAlg());
+ level1.setLevel2KeyAlg(asnLevel1.getLevel2KeyAlg());
+ level1.setLevel2SigningAlg(asnLevel1.getLevel2SigningAlg());
+ if (asnLevel1.getLevel2publicKey() != null) {
+ level1.setLevel2publicKey(asnLevel1.getLevel2publicKey().toByteArray());
+ }
+
+ if (asnLevel1.getData() != null && !asnLevel1.getData().isEmpty()) {
+
+ for (DataType asnData : asnLevel1.getData()) {
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ level1.addData(data);
+ }
+ }
+
+ return level1;
+ }
+
+ public static byte[] encode(IDynamicFrame dynamicFrame) throws EncodingFormatException {
+
+ DynamicFrame asnDynamicFrame = populateAsn(dynamicFrame);
+
+ return UperEncoder.encode(asnDynamicFrame);
+
+ }
+
+
+ public static byte[] encode(ILevel1Data level1Data) throws EncodingFormatException {
+
+ Level1DataType asn = populateAsn(level1Data);
+
+ return UperEncoder.encode(asn);
+ }
+
+ public static byte[] encode(ILevel2Data level2SignedData) throws EncodingFormatException {
+
+ Level2DataType asn = populateAsn(level2SignedData);
+
+ return UperEncoder.encode(asn);
+ }
+
+ private static DynamicFrame populateAsn(IDynamicFrame frame) throws EncodingFormatException {
+
+ DynamicFrame asnFrame = new DynamicFrame();
+
+ asnFrame.setFormat(frame.getFormat());
+
+ if (frame.getLevel2Signature() != null && frame.getLevel2Signature().length > 0) {
+ asnFrame.setLevel2Signature(new OctetString(frame.getLevel2Signature()));
+ }
+
+ Level2DataType asnLevel2 = populateAsn(frame.getLevel2Data());
+ if (asnLevel2 != null) {
+ asnFrame.setLevel2SignedData(asnLevel2);
+ }
+
+ return asnFrame;
+ }
+
+
+ private static Level2DataType populateAsn(ILevel2Data level2) throws EncodingFormatException {
+
+ Level2DataType asnLevel2 = new Level2DataType();
+
+ asnLevel2.setLevel1Signature(level2.getLevel1Signature());
+
+ Level1DataType asnLevel1 = populateAsn(level2.getLevel1Data());
+
+ asnLevel2.setLevel1Data(asnLevel1);
+
+ if (level2.getLevel2Data() != null) {
+ DataType data2 = new DataType();
+ data2.setFormat(level2.getLevel2Data().getFormat());
+ data2.setData(new OctetString(level2.getLevel2Data().getData()));
+ asnLevel2.setLevel2Data(data2);
+ }
+
+ return asnLevel2;
+ }
+
+ private static Level1DataType populateAsn(ILevel1Data level1) throws EncodingFormatException {
+
+ Level1DataType asnLevel1 = new Level1DataType();
+
+ asnLevel1.setSecurityProvider(level1.getSecurityProvider());
+
+ asnLevel1.setKeyId(level1.getKeyId());
+
+ asnLevel1.setLevel1KeyAlg(level1.getLevel1KeyAlg());
+
+ asnLevel1.setLevel1SigningAlg(level1.getLevel1SigningAlg());
+
+ asnLevel1.setLevel2KeyAlg(level1.getLevel2KeyAlg());
+
+ if (level1.getLevel2publicKey() != null && level1.getLevel2publicKey().length > 0) {
+ asnLevel1.setLevel2publicKey(new OctetString(level1.getLevel2publicKey()));
+ }
+
+ asnLevel1.setLevel2SigningAlg(level1.getLevel2SigningAlg());
+
+ if (level1.getData() != null && !level1.getData().isEmpty()) {
+
+ asnLevel1.setData(new SequenceOfDataType());
+
+ for (IData data : level1.getData()) {
+
+ DataType asnData = new DataType();
+ asnData.setByteData(data.getData());
+ asnData.setFormat(data.getFormat());
+ asnLevel1.getData().add(asnData);
+
+ }
+
+ }
+
+ return asnLevel1;
+ }
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java
index 958cafc..5104c50 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Level1DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level1DataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v1;
import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java
new file mode 100644
index 0000000..7813cf2
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/Level2DataType.java
@@ -0,0 +1,74 @@
+package org.uic.barcode.dynamicFrame.v1;
+
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class DataType.
+ */
+@Sequence
+public class Level2DataType {
+
+ @FieldOrder(order = 0)
+ Level1DataType level1Data;
+
+ /** The data. */
+ @FieldOrder(order = 1)
+ @Asn1Optional public OctetString level1Signature;
+
+ @FieldOrder(order = 2)
+ @Asn1Optional DataType level2Data;
+
+
+ public Level1DataType getLevel1Data() {
+ return level1Data;
+ }
+
+
+ public void setLevel1Data(Level1DataType level1Data) {
+ this.level1Data = level1Data;
+ }
+
+
+ public OctetString getLevel1Signature() {
+ return level1Signature;
+ }
+
+ public byte[] getLevel1SignatureBytes() {
+ return level1Signature.toByteArray();
+ }
+
+ public void setLevel1Signature(OctetString level1Signature) {
+ this.level1Signature = level1Signature;
+ }
+
+ public void setLevel1Signature(byte[] level1Signature) {
+ this.level1Signature = new OctetString(level1Signature);
+ }
+
+
+ public DataType getLevel2Data() {
+ return level2Data;
+ }
+
+
+ public void setLevel2Data(DataType level2Data) {
+ this.level2Data = level2Data;
+ }
+
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java
index b5c130e..be0bf95 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/SequenceOfDataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v1/SequenceOfDataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v1;
import java.util.Collection;
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java
new file mode 100644
index 0000000..f94b622
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DataType.java
@@ -0,0 +1,95 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
+import org.uic.barcode.asn1.datatypes.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+
+/**
+ * The Class DataType.
+ */
+@Sequence
+@HasExtensionMarker
+public class DataType {
+
+
+ /** The data format.
+ *
+ * -- FCB1 FCB version 1
+ * -- FCB2 FCB version 2
+ * -- RICS company code + ...
+ **/
+ @RestrictedString(CharacterRestriction.IA5String)
+ public String format;
+
+ /** The data. */
+ public OctetString data;
+
+ /**
+ * Gets the data format.
+ *
+ * @return the data format
+ */
+ public String getFormat() {
+ return format;
+ }
+
+ /**
+ * Sets the data format.
+ *
+ * @param dataFormat the new data format
+ */
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public OctetString getData() {
+ return data;
+ }
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(OctetString data) {
+ this.data = data;
+ }
+
+ /**
+ * Gets the data as byte array.
+ *
+ * @return the data
+ */
+ public byte[] getByteData() {
+ return data.toByteArray();
+ }
+
+ /**
+ * Sets the data from a byte array.
+ *
+ * @param data the new data
+ */
+ public void setByteData(byte[] data) {
+ this.data = new OctetString(data);
+ }
+
+ /**
+ * Encode.
+ *
+ * Encode the header as ASN.1 PER UNALIGNED byte array
+ *
+ * @return the byte[]
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+ }
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java
index eb26729..2986f75 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/DynamicFrame.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrame.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v2;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
@@ -14,6 +14,7 @@ import java.security.spec.X509EncodedKeySpec;
import org.uic.barcode.asn1.datatypes.Asn1Optional;
import org.uic.barcode.asn1.datatypes.CharacterRestriction;
import org.uic.barcode.asn1.datatypes.FieldOrder;
+import org.uic.barcode.asn1.datatypes.HasExtensionMarker;
import org.uic.barcode.asn1.datatypes.RestrictedString;
import org.uic.barcode.asn1.datatypes.Sequence;
import org.uic.barcode.asn1.datatypesimpl.OctetString;
@@ -21,17 +22,18 @@ import org.uic.barcode.asn1.uper.UperEncoder;
import org.uic.barcode.dynamicContent.api.DynamicContentCoder;
import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
+import org.uic.barcode.dynamicFrame.Constants;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.utils.AlgorithmNameResolver;
-// TODO: Auto-generated Javadoc
/**
* The DynamicHeader for bar codes
*
* Implementation of the Draft under discussion, not final.
*/
@Sequence
+@HasExtensionMarker
public class DynamicFrame extends Object{
/**
@@ -387,7 +389,10 @@ public class DynamicFrame extends Object{
* @param dynamicData the dynamic data
*/
public void addLevel2DynamicData(UicDynamicContentDataFDC1 dynamicData) {
- this.getLevel2SignedData().setLevel2Data( dynamicData.getDataType());
+ DataType dt = new DataType();
+ dt.setByteData(dynamicData.getDataType().getByteData());
+ dt.setFormat(dynamicData.getDataType().getFormat());
+ level2SignedData.setLevel2Data(dt);
}
/**
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java
new file mode 100644
index 0000000..8987f59
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/DynamicFrameCoderV2.java
@@ -0,0 +1,203 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.dynamicFrame.v2.DynamicFrame;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.IDynamicFrame;
+import org.uic.barcode.dynamicFrame.api.ILevel1Data;
+import org.uic.barcode.dynamicFrame.api.ILevel2Data;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel1Data;
+import org.uic.barcode.dynamicFrame.api.SimpleLevel2Data;
+import org.uic.barcode.dynamicFrame.v2.Level2DataType;
+import org.uic.barcode.dynamicFrame.v2.DataType;
+import org.uic.barcode.dynamicFrame.v2.Level1DataType;
+import org.uic.barcode.dynamicFrame.v2.SequenceOfDataType;
+import org.uic.barcode.ticket.EncodingFormatException;
+
+public class DynamicFrameCoderV2 {
+
+ public static void decode(IDynamicFrame frame, byte[] bytes) {
+
+ DynamicFrame asnFrame = UperEncoder.decode(bytes,DynamicFrame.class);
+
+ frame.setFormat(asnFrame.getFormat());
+
+ if (asnFrame.getLevel2Signature() != null) {
+ frame.setLevel2Signature(asnFrame.getLevel2Signature().toByteArray());
+ }
+
+ if (asnFrame.getLevel2SignedData() != null) {
+ frame.setLevel2Data(new SimpleLevel2Data());
+ populateApi(frame.getLevel2Data(), asnFrame.getLevel2SignedData());
+ }
+
+ }
+
+ private static void populateApi(ILevel2Data level2, Level2DataType asnLevel2) {
+
+ if (asnLevel2 == null) return;
+
+ level2.setLevel1Signature(asnLevel2.getLevel1SignatureBytes());
+
+ if (asnLevel2.getLevel1Data() != null) {
+ level2.setLevel1Data(new SimpleLevel1Data());
+ level2.setLevel1Data(populateApi(asnLevel2.getLevel1Data()));
+ }
+
+ if (asnLevel2.getLevel2Data() != null) {
+ level2.setLevel2Data(new SimpleData());
+ level2.setLevel2Data(populateApi(asnLevel2.getLevel2Data()));
+ }
+
+ }
+
+ private static IData populateApi(DataType asnData) {
+
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ return data;
+ }
+
+ private static ILevel1Data populateApi(Level1DataType asnLevel1) {
+
+ ILevel1Data level1 = new SimpleLevel1Data();
+
+ level1.setKeyId(asnLevel1.getKeyId());
+ level1.setSecurityProvider(asnLevel1.getSecurityProvider());
+ level1.setLevel1KeyAlg(asnLevel1.getLevel1KeyAlg());
+ level1.setLevel1SigningAlg(asnLevel1.getLevel1SigningAlg());
+ level1.setLevel2KeyAlg(asnLevel1.getLevel2KeyAlg());
+ level1.setLevel2SigningAlg(asnLevel1.getLevel2SigningAlg());
+ if (asnLevel1.getLevel2publicKey() != null) {
+ level1.setLevel2publicKey(asnLevel1.getLevel2publicKey().toByteArray());
+ }
+
+ if (asnLevel1.getData() != null && !asnLevel1.getData().isEmpty()) {
+
+ for (DataType asnData : asnLevel1.getData()) {
+ IData data = new SimpleData();
+ data.setData(asnData.getByteData());
+ data.setFormat(asnData.getFormat());
+ level1.addData(data);
+ }
+ }
+
+ if (asnLevel1.getEndOfValidityDate() != null) {
+ level1.setEndOfBarcodeValidity(asnLevel1.getEndOfValidityDate());
+ }
+
+ return level1;
+ }
+
+ public static byte[] encode(IDynamicFrame dynamicFrame) throws EncodingFormatException {
+
+ DynamicFrame asnDynamicFrame = populateAsn(dynamicFrame);
+
+ return UperEncoder.encode(asnDynamicFrame);
+
+ }
+
+
+
+ public static byte[] encode(ILevel1Data level1Data) throws EncodingFormatException {
+
+ Level1DataType asn = populateAsn(level1Data);
+
+ return UperEncoder.encode(asn);
+ }
+
+ public static byte[] encode(ILevel2Data level2SignedData) throws EncodingFormatException {
+
+ Level2DataType asn = populateAsn(level2SignedData);
+
+ return UperEncoder.encode(asn);
+ }
+
+ private static DynamicFrame populateAsn(IDynamicFrame frame) throws EncodingFormatException {
+
+ DynamicFrame asnFrame = new DynamicFrame();
+
+ frame.setFormat(frame.getFormat());
+
+ if (frame.getLevel2Signature() != null && frame.getLevel2Signature().length > 0) {
+ asnFrame.setLevel2Signature(new OctetString(frame.getLevel2Signature()));
+ }
+
+ Level2DataType asnLevel2 = populateAsn(frame.getLevel2Data());
+ if (asnLevel2 != null) {
+ asnFrame.setLevel2SignedData(asnLevel2);
+ }
+
+ return asnFrame;
+ }
+
+
+ private static Level2DataType populateAsn(ILevel2Data level2) throws EncodingFormatException {
+
+ Level2DataType asnLevel2 = new Level2DataType();
+
+ asnLevel2.setLevel1Signature(level2.getLevel1Signature());
+
+ Level1DataType asnLevel1 = populateAsn(level2.getLevel1Data());
+
+ asnLevel2.setLevel1Data(asnLevel1);
+
+ if (level2.getLevel2Data() != null) {
+ DataType data2 = new DataType();
+ data2.setFormat(level2.getLevel2Data().getFormat());
+ data2.setData(new OctetString(level2.getLevel2Data().getData()));
+ asnLevel2.setLevel2Data(data2);
+ }
+
+
+
+ return asnLevel2;
+ }
+
+ private static Level1DataType populateAsn(ILevel1Data level1) throws EncodingFormatException {
+
+ Level1DataType asnLevel1 = new Level1DataType();
+
+ asnLevel1.setSecurityProvider(level1.getSecurityProvider());
+
+ asnLevel1.setKeyId(level1.getKeyId());
+
+ asnLevel1.setLevel1KeyAlg(level1.getLevel1KeyAlg());
+
+ asnLevel1.setLevel1SigningAlg(level1.getLevel1SigningAlg());
+
+ asnLevel1.setLevel2KeyAlg(level1.getLevel2KeyAlg());
+
+ if (level1.getLevel2publicKey() != null && level1.getLevel2publicKey().length > 0) {
+ asnLevel1.setLevel2publicKey(new OctetString(level1.getLevel2publicKey()));
+ }
+
+ asnLevel1.setLevel2SigningAlg(level1.getLevel2SigningAlg());
+
+ if (level1.getData() != null && !level1.getData().isEmpty()) {
+
+ asnLevel1.setData(new SequenceOfDataType());
+
+ for (IData data : level1.getData()) {
+
+ DataType asnData = new DataType();
+ asnData.setByteData(data.getData());
+ asnData.setFormat(data.getFormat());
+ asnLevel1.getData().add(asnData);
+
+ }
+
+ }
+
+ asnLevel1.setEndOfValidityDate(level1.getEndOfBarcodeValidity());
+
+
+ return asnLevel1;
+ }
+
+
+
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java
new file mode 100644
index 0000000..1dff709
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level1DataType.java
@@ -0,0 +1,374 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.uic.barcode.asn1.datatypes.Asn1Optional;
+import org.uic.barcode.asn1.datatypes.CharacterRestriction;
+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.RestrictedString;
+import org.uic.barcode.asn1.datatypes.Sequence;
+import org.uic.barcode.asn1.datatypesimpl.OctetString;
+import org.uic.barcode.asn1.uper.UperEncoder;
+import org.uic.barcode.ticket.EncodingFormatException;
+import org.uic.barcode.ticket.api.utils.UicEncoderUtils;
+
+// TODO: Auto-generated Javadoc
+/**
+ * The Class SignedDataType.
+ */
+@Sequence
+@HasExtensionMarker
+public class Level1DataType {
+
+ /**
+ * The security provider
+ * numeric codes 1 ...32000
+ *
+ * */
+ @FieldOrder(order = 0)
+ @IntRange(minValue=1,maxValue=32000)
+ @Asn1Optional public Long securityProviderNum;
+
+ /** The security provider alphanumeric codes. */
+ @FieldOrder(order = 1)
+ @RestrictedString(CharacterRestriction.IA5String)
+ @Asn1Optional public String securityProviderIA5;
+
+
+ /** The key id. */
+ @FieldOrder(order = 2)
+ @IntRange(minValue=0,maxValue=99999)
+ @Asn1Optional public Long keyId;
+
+
+ /** The data. */
+ @FieldOrder(order = 3)
+ public SequenceOfDataType data;
+
+ /**
+ * The key generator algorithms
+ * Object Identifier of the Algorithm
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ @FieldOrder(order = 4)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level1KeyAlg;
+
+ /** The level 2 key alg. */
+ @FieldOrder(order = 5)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level2KeyAlg;
+
+ /**
+ * The signing algorithm
+ * Object Identifier of the Algorithms
+ * Number notation:
+ *
+ * e.g.:
+ * -- DSA SHA224 2.16.840.1.101.3.4.3.1
+ * -- DSA SHA256 2.16.840.1.101.3.4.3.2
+ * -- ECC 256 1.2.840.10045.3.1.7
+ *
+ *
+ */
+ @FieldOrder(order = 6)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level1SigningAlg;
+
+ /** The level 2 signing alg. */
+ @FieldOrder(order = 7)
+ @RestrictedString(CharacterRestriction.ObjectIdentifier)
+ @Asn1Optional public String level2SigningAlg;
+
+
+ /** The level 2 public key. */
+ @FieldOrder(order = 8)
+ @Asn1Optional public OctetString level2publicKey;
+
+
+ /** The End of validity year. */
+ @FieldOrder(order = 9)
+ @IntRange(minValue=2016,maxValue=2269)
+ public Long EndOfValidityYear;
+
+ /** The End of validity day. */
+ @FieldOrder(order = 10)
+ @IntRange(minValue=1,maxValue=366)
+ public Long EndOfValidityDay;
+
+ /** The End of validity time. */
+ @FieldOrder(order = 11)
+ @IntRange(minValue=0,maxValue=1440)
+ @Asn1Optional public Long EndOfValidityTime;
+
+
+
+
+
+ /**
+ * Gets the security provider num.
+ *
+ * @return the security provider num
+ */
+ public Long getSecurityProviderNum() {
+ return securityProviderNum;
+ }
+
+ /**
+ * Sets the security provider num.
+ *
+ * in case the security provider code is encoded in IA5 this will return null
+ *
+ * @param securityProviderNum the new security provider num
+ */
+ public void setSecurityProviderNum(Long securityProviderNum) {
+ this.securityProviderNum = securityProviderNum;
+ }
+
+ /**
+ * Gets the security provider IA5.
+ *
+ * in case the security provider code is encoded numerically this will return null
+ *
+ * @return the security provider IA5
+ */
+ public String getSecurityProviderIA5() {
+ return securityProviderIA5;
+ }
+
+ /**
+ * Sets the security provider
+ *
+ * The security provider code must use the IA5 Alphabet .
+ *
+ * @param securityProvider the new security provider
+ * @throws EncodingFormatException the encoding format exception
+ */
+ public void setSecurityProvider(String securityProvider) throws EncodingFormatException {
+ this.securityProviderNum = UicEncoderUtils.getNum(securityProvider);
+ this.securityProviderIA5 = UicEncoderUtils.getIA5NonNum(securityProvider);
+ }
+
+
+ /**
+ * Gets the security provider.
+ *
+ * @return the security provider
+ */
+ public String getSecurityProvider() {
+ return UicEncoderUtils.mapToString(this.securityProviderNum, this.securityProviderIA5);
+ }
+
+
+ /**
+ * Sets the security provider IA 5.
+ *
+ * @param securityProviderIA5 the new security provider IA 5
+ */
+ public void setSecurityProviderIA5(String securityProviderIA5) {
+ this.securityProviderIA5 = securityProviderIA5;
+ }
+
+ /**
+ * Gets the key id.
+ *
+ * @return the key id
+ */
+ public Long getKeyId() {
+ return keyId;
+ }
+
+ /**
+ * Sets the key id.
+ *
+ * @param keyId the new key id
+ */
+ public void setKeyId(Long keyId) {
+ this.keyId = keyId;
+ }
+
+ /**
+ * Gets the data.
+ *
+ * @return the data
+ */
+ public SequenceOfDataType getData() {
+ return data;
+ }
+
+ /**
+ * Sets the data.
+ *
+ * @param data the new data
+ */
+ public void setData(SequenceOfDataType data) {
+ this.data = data;
+ }
+
+ /**
+ * Gets the level 2 key alg.
+ *
+ * @return the level 2 key alg
+ */
+ public String getLevel2KeyAlg() {
+ return level2KeyAlg;
+ }
+
+ /**
+ * Sets the level 2 key alg.
+ *
+ * @param level2KeyAlg the new level 2 key alg
+ */
+ public void setLevel2KeyAlg(String level2KeyAlg) {
+ this.level2KeyAlg = level2KeyAlg;
+ }
+
+ /**
+ * Gets the level 1 signing alg.
+ *
+ * @return the level 1 signing alg
+ */
+ public String getLevel1SigningAlg() {
+ return level1SigningAlg;
+ }
+
+ /**
+ * Sets the level 1 signing alg.
+ *
+ * @param level1SigningAlg the new level 1 signing alg
+ */
+ public void setLevel1SigningAlg(String level1SigningAlg) {
+ this.level1SigningAlg = level1SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 signing alg.
+ *
+ * @return the level 2 signing alg
+ */
+ public String getLevel2SigningAlg() {
+ return level2SigningAlg;
+ }
+
+ /**
+ * Sets the level 2 signing alg.
+ *
+ * @param level2SigningAlg the new level 2 signing alg
+ */
+ public void setLevel2SigningAlg(String level2SigningAlg) {
+ this.level2SigningAlg = level2SigningAlg;
+ }
+
+ /**
+ * Gets the level 2 public key.
+ *
+ * @return the level 2 public key
+ */
+ public OctetString getLevel2publicKey() {
+ return level2publicKey;
+ }
+
+ /**
+ * Sets the level 2 public key.
+ *
+ * @param level2publicKey the new level 2 public key
+ */
+ public void setLevel2publicKey(OctetString level2publicKey) {
+ this.level2publicKey = level2publicKey;
+ }
+
+
+
+ /**
+ * Gets the level 1 key alg.
+ *
+ * @return the level 1 key alg
+ */
+ public String getLevel1KeyAlg() {
+ return level1KeyAlg;
+ }
+
+ /**
+ * Sets the level 1 key alg.
+ *
+ * @param level1KeyAlg the new level 1 key alg
+ */
+ public void setLevel1KeyAlg(String level1KeyAlg) {
+ this.level1KeyAlg = level1KeyAlg;
+ }
+
+ /**
+ * Sets the end of validity date. The validity date has to be provided in UTC.
+ *
+ * @param date the new end of validity date
+ */
+ public void setEndOfValidityDate(Date date){
+
+ if (date == null) {
+ date = Calendar.getInstance().getTime();
+ }
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(date);
+
+ this.EndOfValidityYear = new Long( cal.get(Calendar.YEAR));
+ this.EndOfValidityDay = new Long (cal.get(Calendar.DAY_OF_YEAR));
+ int time = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE);
+ if (time >= 0) {
+ this.EndOfValidityTime = new Long (time );
+ }
+
+ }
+
+ /**
+ * Gets the end of validity date.
+ *
+ * @return the end of validity date
+ */
+ public Date getEndOfValidityDate() {
+
+ if (this.EndOfValidityYear == null || this.EndOfValidityDay == null) return null;
+
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.setTimeZone(TimeZone.getTimeZone("UTC"));
+ cal.set(Calendar.YEAR, this.EndOfValidityYear.intValue());
+ cal.set(Calendar.DAY_OF_YEAR, this.EndOfValidityDay.intValue());
+
+ if (this.EndOfValidityTime != null) {
+
+ int hours = this.EndOfValidityTime.intValue() / 60;
+ int minutes = this.EndOfValidityTime.intValue() % 60;
+ cal.set(Calendar.HOUR_OF_DAY, hours);
+ cal.set(Calendar.MINUTE,minutes);
+
+ }
+
+ Date d = cal.getTime();
+ return d;
+ }
+
+ /**
+ * Gets the data for signature.
+ *
+ * The byte array containing the ASN.1 PER UNALIGNED encoded data of the DataBlock
+ *
+ *
+ * @return the data for signature
+ */
+ public byte[] encode() {
+ return UperEncoder.encode(this);
+
+ }
+}
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java
index 8c3cd60..6534c4d 100644
--- a/src/main/java/org/uic/barcode/dynamicFrame/Level2DataType.java
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/Level2DataType.java
@@ -1,4 +1,4 @@
-package org.uic.barcode.dynamicFrame;
+package org.uic.barcode.dynamicFrame.v2;
import java.security.PrivateKey;
import java.security.Provider;
@@ -6,6 +6,7 @@ import java.security.Signature;
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.Sequence;
import org.uic.barcode.asn1.datatypesimpl.OctetString;
import org.uic.barcode.asn1.uper.UperEncoder;
@@ -15,6 +16,7 @@ import org.uic.barcode.utils.AlgorithmNameResolver;
* The Class DataType.
*/
@Sequence
+@HasExtensionMarker
public class Level2DataType {
@FieldOrder(order = 0)
diff --git a/src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java b/src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java
new file mode 100644
index 0000000..fc76776
--- /dev/null
+++ b/src/main/java/org/uic/barcode/dynamicFrame/v2/SequenceOfDataType.java
@@ -0,0 +1,25 @@
+package org.uic.barcode.dynamicFrame.v2;
+
+
+import java.util.Collection;
+
+import org.uic.barcode.asn1.datatypes.Asn1SequenceOf;
+
+/**
+ * The Class SequenceOfDataType.
+ */
+public class SequenceOfDataType extends Asn1SequenceOf<DataType>{
+
+ /**
+ * Instantiates a new sequence of data type.
+ */
+ public SequenceOfDataType() { super(); }
+
+ /**
+ * Instantiates a new sequence of data type.
+ *
+ * @param coll the coll
+ */
+ public SequenceOfDataType(Collection<DataType> coll) { super(coll); }
+
+}
diff --git a/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java
index 10963c5..5355d5d 100644
--- a/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicContentCoderTest.java
@@ -108,7 +108,7 @@ public class DynamicContentCoderTest {
assert(content.getTimeStamp() != null);
- assert(content.getTimeStamp().toString().equals("Wed Dec 15 12:30:00 CET 2021" ));
+ assert(content.getTimeStamp().toString().contains("04 12:30:00 CET"));
}
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
index 84f7795..0730e69 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureProviderSelectionTest.java
@@ -22,7 +22,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.Level2TestDataFactory;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
@@ -93,7 +93,7 @@ public class DynamicFrameDoubleSignatureProviderSelectionTest {
assert(enc != null);
- DataType level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
+ IData level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
try {
enc.setLevel2Data(level2Data);
enc.signLevel2(keyPairLevel2.getPrivate(),prov);
@@ -135,15 +135,15 @@ public class DynamicFrameDoubleSignatureProviderSelectionTest {
signatureCheck = 0;
try {
signatureCheck = dec.validateLevel2(prov);
- } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ } catch (Exception e) {
assert(false);
}
assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK);
- DataType level2DataDec = dec.getLevel2Data();
+ IData level2DataDec = dec.getLevel2Data();
assert(level2Data.getFormat().equals(level2DataDec.getFormat()));
- assert(Arrays.equals(level2Data.getData().toByteArray(),level2DataDec.getData().toByteArray()));
+ assert(Arrays.equals(level2Data.getData(),level2DataDec.getData()));
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java
index a316cfc..787ebae 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDoubleSignatureTest.java
@@ -21,7 +21,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.Level2TestDataFactory;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
@@ -89,7 +89,7 @@ public class DynamicFrameDoubleSignatureTest {
assert(enc != null);
- DataType level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
+ IData level2Data = Level2TestDataFactory.getLevel2SimpleTestData();
try {
enc.setLevel2Data(level2Data);
enc.signLevel2(keyPairLevel2.getPrivate());
@@ -131,15 +131,15 @@ public class DynamicFrameDoubleSignatureTest {
signatureCheck = 0;
try {
signatureCheck = dec.validateLevel2();
- } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ } catch (Exception e) {
assert(false);
}
assert(signatureCheck == Constants.LEVEL2_VALIDATION_OK);
- DataType level2DataDec = dec.getLevel2Data();
+ IData level2DataDec = dec.getLevel2Data();
assert(level2Data.getFormat().equals(level2DataDec.getFormat()));
- assert(Arrays.equals(level2Data.getData().toByteArray(),level2DataDec.getData().toByteArray()));
+ assert(Arrays.equals(level2Data.getData(),level2DataDec.getData()));
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
index a5f91ca..4cfca12 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameDynamicContentTest.java
@@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
+import org.uic.barcode.dynamicContent.api.IUicDynamicContent;
import org.uic.barcode.dynamicContent.fdc1.GeoCoordinateType;
import org.uic.barcode.dynamicContent.fdc1.TimeStamp;
import org.uic.barcode.dynamicContent.fdc1.UicDynamicContentDataFDC1;
@@ -217,7 +218,7 @@ public class DynamicFrameDynamicContentTest {
assert(level2check == Constants.LEVEL2_VALIDATION_OK);
- UicDynamicContentDataFDC1 dynamicData = dec.getDynamicHeader().getDynamicDataFDC1();
+ IUicDynamicContent dynamicData = dec.getDynamicHeader().getDynamicContent();
assert(dynamicData.getChallengeString().equals("CHALLENGE"));
@@ -228,9 +229,9 @@ public class DynamicFrameDynamicContentTest {
assert(Arrays.equals(dynamicData.getPhoneIdHash(),phoneIdHash));
assert(dynamicData.getGeoCoordinate().getLatitude() == 123456L);
- assert(dynamicData.getGeoCoordinate().getLongitude() == 823456L);
+ assert(dynamicData.getGeoCoordinate().getLongitude() == 103456L);
- Date timeStamp = dynamicData.getTimeStamp().getTimeAsDate();
+ Date timeStamp = dynamicData.getTimeStamp();
ZonedDateTime retrievedTimeStamp = timeStamp.toInstant().atZone(ZoneId.of("UTC"));
long diff = ChronoUnit.SECONDS.between(originalTimeStamp, retrievedTimeStamp);
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
index 63ba68e..861fc85 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion1Test.java
@@ -20,6 +20,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.ticket.api.spec.IUicRailTicket;
@@ -144,9 +145,10 @@ public class DynamicFrameFcbVersion1Test {
assert(dec.getDynamicHeader().getFormat().equals("U1"));
- assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB1"));
-
-
+ for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) {
+ assert(data.getFormat().equals("FCB1") );
+ }
+
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
index 4f0897e..fa055dc 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameFcbVersion3Test.java
@@ -20,6 +20,7 @@ import org.junit.Test;
import org.uic.barcode.Decoder;
import org.uic.barcode.Encoder;
import org.uic.barcode.dynamicFrame.Constants;
+import org.uic.barcode.dynamicFrame.api.IData;
import org.uic.barcode.test.utils.SimpleUICTestTicket;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.ticket.api.spec.IUicRailTicket;
@@ -144,8 +145,9 @@ public class DynamicFrameFcbVersion3Test {
assert(dec.getDynamicHeader().getFormat().equals("U1"));
- assert(dec.getDynamicHeader().getLevel2SignedData().getLevel1Data().getData().get(0).getFormat().equals("FCB3"));
-
+ for (IData data : dec.getDynamicHeader().getLevel2Data().getLevel1Data().getData()) {
+ assert(data.getFormat().equals("FCB3") );
+ }
SimpleUICTestTicket.compare(ticket, dec.getUicTicket());
diff --git a/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java b/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java
index 5dd9668..d354837 100644
--- a/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java
+++ b/src/test/java/org/uic/barcode/test/DynamicFrameLOwLevelTest.java
@@ -21,7 +21,7 @@ import org.junit.Before;
import org.junit.Test;
import org.uic.barcode.asn1.uper.UperEncoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrame;
import org.uic.barcode.test.utils.SimpleDynamicFrameTestBarcode;
public class DynamicFrameLOwLevelTest {
diff --git a/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java b/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java
index b1eb0f5..bdabdc6 100644
--- a/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java
+++ b/src/test/java/org/uic/barcode/test/utils/Level2TestDataFactory.java
@@ -1,17 +1,17 @@
package org.uic.barcode.test.utils;
-import org.uic.barcode.asn1.datatypesimpl.OctetString;
-import org.uic.barcode.dynamicFrame.DataType;
+import org.uic.barcode.dynamicFrame.api.IData;
+import org.uic.barcode.dynamicFrame.api.SimpleData;
public class Level2TestDataFactory {
- public static DataType getLevel2SimpleTestData() {
+ public static IData getLevel2SimpleTestData() {
String testContent = "2020.10.01T12:12.20";
- DataType level2Data = new DataType();
+ IData level2Data = new SimpleData();
level2Data.setFormat("TEST");
- level2Data.setData(new OctetString(testContent.getBytes()));
+ level2Data.setData(testContent.getBytes());
return level2Data;
}
diff --git a/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java b/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java
index 0060fcd..f2ef0f3 100644
--- a/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java
+++ b/src/test/java/org/uic/barcode/test/utils/SimpleDynamicFrameTestBarcode.java
@@ -1,28 +1,27 @@
package org.uic.barcode.test.utils;
import java.security.KeyPair;
+import java.security.Signature;
+import org.uic.barcode.asn1.uper.UperEncoder;
import org.uic.barcode.dynamicFrame.Constants;
-import org.uic.barcode.dynamicFrame.DataType;
-import org.uic.barcode.dynamicFrame.DynamicFrame;
-import org.uic.barcode.dynamicFrame.Level1DataType;
-import org.uic.barcode.dynamicFrame.Level2DataType;
-import org.uic.barcode.dynamicFrame.SequenceOfDataType;
+import org.uic.barcode.dynamicFrame.v1.DataType;
+import org.uic.barcode.dynamicFrame.v1.DynamicFrame;
+import org.uic.barcode.dynamicFrame.v1.Level1DataType;
+import org.uic.barcode.dynamicFrame.v1.Level2DataType;
+import org.uic.barcode.dynamicFrame.v1.SequenceOfDataType;
import org.uic.barcode.ticket.EncodingFormatException;
import org.uic.barcode.ticket.api.asn.omv1.UicRailTicketData;
import org.uic.barcode.ticket.api.test.testtickets.SimpleUicTestTicket;
+import org.uic.barcode.utils.AlgorithmNameResolver;
public class SimpleDynamicFrameTestBarcode {
public static DynamicFrame getSimpleDynamicHeaderBarcode(String algorithm, KeyPair keyPair) {
-
-
DynamicFrame barcode = null;
-
-
try {
barcode = new DynamicFrame();
barcode.setFormat(Constants.DYNAMIC_BARCODE_FORMAT_DEFAULT);
@@ -47,7 +46,12 @@ public class SimpleDynamicFrameTestBarcode {
level1Data.getData().add(data);
try {
- level2Data.signLevel1(keyPair.getPrivate());
+ String algo = AlgorithmNameResolver.getSignatureAlgorithmName(level1Data.getLevel1SigningAlg());
+ Signature sig = Signature.getInstance(algo);
+ sig.initSign(keyPair.getPrivate());
+ byte[] data2 = UperEncoder.encode(level1Data);
+ sig.update(data2);
+ level2Data.setLevel1Signature(sig.sign());
} catch (Exception e) {
assert(false);
}