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); } }
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 GPKeySet DeriveSessionKeysSCP03(GPKeySet staticKeys, byte[] host_challenge, byte[] card_challenge) { GPKeySet sessionKeys = new GPKeySet(); byte mac_constant = 0x06; byte enc_constant = 0x04; byte rmac_constant = 0x07; byte[] context = Arrays.Concatenate(host_challenge, card_challenge); // MAC byte[] kdf = SCP03Wrapper.Scp03_kdf(staticKeys.GetKey(KeySessionType.MAC), mac_constant, context, 128); sessionKeys.SetKey(KeySessionType.MAC, new GPKey(kdf, KeyType.AES)); // ENC kdf = SCP03Wrapper.Scp03_kdf(staticKeys.GetKey(KeySessionType.ENC), enc_constant, context, 128); sessionKeys.SetKey(KeySessionType.ENC, new GPKey(kdf, KeyType.AES)); // RMAC kdf = SCP03Wrapper.Scp03_kdf(staticKeys.GetKey(KeySessionType.MAC), rmac_constant, context, 128); sessionKeys.SetKey(KeySessionType.RMAC, new GPKey(kdf, KeyType.AES)); // KEK remains the same sessionKeys.SetKey(KeySessionType.KEK, staticKeys.GetKey(KeySessionType.KEK)); return(sessionKeys); }
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); } }