private void SelectApp() { try { if (!LoadCurrentIsoDept()) { OnAppSelected?.Invoke(this, false); } List <byte> selectOperation = new List <byte> { 0x5A }; selectOperation.AddRange(appToSelect); byte[] result = currentIsoDept.Transceive(selectOperation.ToArray()); if (result.Length == 1 && result[0] == 0x00) { OnAppSelected?.Invoke(this, true); } else { OnAppSelected?.Invoke(this, false); } } catch { OnAppSelected?.Invoke(this, false); } }
/** * Callback when a new tag is discovered by the system. * * <p>Communication with the card should take place here. * * @param tag Discovered tag */ public void OnTagDiscovered(Android.Nfc.Tag tag) { Console.WriteLine("New tag discovered"); IsoDep isoDep = IsoDep.Get(tag); if (isoDep != null) { try { // Connect to the remote NFC device isoDep.Connect(); byte[] command = new byte[] { (byte)0x00, /* CLA = 00 (first interindustry command set) */ (byte)0xA4, /* INS = A4 (SELECT) */ (byte)0x04, /* P1 = 04 (select file by DF name) */ (byte)0x0C, /* P2 = 0C (first or only file; no FCI) */ (byte)0x07, /* Lc = 7 (data/AID has 7 bytes) */ /* AID = D6 16 00 00 30 01 01: */ (byte)0xD6, (byte)0x16, (byte)0x00, (byte)0x00, (byte)0x30, (byte)0x01, (byte)0x01, (byte)0x00 }; byte[] result = isoDep.Transceive(command); // If AID is successfully selected, 0x9000 is returned as the status word (last 2 // bytes of the result) by convention. Everything before the status word is // optional payload, which is used here to hold the account number. int resultLength = result.Length; byte[] statusWord = { result[resultLength - 2], result[resultLength - 1] }; byte[] payload = new byte[resultLength - 2]; Array.Copy(result, payload, resultLength - 2); bool arrayEquals = SELECT_OK_SW.Length == statusWord.Length; for (int i = 0; i < SELECT_OK_SW.Length && i < statusWord.Length && arrayEquals; i++) { arrayEquals = (SELECT_OK_SW[i] == statusWord[i]); if (!arrayEquals) { break; } } if (arrayEquals) { // The remote NFC device will immediately respond with its stored account number string info = System.Text.Encoding.UTF8.GetString(result); Console.WriteLine("Received: " + info); // Inform CardReaderFragment of received account number InfoCallback ourCallback; if (callback.TryGetTarget(out ourCallback)) { ourCallback.InfoRecieved(info); } } } catch (Exception e) { Console.WriteLine("Error communicating with card: " + e.Message); } } }
private void DoChallengeYubiKey(IsoDep isoTag, int slot, byte[] challenge) { if (challenge == null || challenge.Length != CHAL_BYTES) { return; } byte[] apdu = new byte[chalCommand.Length + CHAL_BYTES]; chalCommand.CopyTo(apdu, 0); if (slot == 1) { apdu[2] = SLOT_CHAL_HMAC1; } challenge.CopyTo(apdu, chalCommand.Length); byte[] respApdu = isoTag.Transceive(apdu); if (respApdu.Length == 22 && respApdu[20] == (byte)0x90 && respApdu[21] == 0x00) { // Get the secret byte[] resp = new byte[RESP_BYTES]; Array.Copy(respApdu, 0, resp, 0, RESP_BYTES); Intent data = Intent; data.PutExtra("response", resp); SetResult(Result.Ok, data); } else { Toast.MakeText(this, Resource.String.yubichallenge_challenge_failed, ToastLength.Long) .Show(); } }
public async Task <byte[]> TransmitAsync(byte[] inputData) { return(await Task.Run(() => { return isoDep.Transceive(inputData); })); }
/// <summary> /// Callback when a new tag is discovered by the system. /// Communication with the card should take place here. /// </summary> /// <param name="tag">Discovered tag</param> public void OnTagDiscovered(Tag tag) { Log.Info(TAG, "New tag discovered"); IsoDep isoDep = IsoDep.Get(tag); if (isoDep != null) { try { // Connect to the remote NFC device isoDep.Connect(); // Build SELECT AID command for our loyalty card service. // This command tells the remote device which service we wish to communicate with. Log.Info(TAG, "Requesting remote AID: " + SAMPLE_LOYALTY_CARD_AID); byte[] command = BuildSelectApdu(SAMPLE_LOYALTY_CARD_AID); // Send command to remote device Log.Info(TAG, "Sending: " + ByteArrayToHexString(command)); byte[] result = isoDep.Transceive(command); // If AID is successfully selected, 0x9000 is returned as the status word (last 2 // bytes of the result) by convention. Everything before the status word is // optional payload, which is used here to hold the account number. int resultLength = result.Length; byte[] statusWord = { result[resultLength - 2], result[resultLength - 1] }; byte[] payload = new byte[resultLength - 2]; Array.Copy(result, payload, resultLength - 2); bool arrayEquals = SELECT_OK_SW.Length == statusWord.Length; for (int i = 0; i < SELECT_OK_SW.Length && i < statusWord.Length && arrayEquals; i++) { arrayEquals = (SELECT_OK_SW[i] == statusWord[i]); if (!arrayEquals) { break; } } if (arrayEquals) { // The remote NFC device will immediately respond with its stored account number string accountNumber = System.Text.Encoding.UTF8.GetString(payload); Log.Info(TAG, "Received: " + accountNumber); // Inform CardReaderFragment of received account number if (_messageCallback.TryGetTarget(out MessageCallback accountCallback)) { accountCallback.OnMessageRecieved(accountNumber); } } } catch (Exception e) { Log.Error(TAG, "Error communicating with card: " + e.Message); } } }
public byte[] SendReceive(string input) { byte[] command = HexStringToByteArray(input); // Send command to remote device //Console.WriteLine("Sending Command: " + ByteArrayToHexString(command)); byte[] result = isoDep.Transceive(command); //Console.WriteLine("Command returns: " + ByteArrayToHexString(result)); return(result); }
public void OnTagDiscovered(Tag tag) { IsoDep isoDep = IsoDep.Get(tag); if (isoDep == null) { Console.WriteLine("[CODE] Unsupported Tag"); //navigator.failureNavigation("Unsupported Tag"); } else { Console.WriteLine("[CODE] IsoDep Found"); isoDep.Connect(); byte[] command = BuildSelectApdu(ACCESS_CARD_AID); //Once we find a tag, trancieve the command try { byte[] result = isoDep.Transceive(command); // If the matching AID is successfully found, 0x9000 is returned from the device as the status word (last 2 // bytes of the result) (0x9000 is the OK Status Word - this is returned if the phone is authorised and the scan was successful). Everything before the status word is // payload, in this case will be the user ID - this means result will be dynamic int resultLength = result.Length; byte[] statusWord = { result[resultLength - 2], result[resultLength - 1] }; //Grab last two bytes for the status word byte[] payload = new byte[resultLength - 2]; //Initialise empty array payload Array.Copy(result, payload, resultLength - 2); //We know the lengths, so copy from those indexes into a new array bool arrayEquals = SELECT_OK_SW.Length == statusWord.Length; for (int i = 0; i < SELECT_OK_SW.Length && i < statusWord.Length && arrayEquals; i++) { arrayEquals = (SELECT_OK_SW[i] == statusWord[i]); //Compare byte by byte, ISO-DEP communcation is in bytes - we're looking for 0x90, 0x00 if (!arrayEquals) { break; } } if (arrayEquals) //Only if the status word is OK, unauthenticated devices will not respond with the "OK" status { // The NFC device will respond with the userId as a payload string payloadString = System.Text.Encoding.UTF8.GetString(payload); Console.WriteLine($"Recieved Payload: {payloadString}"); OnPayloadReceived(payloadString); } } catch (TagLostException e) //If something happens or the tag moves away, this is thrown. Close communication and inform user that an error occurred { isoDep.Close(); Console.WriteLine("[CODE] Caught tag loss error"); Device.BeginInvokeOnMainThread(async() => { await Xamarin.Forms.Application.Current.MainPage.DisplayAlert("Error", $"Tag Lost Error", "OK"); }); } } }
protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); Tag tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag; SetResult(Result.Canceled, intent); if (tag != null) { IsoDep isoTag = IsoDep.Get(tag); try { isoTag.Connect(); isoTag.Timeout = 30000; byte[] resp = isoTag.Transceive(selectCommand); int length = resp.Length; if (resp[length - 2] == (byte)0x90 && resp[length - 1] == 0x00) { DoChallengeYubiKey(isoTag, slot, challenge); } else { Toast.MakeText(this, Resource.String.yubichallenge_tag_error, ToastLength.Long) .Show(); } isoTag.Close(); } catch (TagLostException e) { Toast.MakeText(this, Resource.String.yubichallenge_lost_tag, ToastLength.Long) .Show(); } catch (IOException e) { Toast.MakeText(this, GetString(Resource.String.yubichallenge_tag_error) + e.Message, ToastLength.Long).Show(); } } else { SetResult(Result.Canceled, intent); } Finish(); }
public async void OnTagDiscovered(Tag tag) { IsoDep isoDep = IsoDep.Get(tag); if (isoDep != null) { try { isoDep.Connect(); var aidLength = (byte)(SAMPLE_LOYALTY_CARD_AID.Length / 2); var aidBytes = StringToByteArray(SAMPLE_LOYALTY_CARD_AID); var command = SELECT_APDU_HEADER .Concat(new byte[] { aidLength }) .Concat(aidBytes) .ToArray(); var result = isoDep.Transceive(command); var resultLength = result.Length; byte[] statusWord = { result[resultLength - 2], result[resultLength - 1] }; var payload = new byte[resultLength - 2]; Array.Copy(result, payload, resultLength - 2); var arrayEquals = SELECT_OK_SW.Length == statusWord.Length; if (Enumerable.SequenceEqual(SELECT_OK_SW, statusWord)) { var msg = Encoding.UTF8.GetString(payload); await App.DisplayAlertAsync(msg); } } catch (Exception e) { await App.DisplayAlertAsync("Error communicating with card: " + e.Message); } } }
public async void OnTagDiscovered(Tag tag) { IsoDep isoDep = IsoDep.Get(tag); // NfcA nfcA = NfcA.Get(tag); // //byte[] response = nfcA.Transceive(new byte[] { (byte)0x30, (byte)0x00 }); // nfcA.Connect(); // var aidLength2 = (byte)(SAMPLE_LOYALTY_CARD_AID.Length / 2); // var aidBytes2 = StringToByteArray(SAMPLE_LOYALTY_CARD_AID); // var command2 = SELECT_APDU_HEADER // .Concat(new byte[] { aidLength2 }) // .Concat(aidBytes2) // .ToArray(); // var result2 = nfcA.Transceive(new byte[] { // (byte)0x30, /* CMD = READ */ // (byte)0x10 /* PAGE = 16 */ //}); // string TagUid = ByteArrayToString(result2); // var resultLength2 = result2.Length; // byte[] statusWord2 = { result2[resultLength2 - 2], result2[resultLength2 - 1] }; // var payload2 = new byte[resultLength2 - 2]; // Array.Copy(result2, payload2, resultLength2 - 2); // var arrayEquals2 = SELECT_OK_SW.Length == statusWord2.Length; // var msg2 = Encoding.UTF8.GetString(payload2); // if (Enumerable.SequenceEqual(SELECT_OK_SW, statusWord2)) // { // var msg = Encoding.UTF8.GetString(payload2); // await App.DisplayAlertAsync(msg); // } if (isoDep != null) { try { isoDep.Connect(); var aidLength = (byte)(SAMPLE_LOYALTY_CARD_AID.Length / 2); var aidBytes = StringToByteArray(SAMPLE_LOYALTY_CARD_AID); var command = SELECT_APDU_HEADER .Concat(new byte[] { aidLength }) .Concat(aidBytes) .ToArray(); var result = isoDep.Transceive(command); var resultLength = result.Length; byte[] statusWord = { result[resultLength - 2], result[resultLength - 1] }; var payload = new byte[resultLength - 2]; Array.Copy(result, payload, resultLength - 2); var arrayEquals = SELECT_OK_SW.Length == statusWord.Length; if (Enumerable.SequenceEqual(SELECT_OK_SW, statusWord)) { var msg = Encoding.UTF8.GetString(payload); Imprime_box.Consulta_user(msg, ""); } } catch (Exception e) { Console.WriteLine(e.Message); //await App.DisplayAlertAsync("Error communicating with card: " + e.Message); } } }
/// <summary> /// Reads the travel card data from HSL Mifare DESFire card. /// </summary> /// <param name="card">The card to try to read.</param> /// <returns>A deserialized Travel Card object if the card was valid, otherwise null.</returns> public static async Task <TravelCard> ReadTravelCardAsync(IsoDep card) { try { card.Connect(); byte[] selection = card.Transceive(HslCommands.SelectHslCommand); if (selection != null && selection.Length > 0 && selection.SequenceEqual(HslCommands.OkResponse)) { // Travel card info bytes byte[] appInfo = null; byte[] periodPass = null; byte[] storedValue = null; byte[] eTicket = null; byte[] history = null; // Temporary containers for history chunks byte[] hist1 = new byte[2]; byte[] hist2 = new byte[2]; appInfo = await card.TransceiveAsync(HslCommands.ReadAppInfoCommand); periodPass = await card.TransceiveAsync(HslCommands.ReadPeriodPassCommand); storedValue = await card.TransceiveAsync(HslCommands.ReadStoredValueCommand); eTicket = await card.TransceiveAsync(HslCommands.ReadETicketCommand); hist1 = await card.TransceiveAsync(HslCommands.ReadHistoryCommand); // If we have more history, the last two bytes of the history array will contain the MORE_DATA bytes. if (hist1.Skip(Math.Max(0, hist1.Length - 2)).ToArray() == HslCommands.MoreData) { hist2 = await card.TransceiveAsync(HslCommands.ReadNextCommand); } // Combine the two history chunks into a single array, minus their last two MORE_DATA bytes history = hist1.Take(hist1.Length - 2) .Concat(hist2.Take(hist2.Length - 2)).ToArray(); var rawCard = new RawTravelCard(appInfo, periodPass, storedValue, eTicket, history); if (rawCard.Status == CardStatus.HslCardDataFailure) { System.Diagnostics.Debug.WriteLine("Failed to construct travel card. Data appears to be invalid."); return(null); } else { return(new TravelCard(rawCard)); } } else { System.Diagnostics.Debug.WriteLine("Failed to construct travel card. This doesn't seem to be an HSL Travel card."); return(null); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Failed to construct travel card. Reason: " + ex.ToString() + ".\nStack trace:" + ex.StackTrace); return(null); } finally { card.Close(); } }