public static GPKeySet Diversify(GPKeySet keys, byte[] diversification_data, Diversification mode, int scp) { try { GPKeySet result = new GPKeySet(); //Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); foreach (KeySessionType v in KeyTypeList.Values) { if (v == KeySessionType.RMAC) { continue; } byte[] kv = null; // shift around and fill initialize update data as required. if (mode == Diversification.VISA2) { kv = FillVisa(diversification_data, v); } else if (mode == Diversification.EMV) { kv = FillEmv(diversification_data, v); } // Encrypt with current master key //cipher.init(Cipher.ENCRYPT_MODE, keys.getKey(v).getKey(Type.DES3)); //byte[] keybytes = cipher.doFinal(kv); byte[] keybytes = GPCrypto.DoEncrypt_DES3_ECB(keys.GetKey(v).GetKey(KeyType.DES3).GetEncoded(), kv); // Replace the key, possibly changing type. G&D SCE 6.0 uses EMV 3DES and resulting keys // must be interpreted as AES-128 GPKey nk = new GPKey(keybytes, scp == 3 ? KeyType.AES : KeyType.DES3); result.SetKey(v, nk); } return(result); } //catch (BadPaddingException e) //{ // throw new Exception("Diversification failed.", e); //} //catch (InvalidKeyException e) //{ // throw new Exception("Diversification failed.", e); //} //catch (IllegalBlockSizeException e) //{ // throw new Exception("Diversification failed.", e); //} //catch (NoSuchAlgorithmException e) //{ // throw new Exception("Diversification failed.", e); //} //catch (NoSuchPaddingException e) //{ // throw new Exception("Diversification failed.", e); //} catch (Exception e) { throw new Exception("Diversification failed.", e); } }
private static byte[] Mac_des_3des(GPKey key, byte[] text, int offset, int length, byte[] iv) { if (length == -1) { length = text.Length - offset; } try { //Cipher cipher1 = Cipher.getInstance(DES_CBC_CIPHER); //cipher1.init(Cipher.ENCRYPT_MODE, key.getKey(Type.DES), new IvParameterSpec(iv)); //Cipher cipher2 = Cipher.getInstance(DES3_CBC_CIPHER); //cipher2.init(Cipher.ENCRYPT_MODE, key.getKey(Type.DES3), new IvParameterSpec(iv)); byte[] result = Arrays.Clone(iv); byte[] temp; if (length > 8) { temp = GPCrypto.DoEncrypt_DES_CBC(key.GetKey(KeyType.DES).GetEncoded(), text, offset, length - 8, iv); Array.Copy(temp, temp.Length - 8, result, 0, 8); } temp = GPCrypto.DoEncrypt_DES3_CBC(key.GetKey(KeyType.DES3).GetEncoded(), text, (offset + length) - 8, 8, result); Array.Copy(temp, temp.Length - 8, result, 0, 8); return(result); } catch (Exception e) { //e.printStackTrace(); throw new Exception("MAC computation failed.", e); } }
public static GPPlaintextKeys FromMasterKey(GPKey master, Diversification div) { GPKeySet ks = new GPKeySet(master); GPPlaintextKeys p = new GPPlaintextKeys(ks, div) { master = master }; return(p); }
public void AuthWithCard(byte[] mk, byte[] hostChallenge = null) { GPKey kmc = new GPKey(mk, KeyType.DES3); GPPlaintextKeys gpptk = GPPlaintextKeys.FromMasterKey(kmc, Diversification.VISA2); gp.OpenSecureChannel(gpptk, new List <APDUMode>() { APDUMode.CLR }, hostChallenge); }
private GPKeySet DeriveSessionKeysSCP01(GPKeySet staticKeys, byte[] host_challenge, byte[] card_challenge) { GPKeySet sessionKeys = new GPKeySet(); byte[] derivationData = new byte[16]; Array.Copy(card_challenge, 4, derivationData, 0, 4); Array.Copy(host_challenge, 0, derivationData, 4, 4); Array.Copy(card_challenge, 0, derivationData, 8, 4); Array.Copy(host_challenge, 4, derivationData, 12, 4); try { //Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); foreach (KeySessionType v in KeyTypeList.Values) { if (v == KeySessionType.RMAC) // skip RMAC key { continue; } //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(v)); //GPKey nk = new GPKey(cipher.doFinal(derivationData), Type.DES3); byte[] result = GPCrypto.DoEncrypt_DES3_ECB(staticKeys.GetKeyFor(v).GetEncoded(), derivationData); GPKey nk = new GPKey(result, KeyType.DES3); sessionKeys.SetKey(v, nk); } // KEK is the same sessionKeys.SetKey(KeySessionType.KEK, staticKeys.GetKey(KeySessionType.KEK)); return(sessionKeys); } //catch (NoSuchAlgorithmException e) //{ // throw new IllegalStateException("Session keys calculation failed.", e); //} //catch (NoSuchPaddingException e) //{ // throw new IllegalStateException("Session keys calculation failed.", e); //} //catch (InvalidKeyException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} //catch (IllegalBlockSizeException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} //catch (BadPaddingException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} catch (Exception e) { throw new Exception("Session keys calculation failed.", e); } }
private static byte[] Scp03_key_check_value(GPKey key) { try { byte[] cv = GPCrypto.DoEncrypt_AES_CBC(key.GetKey().GetEncoded(), GPCrypto.one_bytes_16); //Cipher c = Cipher.getInstance(AES_CBC_CIPHER); //c.init(Cipher.ENCRYPT_MODE, key.getKey(), iv_null_aes); //byte[] cv = c.doFinal(one_bytes_16); return(Arrays.CopyOfRange(cv, 0, 3)); } catch (Exception e) { throw new Exception("Could not calculate key check value: ", e); } }
//public static IvParameterSpec iv_null_des = new IvParameterSpec(null_bytes_8); //public static IvParameterSpec iv_null_aes = new IvParameterSpec(null_bytes_16); public static byte[] Kcv_3des(GPKey key) { try { byte[] check = DoEncrypt_DES3_ECB(key.GetKey().GetEncoded(), null_bytes_8); //Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding"); //cipher.init(Cipher.ENCRYPT_MODE, key.getKey()); //byte check[] = cipher.doFinal(GPCrypto.null_bytes_8); return(Arrays.CopyOf(check, 3)); } catch (Exception e) { throw new Exception("Could not calculate KCV", e); } }
private static byte[] Scp03_encrypt_key(GPKey kek, GPKey key) { try { // Pad with random int n = key.GetLength() % 16 + 1; byte[] plaintext = new byte[n * 16]; SecureRandom sr = new SecureRandom(); sr.NextBytes(plaintext); Array.Copy(key.GetValue(), 0, plaintext, 0, key.GetValue().Length); // encrypt byte[] cgram = GPCrypto.DoEncrypt_AES_CBC(kek.GetValue(), plaintext); //Cipher c = Cipher.getInstance(AES_CBC_CIPHER); //c.init(Cipher.ENCRYPT_MODE, kek.GetEncoded(), null_bytes_16); //byte[] cgram = c.doFinal(plaintext); return(cgram); } catch (Exception e) { throw new Exception("Could not calculate key check value: ", e); } }
private GPKeySet DeriveSessionKeysSCP02(GPKeySet staticKeys, byte[] sequence, bool implicitChannel) { GPKeySet sessionKeys = new GPKeySet(); try { //Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding"); byte[] derivationData = new byte[16]; Array.Copy(sequence, 0, derivationData, 2, 2); byte[] constantMAC = new byte[] { (byte)0x01, (byte)0x01 }; Array.Copy(constantMAC, 0, derivationData, 0, 2); //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.MAC), GPCrypto.iv_null_des); //GPKey nk = new GPKey(cipher.doFinal(derivationData), Type.DES3); byte[] result = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.MAC).GetEncoded(), derivationData); GPKey nk = new GPKey(result, KeyType.DES3); sessionKeys.SetKey(KeySessionType.MAC, nk); // TODO: is this correct? - increment by one for all other than C-MAC if (implicitChannel) { Buffer_increment(derivationData, 2, 2); } byte[] constantRMAC = new byte[] { (byte)0x01, (byte)0x02 }; Array.Copy(constantRMAC, 0, derivationData, 0, 2); //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.MAC), GPCrypto.iv_null_des); //nk = new GPKey(cipher.doFinal(derivationData), Type.DES3); byte[] result2 = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.MAC).GetEncoded(), derivationData); nk = new GPKey(result2, KeyType.DES3); sessionKeys.SetKey(KeySessionType.RMAC, nk); byte[] constantENC = new byte[] { (byte)0x01, (byte)0x82 }; Array.Copy(constantENC, 0, derivationData, 0, 2); //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.ENC), GPCrypto.iv_null_des); //nk = new GPKey(cipher.doFinal(derivationData), Type.DES3); byte[] result3 = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), derivationData); nk = new GPKey(result3, KeyType.DES3); sessionKeys.SetKey(KeySessionType.ENC, nk); byte[] constantDEK = new byte[] { (byte)0x01, (byte)0x81 }; Array.Copy(constantDEK, 0, derivationData, 0, 2); //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.KEK), GPCrypto.iv_null_des); //nk = new GPKey(cipher.doFinal(derivationData), Type.DES3); byte[] result4 = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.KEK).GetEncoded(), derivationData); nk = new GPKey(result4, KeyType.DES3); sessionKeys.SetKey(KeySessionType.KEK, nk); return(sessionKeys); } //catch (NoSuchAlgorithmException e) //{ // throw new IllegalStateException("Session keys calculation failed.", e); //} //catch (NoSuchPaddingException e) //{ // throw new IllegalStateException("Session keys calculation failed.", e); //} //catch (InvalidKeyException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} //catch (IllegalBlockSizeException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} //catch (BadPaddingException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} //catch (InvalidAlgorithmParameterException e) //{ // throw new RuntimeException("Session keys calculation failed.", e); //} catch (Exception e) { throw new Exception("Session keys calculation failed.", e); } }
public static GPPlaintextKeys FromMasterKey(GPKey master) { return(FromMasterKey(master, Diversification.NONE)); }
public void SetKey(KeySessionType type, GPKey k) { keys.Add(type, k); }
public GPKeySet(GPKey master) { keys.Add(KeySessionType.ENC, master); keys.Add(KeySessionType.MAC, master); keys.Add(KeySessionType.KEK, master); }
// SCP03 related private static byte[] Scp03_mac(GPKey key, byte[] msg, int lengthbits) { return(Scp03_mac(key.GetValue(), msg, lengthbits)); }
// GP 2.2.1 Amendment D v 1.1.1 public static byte[] Scp03_kdf(GPKey key, byte constant, byte[] context, int blocklen_bits) { return(Scp03_kdf(key.GetValue(), constant, context, blocklen_bits)); }
private static byte[] Mac_des_3des(GPKey key, byte[] text, byte[] iv) { byte[] d = Pad80(text, 8); return(Mac_des_3des(key, d, 0, d.Length, iv)); }
public static byte[] Mac_3des_nulliv(GPKey key, byte[] d) { return(Mac_3des(key, d, GPCrypto.null_bytes_8)); }