Skip to content

Commit

Permalink
Merge pull request #613 from tilln/feature-next/arqc-padding
Browse files Browse the repository at this point in the history
Define padding method for each CryptogramDataBuilder
  • Loading branch information
ar authored Sep 11, 2024
2 parents afcf598 + af3515e commit 1d2c0e8
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 59 deletions.
4 changes: 0 additions & 4 deletions jpos/src/main/java/org/jpos/emv/cryptogram/CPACryptogram.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public String getDefaultARPCRequest(boolean approved) {
return approved ? "0000" : "9900";
}


@Override
public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
StringBuilder sb = new StringBuilder();
Expand All @@ -46,7 +45,7 @@ public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod){
return paddingMethod.apply(buildARQCRequest(data, iad));
public PaddingMethod getPaddingMethod() {
return PaddingMethod.ISO9797Method1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod) {
return paddingMethod.apply(buildARQCRequest(data, iad));
public PaddingMethod getPaddingMethod() {
return PaddingMethod.ISO9797Method1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public String buildARQCRequest(TLVList data, IssuerApplicationData iad) {
}

@Override
public String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad, PaddingMethod paddingMethod) {
return paddingMethod.apply(buildARQCRequest(data, iad));
public PaddingMethod getPaddingMethod() {
return PaddingMethod.ISO9797Method2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,13 @@ 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";
}

@Override
public PaddingMethod getPaddingMethod() {
return PaddingMethod.ISO9797Method2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,53 @@
*/
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();
};

enum PaddingMethod {
NO_PADDING,

/**
* ISO/IEC 9797-1 padding method 1
* for Block size 8, n = 64
*/
ISO9797Method1 {
@Override
public String apply(String data) {
return 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
*/
ISO9797Method2 {
@Override
public String apply(String data) {
return ISO9797Method1.apply(data + "80");
}
},

/**
* ISO/IEC 9797-1 padding method 3
* for Block size 8, n = 64
*/
ISO9797Method3 {
@Override
public String apply(String 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();
}
};

public String apply(String data) {
return data;
}
}

/**
* Method that selects the minimum set of data elements recommended for
Expand All @@ -86,7 +104,6 @@ static List<String> minimumSetOfDataElement(TLVList data) {
);
}


/**
* Method that returns default issuer response data (ARC or CSU)
*
Expand All @@ -105,22 +122,21 @@ 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);
default String buildARQCRequest_padded(TLVList data, IssuerApplicationData iad) {
return getPaddingMethod().apply(buildARQCRequest(data, iad));
}

/**
* Padding Method Interface
/** Defines how to pad the request data when generating the ARQC.
* @return PaddingMethod this builder uses
*/
interface PaddingMethod {
String apply(String data);
}
PaddingMethod getPaddingMethod();

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ public class CPACryptogramTest {
@Test
void test(){
CPACryptogram spec = new CPACryptogram();
assertEquals(spec.paddingMethod, CryptogramDataBuilder.ISO9797Method2);
assertEquals(spec.getMKDMethod(), MKDMethod.OPTION_A);
assertEquals(spec.getSKDMethod(), SKDMethod.EMV_CSKD);
assertEquals(spec.getARPCMethod(), ARPCMethod.METHOD_2);
assertTrue(spec.getDataBuilder() instanceof CVNCPADataBuilder);
assertEquals(CryptogramDataBuilder.PaddingMethod.ISO9797Method2, spec.getDataBuilder().getPaddingMethod());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void testBuildARQCRequest() {

assertEquals(
"00000000010000000000000008400000000000084018123101ABCDEF101800000203000000000000",
builder.buildARQCRequest_padded(data, iad, builder.ISO9797Method1)
builder.buildARQCRequest_padded(data, iad)
);


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void testBuildARQCRequest() {

assertEquals(
"00000000010000000000000008400000000000084018123101ABCDEF101800000106011203000000",
builder.buildARQCRequest_padded(data, iad, builder.ISO9797Method1)
builder.buildARQCRequest_padded(data, iad)
);


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void testBuildARQCRequest() {

assertEquals(
"0000000100000000000010000840000000108008409807040011111111580034560FA500A03800000000000000000000000F01000000000000000000000000000080000000000000",
builder.buildARQCRequest_padded(data, iad, builder.ISO9797Method2)
builder.buildARQCRequest_padded(data, iad)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.Arrays;
import java.util.Random;

import static org.jpos.emv.cryptogram.CryptogramDataBuilder.*;
import static org.jpos.emv.cryptogram.CryptogramDataBuilder.PaddingMethod.*;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;

Expand Down

0 comments on commit 1d2c0e8

Please sign in to comment.