Created
March 27, 2019 15:21
-
-
Save ozkansari/65fa143b2018bb7c2efaf44e76d89e62 to your computer and use it in GitHub Desktop.
PIN Block Creation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import javax.crypto.Cipher; | |
import javax.crypto.spec.SecretKeySpec; | |
public class EncryptSample { | |
private static final String KEY = "AB1C11111111111AAAAAAADDDDD11111"; | |
private static final int PIN_LENGTH = 6; | |
public static void main(String[] args) throws Exception { | |
TripleDES td = new TripleDES(KEY, PIN_LENGTH); | |
String pan = "4111111111111111"; | |
String pin = "123456"; | |
String encrypted = td.encrypt(pan, pin); | |
System.out.println("encrypted: " + encrypted); | |
String decrypted = td.decrypt(pan, encrypted); | |
System.out.println("decrypted : " + decrypted); | |
} | |
} | |
class TripleDES { | |
private static final String ALGORITHM = "TripleDES"; | |
private static final String MODE = "ECB"; | |
private static final String PADDING = "NoPadding"; | |
/** algorithm/mode/padding */ | |
private static final String TRANSFORMATION = ALGORITHM+"/"+MODE+"/"+PADDING; | |
private final String key; | |
private int pinLength; | |
TripleDES(String key, int pinLength) { | |
this.key = key; | |
this.pinLength = pinLength; | |
} | |
public String encrypt(String pan, String pinClear) throws Exception { | |
if(pinClear.length() != pinLength) { | |
System.out.println("Incorrect PIN length given. Please fix! pinClear.size() " + "!= " + " pinLength : " + pinClear.length() + " !=" + pinLength); | |
} | |
String pinEncoded = encodePinBlockAsHex(pan, pinClear); | |
byte[] tmp = h2b(this.key); | |
byte[] key = new byte[24]; | |
System.arraycopy(tmp, 0, key, 0, 16); | |
System.arraycopy(tmp, 0, key, 16, 8); | |
Cipher cipher = Cipher.getInstance(TRANSFORMATION); | |
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, ALGORITHM)); | |
byte[] plaintext = cipher.doFinal(h2b(pinEncoded)); | |
return b2h(plaintext); | |
} | |
public String decrypt(String pan, String encryptedPin) throws Exception { | |
byte[] tmp = h2b(this.key); | |
byte[] key = new byte[24]; | |
System.arraycopy(tmp, 0, key, 0, 16); | |
System.arraycopy(tmp, 0, key, 16, 8); | |
Cipher cipher = Cipher.getInstance(TRANSFORMATION); | |
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, ALGORITHM)); | |
byte[] plaintext = cipher.doFinal(h2b(encryptedPin)); | |
String pinEncoded = b2h(plaintext); | |
return decodePinBlock(pan, pinEncoded); | |
} | |
public String decodePinBlock(String pan, String pinEncoded) throws Exception { | |
pan = pan.substring(pan.length() - 12 - 1, pan.length() - 1); | |
String paddingPAN = "0000".concat(pan); | |
byte[] pinBlock = xorBytes(h2b(paddingPAN), h2b(pinEncoded)); | |
return b2h(pinBlock).substring(2, pinLength+2); | |
} | |
public String encodePinBlockAsHex(String pan, String pin) throws Exception { | |
pan = pan.substring(pan.length() - 12 - 1, pan.length() - 1); | |
String paddingPAN = "0000".concat(pan); | |
String Fs = "FFFFFFFFFFFFFFFF"; | |
String paddingPIN = "0" + pin.length() + pin + Fs.substring(2 + pin.length(), Fs.length()); | |
byte[] pinBlock = xorBytes(h2b(paddingPAN), h2b(paddingPIN)); | |
return b2h(pinBlock); | |
} | |
private static byte[] xorBytes(byte[] a, byte[] b) throws Exception { | |
if (a.length != b.length) { | |
throw new Exception(); | |
} | |
byte[] result = new byte[a.length]; | |
for (int i = 0; i < a.length; i++) { | |
int r = 0; | |
r = a[i] ^ b[i]; | |
r &= 0xFF; | |
result[i] = (byte) r; | |
} | |
return result; | |
} | |
private static byte[] h2b(String hex) { | |
if ((hex.length() & 0x01) == 0x01) | |
throw new IllegalArgumentException(); | |
byte[] bytes = new byte[hex.length() / 2]; | |
for (int idx = 0; idx < bytes.length; ++idx) { | |
int hi = Character.digit((int) hex.charAt(idx * 2), 16); | |
int lo = Character.digit((int) hex.charAt(idx * 2 + 1), 16); | |
if ((hi < 0) || (lo < 0)) | |
throw new IllegalArgumentException(); | |
bytes[idx] = (byte) ((hi << 4) | lo); | |
} | |
return bytes; | |
} | |
private static String b2h(byte[] bytes) { | |
char[] hex = new char[bytes.length * 2]; | |
for (int idx = 0; idx < bytes.length; ++idx) { | |
int hi = (bytes[idx] & 0xF0) >>> 4; | |
int lo = (bytes[idx] & 0x0F); | |
hex[idx * 2] = (char) (hi < 10 ? '0' + hi : 'A' - 10 + hi); | |
hex[idx * 2 + 1] = (char) (lo < 10 ? '0' + lo : 'A' - 10 + lo); | |
} | |
return new String(hex); | |
} | |
} |
You are the man!!!
This is amazing!!!
I just modified the Pinlock decode to get automatic length, based on this site https://emvlab.org/pinblock/
explaiden here https://www.linkedin.com/pulse/pinblock-explained-iftekharul-haque/
public String decodePinBlock(String pan, String pinEncoded) throws Exception {
pan = pan.substring(pan.length() - 12 - 1, pan.length() - 1);
String paddingPAN = "0000".concat(pan);
byte[] pinBlock = xorBytes(h2b(paddingPAN), h2b(pinEncoded));
//return b2h(pinBlock).substring(2, pinLength+2);
String result=b2h(pinBlock);
int lenClear =Integer.parseInt(result.substring(1,2)) ;
return result.substring(2, lenClear+2);
}
So... pinLength is used to encrypt only !!!
thank you so much.
You are the man!!! This is amazing!!! I just modified the Pinlock decode to get automatic length, based on this site https://emvlab.org/pinblock/ explaiden here https://www.linkedin.com/pulse/pinblock-explained-iftekharul-haque/
public String decodePinBlock(String pan, String pinEncoded) throws Exception { pan = pan.substring(pan.length() - 12 - 1, pan.length() - 1); String paddingPAN = "0000".concat(pan); byte[] pinBlock = xorBytes(h2b(paddingPAN), h2b(pinEncoded)); //return b2h(pinBlock).substring(2, pinLength+2); String result=b2h(pinBlock); int lenClear =Integer.parseInt(result.substring(1,2)) ; return result.substring(2, lenClear+2); }
So... pinLength is used to encrypt only !!!
thank you so much.
this works great thank you
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks!