Skip to content

Commit

Permalink
Merge branch 'master' of github.com:espaillato/jPOS
Browse files Browse the repository at this point in the history
  • Loading branch information
Ozzy Espaillat committed Mar 4, 2024
2 parents e5476a9 + 0b4f0f8 commit 6b52a1b
Show file tree
Hide file tree
Showing 24 changed files with 593 additions and 58 deletions.
23 changes: 18 additions & 5 deletions .github/workflows/jpos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ jobs:
strategy:
fail-fast: false
matrix:
java: [ 1.8, 9, 11 ]
os: [ubuntu-latest, macos-latest, windows-latest]
java: [ 8, 11 ]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: ${{ matrix.java }}
cache: 'gradle'
- name: Cache Gradle packages
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
Expand All @@ -29,7 +31,18 @@ jobs:
run: ./gradlew jpos:check --info
env:
TERM: dumb
- name: Upload test results
if: success() || failure()
uses: actions/upload-artifact@v3
with:
name: test-results
path: jpos/build/reports/tests/*
- name: Dependency Check Analyze
run: ./gradlew jpos:dependencyCheckAnalyze --info
env:
TERM: dumb
- name: Dependency Check Analyze
run: ./gradlew jpos:dependencyCheckAnalyze --info
env:
TERM: dumb

1 change: 1 addition & 0 deletions CREDITS
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Bojan Momcilov <bojan-at-transactility.com>
Pablo Marziotto Pablo Marziotto pmarziotto-at-midinero.com.uy>
Cristian Mengui @cmenghi
Rainer Reyes rreyes-at-fintech.works
Elias Terranti elias.terranti-at-gmail.com

Contributors from other OpenSource projects
-------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ subprojects {
apply plugin: 'project-report'

group = 'org.jpos'
version = '2.1.9-SNAPSHOT'
version = '2.1.10-SNAPSHOT'
[ compileJava, compileTestJava, javadoc ]*.options*.encoding = 'UTF-8'
def isSnapshot = version.contains("SNAPSHOT")
def mavenCentralRepo = isSnapshot ?
Expand Down
2 changes: 1 addition & 1 deletion jpos/src/main/java/org/jpos/emv/IssuerApplicationData.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public IssuerApplicationData(String hexIAD) {
//Therefore, the length of the Issuer Application Data is 18 bytes and for
// M/Chip Advance it may be 18, 20, 26, or 28.
unpackMCHIP(iad);
} else if (len == 32 && iad.startsWith("0F") && iad.startsWith("0F", 32)) {
} else if (len == 32 && (iad.startsWith("0F") || iad.startsWith("0f")) && (iad.startsWith("0F", 32) || iad.startsWith("0f", 32))) {
// EMV_v4.3_Book_3
// C7.2 Issuer Application Data for Format Code 'A'
unpackEMVFormatA(iad);
Expand Down
35 changes: 35 additions & 0 deletions jpos/src/main/java/org/jpos/emv/cryptogram/CPACryptogram.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.jpos.emv.cryptogram;

import org.jpos.security.ARPCMethod;
import org.jpos.security.MKDMethod;
import org.jpos.security.SKDMethod;

import org.jpos.emv.cryptogram.CryptogramDataBuilder.PaddingMethod;

/**
* Common Payment Application (CPA) Cryptogram Specification
*/
public class CPACryptogram implements CryptogramSpec {

final PaddingMethod paddingMethod = CryptogramDataBuilder.ISO9797Method2;

@Override
public MKDMethod getMKDMethod() {
return MKDMethod.OPTION_A;
}

@Override
public SKDMethod getSKDMethod() {
return SKDMethod.EMV_CSKD;
}

@Override
public ARPCMethod getARPCMethod() {
return ARPCMethod.METHOD_2;
}

@Override
public CryptogramDataBuilder getDataBuilder() {
return new CVNCPADataBuilder();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* @author Rainer Reyes
*/
public class CVN10DataBuilder implements CryptogramDataBuilder {

@Override
public String getDefaultARPCRequest(boolean approved) {
return approved ? "0000" : "9900";
Expand All @@ -44,4 +44,9 @@ public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
sb.append(iad.getCardVerificationResults());
return sb.toString();
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod){
return paddingMethod.apply(buildARQCRequest(data, iad));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* @author Rainer Reyes
*/
public class CVN18DataBuilder implements CryptogramDataBuilder {

@Override
public String getDefaultARPCRequest(boolean approved) {
/* for success:
Expand All @@ -47,4 +47,9 @@ public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
sb.append(iad.toString());
return sb.toString();
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod) {
return paddingMethod.apply(buildARQCRequest(data, iad));
}
}
26 changes: 26 additions & 0 deletions jpos/src/main/java/org/jpos/emv/cryptogram/CVNCPADataBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.jpos.emv.cryptogram;

import org.jpos.emv.IssuerApplicationData;
import org.jpos.tlv.TLVList;
import static org.jpos.emv.cryptogram.CryptogramDataBuilder.minimumSetOfDataElement;

public class CVNCPADataBuilder implements CryptogramDataBuilder {

@Override
public String getDefaultARPCRequest(boolean approved) {
return approved ? "3030" : "3031";
}

@Override
public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
StringBuilder sb = new StringBuilder();
minimumSetOfDataElement(data).stream().forEach(sb::append);
sb.append(iad.toString());
return sb.toString();
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod) {
return paddingMethod.apply(buildARQCRequest(data, iad));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,14 @@ public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
return sb.toString();
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod) {
return paddingMethod.apply(buildARQCRequest(data, iad));
}

@Override
public String getDefaultARPCRequest(boolean approved) {
return approved ? "0012" : "9900";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@

import org.jpos.emv.EMVStandardTagType;
import org.jpos.emv.IssuerApplicationData;
import org.jpos.iso.ISOUtil;
import org.jpos.tlv.TLVList;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.*;


/**
Expand All @@ -34,6 +33,36 @@
*/
public interface CryptogramDataBuilder {

final PaddingMethod NO_PADDING = data -> data;

/**
* ISO/IEC 9797-1 padding method 1
* for Block size 8, n = 64
*/
final PaddingMethod ISO9797Method1 = data -> data.isEmpty() ?
"0000000000000000" :
ISOUtil.zeropadRight(data, data.length() % 16 == 0 ? data.length() : data.length() + 16 - data.length() % 16);

/**
* ISO/IEC 9797-1 padding method 2
* for Block size 8, n = 64
*/
final PaddingMethod ISO9797Method2 = data -> ISO9797Method1.apply(data + "80");

/**
* ISO/IEC 9797-1 padding method 3
* for Block size 8, n = 64
*/
final PaddingMethod ISO9797Method3 = data -> {
StringBuilder sb = new StringBuilder();
String D = ISO9797Method1.apply(data);
String Ld = ISOUtil.byte2hex(ISOUtil.int2byte(data.length() / 2));
String Lp = ISO9797Method1.apply(Ld);
Lp = Ld.length() % 16 == 0 ? "" : Lp.substring(Ld.length());
return sb.append(Lp).append(Ld).append(D).toString();
};


/**
* Method that selects the minimum set of data elements recommended for
* the generation of application cryptograms described in EMV Book 2 sec 8.1.1
Expand Down Expand Up @@ -67,7 +96,7 @@ static List<String> minimumSetOfDataElement(TLVList data) {
String getDefaultARPCRequest(boolean approved);

/**
* Select necessary data elements and create the string used to generate the ARQC
* Select necessary data elements and create the string used to generate the ARQC with no padding
* <p>
*
* @param data ICC data received
Expand All @@ -76,4 +105,22 @@ static List<String> minimumSetOfDataElement(TLVList data) {
*/
String buildARQCRequest(TLVList data, IssuerApplicationData iad);


/**
* Select necessary data elements and create the string used to generate the ARQC with padding
* <p>
*
* @param data ICC data received
* @param iad Issuer application Data
* @param paddingMethod Padding method to use
* @return String used to generate the ARQC
*/
String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod);

/**
* Padding Method Interface
*/
interface PaddingMethod {
String apply(String data);
}
}
41 changes: 33 additions & 8 deletions jpos/src/main/java/org/jpos/iso/ISODate.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,25 +167,26 @@ public static Date parseISODate (String d, long currentTime) {
*/
public static Date parseISODate (String d, long currentTime, TimeZone timeZone) {
int YY = 0;

Calendar cal = new GregorianCalendar();
cal.setTimeZone(timeZone);
Date now = new Date(currentTime);
cal.setTime (now);

if (d.length() == 14) {
YY = Integer.parseInt(d.substring (0, 4));
d = d.substring (4);
}
else if (d.length() == 12) {
YY = 2000 + Integer.parseInt(d.substring (0, 2));
YY = calculateNearestFullYear(Integer.parseInt(d.substring(0, 2)), cal);
d = d.substring (2);
}
int MM = Integer.parseInt(d.substring (0, 2))-1;
int DD = Integer.parseInt(d.substring (2, 4));
int hh = Integer.parseInt(d.substring (4, 6));
int mm = Integer.parseInt(d.substring (6, 8));
int ss = Integer.parseInt(d.substring (8,10));

Calendar cal = new GregorianCalendar();
cal.setTimeZone(timeZone);
Date now = new Date(currentTime);

cal.setTime (now);

cal.set (Calendar.MONTH, MM);
cal.set (Calendar.DATE, DD);
cal.set (Calendar.HOUR_OF_DAY, hh);
Expand Down Expand Up @@ -323,5 +324,29 @@ public static String getJulianDate(Date d, TimeZone timeZone) {
year = year.substring(1);
return year + day;
}
}

/**
* Calculates the closest year in full YYYY format based on a two-digit year input.
* The closest year is determined in relation to the current year provided by the Calendar instance.
*
* @param year The two-digit year to be converted (e.g., 23 for 2023 or 2123).
* @param now The current date provided as a Calendar instance used for reference.
* @return The closest full year in YYYY format.
* @throws IllegalArgumentException if the input year is not between 0 and 99.
*/
private static int calculateNearestFullYear(int year, Calendar now) {
if (year < 0 || year > 99) {
throw new IllegalArgumentException("Year must be between 0 and 99");
}

int currentYear = now.get(Calendar.YEAR); // e.g., 2023
int currentCentury = currentYear - currentYear % 100; // e.g., 2000 for 2023
int possibleYear = currentCentury + year; // e.g., 2023 for year 23

// Adjust to the closest century if needed
if (Math.abs(year - currentYear % 100) > 50) {
possibleYear += (year > currentYear % 100) ? -100 : 100;
}
return possibleYear;
}
}
10 changes: 8 additions & 2 deletions jpos/src/main/java/org/jpos/iso/ISOTagStringFieldPackager.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,16 @@ private String makeExceptionMessage(ISOComponent c, String operation) {
*/
public byte[] pack(ISOComponent c) throws ISOException {
try{
String data = (String)c.getValue();
String data;
if(c.getValue() instanceof byte[])
data = new String(c.getBytes(), ISOUtil.CHARSET); // transparent handling of complex fields
else
data = (String)c.getValue();

if (data.length() > getLength())
{
throw new ISOException("Field length " + data.length() + " too long. Max: " + getLength());

}
int tag = (Integer)c.getKey();
String paddedData = padder.pad(data, getLength());
byte[] rawData = new byte[tagPrefixer.getPackedLength()+prefixer.getPackedLength()
Expand Down
Loading

0 comments on commit 6b52a1b

Please sign in to comment.