public static ByteArray GenerateRandom(int length, ByteArray sourceBytes) { ByteArray result = new ByteArray(length); result.Randomize(_random, sourceBytes); return(result); }
/// <summary> /// Uwierzytelnia do CM podanym kluczem /// </summary> public JavaCardKeys StartSecuredChannel(ByteArray motherKey, KeyDiversificationMethod diversification = KeyDiversificationMethod.None, SecurityControlMode securityMode = SecurityControlMode.NoSecurity, byte keyVersion = 0x00, byte referenceControlParameter2 = 0x00) { try { //losowanie danych terminala ByteArray terminalRandom = new ByteArray(8); terminalRandom.Randomize(random); //Initialize Update ByteArray response = InitializeUpdate(keyVersion, 00, terminalRandom); //z odpowiedzi wyciągamy dane byte scpId = response[11]; if (scpId == 0x01) { scp = SecureChannelProtocol.SCP01; } else if (scpId == 0x02) { scp = SecureChannelProtocol.SCP02; } ByteArray sn = response.Extract(4, 4); ByteArray aid = response.Extract(0, 2); ByteArray cardRandom = response.Extract(12, 8); ByteArray cardCryptogram = response.Extract(20, 8); Logger.Log("[JavaCard] \n{0}:\t{1}\n{2}:\t{3}\n{4}:\t{5}\n{6}:\t{7}\n{8}:\t{9}", "TerminalRandom", terminalRandom, "SN", sn, "AID", aid, "CardRandom", cardRandom, "CardCryptogram", cardCryptogram); //wyliczanie kluczy z matki switch (diversification) { case KeyDiversificationMethod.None: Keys = new JavaCardKeys(motherKey); break; case KeyDiversificationMethod.GPICSN: Keys = GPICSerialDiversificate(motherKey, response); break; case KeyDiversificationMethod.MPCOS3DES: throw new Exception("Wybrany algorytm dywersyfikacji nie jest na razie wspierany"); break; case KeyDiversificationMethod.TagCF: Keys = TagCFDiversificate(motherKey, response); break; } //wyliczamy klucze sesyjne AUTH/ENC i MAC if (scp == SecureChannelProtocol.SCP01) { ComputeSessionKeys(Keys, terminalRandom, cardRandom); } else if (scp == SecureChannelProtocol.SCP02) { ComputeSessionKeys2(Keys, terminalRandom, cardRandom); } else { throw new Exception("Nieobsługiwany protokół bezpiecznego kanału"); } //weryfikujemy kryptogram zwrócony przez InitializeUpdate if (!CheckCardCryptogram(cardCryptogram, terminalRandom, cardRandom)) { throw new JavaCardAuthenticationException("Kryptogram zwrócony przez komendę InitializeUpdate nie zgadza się."); } //ExternalAuthenticate ByteArray externalAuthenticateCommand = new ByteArray("84 82") + (byte)securityMode + new ByteArray("00 10"); ByteArray terminalCryptogram = GenerateTerminalCryptogram(terminalRandom, cardRandom); ByteArray MAC = new ByteArray(); if (scp == SecureChannelProtocol.SCP01) { MAC = GenerateExAuthMAC(externalAuthenticateCommand, terminalCryptogram); } else if (scp == SecureChannelProtocol.SCP02) { MAC = GenerateExAuthMAC2(externalAuthenticateCommand, terminalCryptogram); } ByteArray fullExternalAuthenticateCommand = externalAuthenticateCommand + terminalCryptogram + MAC; Encoder.SendCommand(fullExternalAuthenticateCommand); _securityMode = securityMode; _lastMAC = MAC; _authenticatedKeySetVersion = response[10]; } catch (APDUException exception) { _sessionKeys = null; _securityMode = SecurityControlMode.NoSecurity; throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception); } catch (Exception exception) { _sessionKeys = null; _securityMode = SecurityControlMode.NoSecurity; throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception); } return(_sessionKeys); }
/// <summary> /// Uwierzytelnia do CM podanymi kluczami /// </summary> /// <param name="keys">Klucze</param> /// <param name="keySet"></param> /// <param name="keyIndex"></param> /// <param name="securityMode"></param> public JavaCardKeys StartSecuredChannel(JavaCardKeys keys, SecurityControlMode securityMode, Byte keySet = 0, Byte keyIndex = 0) { try { //losowanie danych terminala ByteArray terminalRandom = new ByteArray(8); terminalRandom.Randomize(random); //terminalRandom = new ByteArray("00 00 00 00 00 00 00 00"); //Initialize Update ByteArray initializeUpdateCommand = new ByteArray("80 50 00 00 08") + terminalRandom + new ByteArray("00"); initializeUpdateCommand[2] = keySet; initializeUpdateCommand[3] = keyIndex; ByteArray response = Encoder.SendCommand(initializeUpdateCommand); //z odpowiedzi wyciągamy losowe dane karty i kryptogram ByteArray cardRandom = response.Extract(12, 8); ByteArray cardCryptogram = response.Extract(20, 8); byte scpId = response[11]; if (scpId == 0x01) { scp = SecureChannelProtocol.SCP01; } else if (scpId == 0x02) { scp = SecureChannelProtocol.SCP02; } //wyliczamy klucze sesyjne AUTH/ENC i MAC if (scp == SecureChannelProtocol.SCP01) { ComputeSessionKeys(Keys, terminalRandom, cardRandom); } else if (scp == SecureChannelProtocol.SCP02) { ComputeSessionKeys2(Keys, terminalRandom, cardRandom); } else { throw new Exception("Nieobsługiwany protokół bezpiecznego kanału"); } //weryfikujemy kryptogram zwrócony przez InitializeUpdate if (!CheckCardCryptogram(cardCryptogram, terminalRandom, cardRandom)) { throw new JavaCardAuthenticationException("Kryptogram zwrócony przez komendę InitializeUpdate nie zgadza się."); } //ExternalAuthenticate ByteArray externalAuthenticateCommand = new ByteArray("84 82") + (byte)securityMode + new ByteArray("00 10"); ByteArray terminalCryptogram = GenerateTerminalCryptogram(terminalRandom, cardRandom); ByteArray MAC = GenerateExAuthMAC(externalAuthenticateCommand, terminalCryptogram); ByteArray fullExternalAuthenticateCommand = externalAuthenticateCommand + terminalCryptogram + MAC; Encoder.SendCommand(fullExternalAuthenticateCommand); _securityMode = securityMode; _lastMAC = MAC; _authenticatedKeySetVersion = response[10]; } catch (APDUException exception) { _sessionKeys = null; _securityMode = SecurityControlMode.NoSecurity; throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception); } catch (Exception exception) { _sessionKeys = null; _securityMode = SecurityControlMode.NoSecurity; throw new JavaCardAuthenticationException("Błąd ustanowienia bezpiecznego kanału.", exception); } return(_sessionKeys); }