public byte[] ReadPages(byte pageIndex, byte readSize = 0x04) { unchecked { var isFirstBlock = pageIndex == 0; var readBinaryCmd = new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any) { CLA = CUSTOM_CLA, Instruction = InstructionCode.ReadBinary, P1 = 0x00, P2 = pageIndex, Le = isFirstBlock ? 0x10 : readSize }; Console.WriteLineFormatted("--> Read MIFARE Block = {0}", Color.Blue, Color.White, pageIndex); Console.WriteLineFormatted("--> C-APDU: {0}", Color.Blue, Color.White, BitConverter.ToString(readBinaryCmd.ToArray())); var responses = _isoReader.Transmit(readBinaryCmd); DumpResponse(responses); if (IsSuccess(responses)) { return(responses.GetData()); } return(null); } }
static void Main(string[] args) { Console.OutputEncoding = Encoding.Unicode; using (var ctx = ContextFactory.Instance.Establish(SCardScope.User)) { var firstReader = ctx .GetReaders() .FirstOrDefault(); if (firstReader == null) { Console.WriteLine("No reader connected."); return; } using (var isoReader = new IsoReader(context: ctx, readerName: firstReader, mode: SCardShareMode.Shared, protocol: SCardProtocol.Any)) { var selectApdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol) { CLA = 0x00, INS = 0xA4, P1 = 0x04, P2 = 0x00, Data = new byte[] { 0xD1, 0x58, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11 }, Le = 0x00 }; Console.WriteLine("Send Select APDU command: \r\n{0}", BitConverter.ToString(selectApdu.ToArray())); var selectResponse = isoReader.Transmit(selectApdu); Console.WriteLine("SW1 SW2 = {0:X2} {1:X2}", selectResponse.SW1, selectResponse.SW2); var readProfileApdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol) { CLA = 0x00, INS = 0xCA, P1 = 0x11, P2 = 0x00, Data = new byte[] { 0x00, 0x00 }, Le = 0x00 }; Console.WriteLine("Send Read Profile APDU command: \r\n{0}", BitConverter.ToString(readProfileApdu.ToArray())); var profileResponse = isoReader.Transmit(readProfileApdu); Console.WriteLine("SW1 SW2 = {0:X2} {1:X2}", profileResponse.SW1, profileResponse.SW2); if (profileResponse.HasData) { var data = profileResponse.GetData(); var cardNumber = GetCardNumber(data[..12]);
private void submit_Click(object sender, RoutedEventArgs e) { try { using (var ctx = ContextFactory.Instance.Establish(SCardScope.User)) { var firstReader = ctx .GetReaders() .FirstOrDefault(); if (firstReader == null) { System.Diagnostics.Debug.WriteLine("No reader connected."); return; } using (var isoReader = new IsoReader(context: ctx, readerName: firstReader, mode: SCardShareMode.Shared, protocol: SCardProtocol.Any)) { var selectApdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol) { CLA = 0x00, INS = 0xA4, P1 = 0x04, P2 = 0x00, Data = new byte[] { 0xD1, 0x58, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11 }, Le = 0x00 }; System.Diagnostics.Debug.WriteLine("Send Select APDU command: \r\n{0}", BitConverter.ToString(selectApdu.ToArray())); var selectResponse = isoReader.Transmit(selectApdu); System.Diagnostics.Debug.WriteLine("SW1 SW2 = {0:X2} {1:X2}", selectResponse.SW1, selectResponse.SW2); var readProfileApdu = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol) { CLA = 0x00, INS = 0xCA, P1 = 0x11, P2 = 0x00, Data = new byte[] { 0x00, 0x00 }, Le = 0x00 }; System.Diagnostics.Debug.WriteLine("Send Read Profile APDU command: \r\n{0}", BitConverter.ToString(readProfileApdu.ToArray())); var profileResponse = isoReader.Transmit(readProfileApdu); System.Diagnostics.Debug.WriteLine("SW1 SW2 = {0:X2} {1:X2}", profileResponse.SW1, profileResponse.SW2); if (profileResponse.HasData) { var data = profileResponse.GetData(); var cardNumber = GetCardNumber(data[..12]);
private void Monitor_CardInserted(object sender, CardStatusEventArgs e) { var contextFactory = ContextFactory.Instance; try { using (var ctx = contextFactory.Establish(SCardScope.System)) { using (var isoReader = new IsoReader(ctx, monitor.ReaderNames[0], SCardShareMode.Shared, SCardProtocol.Any, false)) { var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) { CLA = 0xFF, Instruction = (InstructionCode)0xCA, P1 = 0x00, P2 = 0x00, Le = 0x00 }; var response = isoReader.Transmit(apdu); var data = response.GetData(); UidReceived(this, new CardUidReceivedEventArgs(data)); LogAction?.Invoke("SCardWatcher Received : " + BitConverter.ToString(data)); } } } catch (Exception ex) { LogAction?.Invoke("SCardWatcher Error - " + ex); } }
public void UpdateBinary(byte msb, byte lsb, byte[] data) { var isoReader = new IsoReader( ContextFactory.Instance.Establish(SCardScope.System), _reader, SCardShareMode.Shared, SCardProtocol.Any, false); var updateBinaryCmd = new CommandApdu(IsoCase.Case3Short, SCardProtocol.Any) { CLA = CustomCla, Instruction = InstructionCode.UpdateBinary, P1 = msb, P2 = lsb, Data = data }; //Debug.WriteLine($"Update Binary: {BitConverter.ToString(updateBinaryCmd.ToArray())}"); var response = isoReader.Transmit(updateBinaryCmd); //Debug.WriteLine($"SW1 SW2 = {response.SW1:X2} {response.SW2:X2}"); if ((response.SW1 == (byte)SW1Code.Normal) && (response.SW2 == 0x00)) { return; } else { throw new InvalidOperationException("Update binary failed"); } }
private void WriteAllCardBytes(IsoReader isoReader, byte[] bytes, int packetSize) { var bytesToWrite = new List <byte>(bytes); //while (bytesToWrite.Count < 38 * 4) // bytesToWrite.Add(0x00); while (bytesToWrite.Count % packetSize != 0) { bytesToWrite.Add(0x00); } for (int i = 0; i < bytesToWrite.Count / packetSize; i++) { var updateBinaryCmd = new CommandApdu(IsoCase.Case3Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.UpdateBinary, P1 = 0x00, P2 = (byte)((16 / packetSize) + i), Data = bytesToWrite.Skip(i * packetSize).Take(packetSize).ToArray() }; var response = isoReader.Transmit(updateBinaryCmd); Console.WriteLine("UpdateBinary: {0},{1}", response.SW1, response.SW2); } }
private IsoReader GetReader(ref bool iSSecureElement) { IsoReader reader; // Establish SCard context SCardContext hContext = new SCardContext(); hContext.Establish(SCardScope.System); // Retrieve the list of Smartcard readers string[] szReaders = hContext.GetReaders(); // Create a reader object using the existing context reader = new IsoReader(hContext); // Connect to the card foreach (var sZReader in szReaders) { reader.Connect(sZReader, SCardShareMode.Shared, SCardProtocol.T0 | SCardProtocol.T1); var response = reader.Transmit(GetSelectAppBytes(reader)); if (response.SW1 == 0x90) { iSSecureElement = true; break; } } return(reader); }
public APDUResponse SendAPDU(string reader, APDURequest request) { using (var context = new SCardContext()) { context.Establish(SCardScope.System); using (var isoReader = new IsoReader(context, reader, SCardShareMode.Shared, SCardProtocol.Any)) { var apdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol) { CLA = request.CLA, // Class INS = request.INS, //Instruction P1 = request.P1, // Parameter 1 P2 = request.P2, // Parameter 2 Data = request.Data }; byte[] id = null; var response = isoReader.Transmit(apdu); return(new APDUResponse() { Data = response.GetData(), SW1 = response.SW1, SW2 = response.SW2 }); }; } }
private static void Main() { var contextFactory = ContextFactory.Instance; using (var ctx = contextFactory.Establish(SCardScope.System)) { var readerNames = ctx.GetReaders(); if (NoReaderFound(readerNames)) { Console.WriteLine("You need at least one reader in order to run this example."); Console.ReadKey(); return; } var name = ChooseReader(readerNames); if (name == null) { return; } using (var isoReader = new IsoReader( context: ctx, readerName: name, mode: SCardShareMode.Shared, protocol: SCardProtocol.Any, releaseContextOnDispose: false)) { // Build a GET CHALLENGE command var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) { CLA = 0x00, // Class Instruction = InstructionCode.GetChallenge, P1 = 0x00, // Parameter 1 P2 = 0x00, // Parameter 2 Le = 0x08 // Expected length of the returned data }; Console.WriteLine("Send APDU with \"GET CHALLENGE\" command: {0}", BitConverter.ToString(apdu.ToArray())); var response = isoReader.Transmit(apdu); Console.WriteLine("SW1 SW2 = {0:X2} {1:X2}", response.SW1, response.SW2); if (!response.HasData) { Console.WriteLine("No data. (Card does not understand \"GET CHALLENGE\")"); } else { var data = response.GetData(); Console.WriteLine("Challenge: {0}", BitConverter.ToString(data)); } } } Console.ReadKey(); }
/// <summary> /// The implementation of transmit with log /// </summary> /// <param name="reader">Reader Name</param> /// <param name="command">APDU command</param> /// <returns></returns> public static Response TransmitWithLog(this IsoReader reader, CommandApdu command) { SCardPCI receivePci = new SCardPCI(); // IO returned protocol control information. IntPtr sendPci = SCardPCI.GetPci(reader.ActiveProtocol); #if DEBUG System.Diagnostics.Debug.WriteLine(StringTools.ByteArrayToHexString(command.ToArray())); #endif var res = reader.Transmit(command); // data buffer #if DEBUG System.Diagnostics.Debug.WriteLine(StringTools.ByteArrayToHexString(res.GetData())); #endif if (res.SW1 != 0x61) { return(res); } CommandApdu apdu2 = new CommandApdu(IsoCase.Case2Short, reader.ActiveProtocol) { CLA = new ClassByte(ClaHighPart.Iso0x, SecureMessagingFormat.None, 0), Instruction = InstructionCode.GetResponse, P1 = 0x00, P2 = 00, Le = res.SW2 }; #if DEBUG System.Diagnostics.Debug.WriteLine(StringTools.ByteArrayToHexString(apdu2.ToArray())); #endif res = reader.Transmit(apdu2); #if DEBUG System.Diagnostics.Debug.WriteLine(StringTools.ByteArrayToHexString(res.GetData())); #endif return(res); }
private byte[] GetAllCardBytes(IsoReader reader, int packetSize) { try { var firstDataBlock = 16 / packetSize; var readSize = 16; var bytesToRead = 0; var buffer = new List <byte>(); while (true) { var blockToRead = (byte)(firstDataBlock + (buffer.Count / packetSize)); var readBinaryCmd = new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.ReadBinary, P1 = 0x00, P2 = blockToRead, Le = readSize }; var response = reader.Transmit(readBinaryCmd); var data = response.GetData(); if (buffer.Count == 0) { bytesToRead = data[1] + 1 + 1; } buffer.AddRange(data.Take(bytesToRead - buffer.Count < readSize ? bytesToRead - buffer.Count : readSize).ToArray()); if (buffer.Count >= bytesToRead) { break; } } Log.Debug(String.Format("ReadBinary: {0}", BitConverter.ToString(buffer.ToArray()))); Log.Debug(String.Format("Buffersize: Reported: {0}, Actual: {1}", bytesToRead, buffer.Count)); return(buffer.ToArray()); } catch (Exception ex) { Log.Error(ex); } return(new byte[0]); }
public void GetSingleApplication(byte[] aid) { CommandApdu apdu = new CommandApdu(IsoCase.Case4Short, reader.ActiveProtocol); apdu.CLA = new ClassByte(ClaHighPart.Iso0x, SecureMessagingFormat.None, 0); apdu.Instruction = InstructionCode.SelectFile; apdu.P1 = 0x04; //select by name apdu.P2 = 00; // First or only occurrence apdu.Data = aid; System.Diagnostics.Debug.WriteLine(StringTools.ByteArrayToHexString(apdu.ToArray())); Response res = reader.Transmit( apdu); if (res.SW1 == 0x90) { Applications.Add(new SmartApplication(res.GetData(), reader)); } else { throw new PCSCException(SCardError.FileNotFound, "Select command failed"); } }
private async void FormatCardAsync() { try { DispatcherUpdater(FormatingViewGrid, Visibility.Visible); using (var context = _contextFactory.Establish(SCardScope.System)) { using (var isoReader = new IsoReader(context, LoadedBChips.ReaderName, SCardShareMode.Shared, SCardProtocol.Any)) { if (LoadedBChips.AdpuInterface.RequiresInit) { Response initResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.InitCard()); if (initResponse.SW1 != 0x90) { Logger.Log("Error initializing smart card reader"); } } var unlockResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.UnblockCard()); Logger.Log($"ADPU response from pin request: {unlockResponse.StatusWord:X}"); var writeResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.FormatCard(CardType.BChip)); Logger.Log($"ADPU response from format request: {unlockResponse.StatusWord:X}"); } } LoadedBChips = null; } catch (Exception ex) { Logger.Log(ex); } finally { DispatcherUpdater(FormatingViewGrid, Visibility.Collapsed); ScanAndLoadConnectedCards(); } }
public byte[] GetCardId(IsoReader reader) { var command = new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.GetData, P1 = 0x00, P2 = 0x00, Le = 0x00 }; var response = reader.Transmit(command); return(response.GetData()); }
private byte[] SendCommand(CommandApdu command) { var response = reader.Transmit(command); if (!response.HasData) { return new byte[] { response.SW1, response.SW2 } } ; var data = response.GetData(); var result = new byte[data.Length + 2]; Buffer.BlockCopy(data, 0, result, 0, data.Length); result[result.Length - 2] = response.SW1; result[result.Length - 1] = response.SW2; return(result); }
public static void ReadCard(SCardContext context, string reader, ref string tes) { IsoReader isoReader = new IsoReader(context, reader, SCardShareMode.Shared, SCardProtocol.Any); var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) { CLA = 0xff, // Class. INS = 0xCA, // what instrution you are using. P1 = 0x00, // Parameter 1. P2 = 0x00, // Parameter 2. Le = 0x4 // Length of the return value. }; Response test = isoReader.Transmit(apdu); uID = BitConverter.ToString(test.GetData()); string[] a = uID.Split('-'); Array.Reverse(a); parrent.CardInserted(string.Join("", a)); }
public void ReadData() { var contextFactory = ContextFactory.Instance; using (var ctx = contextFactory.Establish(SCardScope.System)) { using (var isoReader = new IsoReader(ctx, readerName, SCardShareMode.Shared, SCardProtocol.Any, false)) { var updateBinaryCmd = new CommandApdu(IsoCase.Case3Short, SCardProtocol.Any) { CLA = 0xFF, INS = 0xCA, P1 = 0x00, P2 = 0x00 }; var response = isoReader.Transmit(updateBinaryCmd); Console.WriteLine(response.GetData()); Console.WriteLine("SW1 SW2 = {0:X2} {1:X2}", response.SW1, response.SW2); } } }
private static void SetBuzzerState(string readerName, bool enabled) { Console.Write("Setting buzzer state... "); using var ctx = ContextFactory.Instance.Establish(SCardScope.System); using var isoReader = new IsoReader(ctx, readerName, SCardShareMode.Shared, SCardProtocol.Any, false); var p2 = enabled ? (byte)0xFF : (byte)0x00; // Set buzzer output during card detection var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) { CLA = 0xFF, // Class Instruction = 0x00, // Insruction P1 = 0x52, // Parameter 1 P2 = p2, // Parameter 2 - 00h: Buzzer will NOT turn on when a card is detected // FFh: Buzzer will turn on when a card is detected Le = 0x00 // Expected length of the returned data }; var response = isoReader.Transmit(apdu); Console.WriteLine(response.SW1 == 0x90 && response.SW2 == 0x00 ? "Success!" : "ERROR"); }
private void ScanAndLoadConnectedCards(BChipSmartCard insertedCard = null) { using (var context = _contextFactory.Establish(SCardScope.System)) { if (insertedCard == null) { List <string> readerNames = GetReaderNames().ToList(); foreach (string curReader in readerNames) { try { using (var reader = context.ConnectReader(curReader, SCardShareMode.Shared, SCardProtocol.Any)) { insertedCard = new BChipSmartCard(curReader) { ATR = reader.GetAttrib(SCardAttribute.AtrString), LastConnected = DateTime.Now, IsConnected = true }; } if (insertedCard.Type() != CardType.BChip) { Logger.Log($"Card type was not an expected BChip and skipped ({insertedCard.Type()})"); continue; } } // We try to check for an inserted card, eat errors. catch (Exception ex) { if ((uint)ex.HResult == 0x80131500) { // ignore card removed continue; } } } } if (insertedCard == null) { ChangePageUi(PageToShow.NoCard, null); } if (insertedCard != null) { using (var isoReader = new IsoReader(context, insertedCard.ReaderName, SCardShareMode.Shared, SCardProtocol.Any)) { try { if (insertedCard.AdpuInterface.RequiresInit) { Response initResponse = isoReader.Transmit(insertedCard.AdpuInterface.InitCard()); if (initResponse.SW1 != 0x90) { Logger.Log("Error initializing smart card reader"); } } Response response = isoReader.Transmit(insertedCard.AdpuInterface.ReadCard()); if (response.HasData) { byte[] data = response.GetData(); byte[] mlvi = data.Skip(0x20).Take(BChipMemoryLayout_BCHIP.MLVI_MAX_DATA).ToArray(); byte[] carddata = data.Skip(0x28).ToArray(); // At this stage, the card has not yet been validated/parsed. Another thread should handle cleanup/de-dupes insertedCard.SmartCardData = new BChipMemoryLayout_BCHIP(mlvi, carddata, PKStatus.NotValidated); LoadedBChips = insertedCard; ChangePageUi(AnalyzeCardData(insertedCard), insertedCard); } else { Logger.Log("Card added had no data to download"); // TODO: Add card data could not be loaded (not CRC error) } } catch (Exception ex) { Logger.Log(ex); }; } } } }
public void SignInvoice() { #region Data used to create Invoice Request //ISO8601 DateTime "2017-07-25T10:17:18.953Z" converted to miliseconds var dateTime = ConvertUInt64To8ByteBigEndianArray(1500977838953); //TIN "021131682" var taxpayerId = new byte[20] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x32, 0x31, 0x31, 0x33, 0x31, 0x36, 0x38, 0x32 }; //Buyer TIN "" var buyerId = new byte[20] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Invoice Type "Normal" var invoiceType = new byte[1] { 0x00 }; //Transaction Type "Sale" var transactionType = new byte[1] { 0x00 }; //Total Invoice Amount "240" var invoiceAmount = ConvertAmountToUInt64_8ByteBigEndianArray(240); //Number of tax categories used in invoice request "1" var categoryCountOninvoice = new byte[1] { 0x01 }; //Tax Category position e.g. VAT "3" var taxCategory = new byte[1] { 0x03 }; //Amount of tax category VAT "13.5849" var taxCategoryAmount = ConvertAmountToUInt64_8ByteBigEndianArray(13.5849m); #endregion #region Prepare Sign Invoice request var payload = new byte[68]; dateTime.CopyTo(payload, 0); taxpayerId.CopyTo(payload, 8); buyerId.CopyTo(payload, 28); invoiceType.CopyTo(payload, 48); transactionType.CopyTo(payload, 49); invoiceAmount.CopyTo(payload, 50); categoryCountOninvoice.CopyTo(payload, 58); taxCategory.CopyTo(payload, 59); taxCategoryAmount.CopyTo(payload, 60); #endregion #region Send Pin Verify Command var iSSecureElement = false; IsoReader reader = GetReader(ref iSSecureElement); var responseSCard = reader.Transmit(PINVerify(reader)); Assert.AreEqual(responseSCard.SW1, (byte)SW1Code.Normal); #endregion Send Pin Verify Command #region Send Sign Invoice command responseSCard = reader.Transmit(SignInvoiceCommand(reader, payload)); Assert.AreEqual(responseSCard.SW1, (byte)SW1Code.Normal); #endregion }
public String GetCardNumber() { try { var contextFactory = ContextFactory.Instance; using (var ctx = contextFactory.Establish(SCardScope.System)) { var readerNames = ctx.GetReaders(); var name = readerNames[0]; using (var isoReader = new IsoReader( context: ctx, readerName: name, mode: SCardShareMode.Shared, protocol: SCardProtocol.Any, releaseContextOnDispose: false)) { //Seleziono il master file var apduMaster = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol) { CLA = 0x00, // Class Instruction = InstructionCode.SelectFile, P1 = 0x00, // Parameter 1 P2 = 0x00, // Parameter 2 Data = new byte[] { 0x3F, 0x00 } }; var responseMaster = isoReader.Transmit(apduMaster); //Seleziono la cartella var apduFolder = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol) { CLA = 0x00, // Class Instruction = InstructionCode.SelectFile, P1 = 0x00, // Parameter 1 P2 = 0x00, // Parameter 2 Data = new byte[] { 0x10, 0x00 } }; var responseFolder = isoReader.Transmit(apduFolder); //Seleziono il file id tessera var apduId = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol) { CLA = 0x00, // Class Instruction = InstructionCode.SelectFile, P1 = 0x00, // Parameter 1 P2 = 0x00, // Parameter 2 Data = new byte[] { 0x10, 0x03 } }; var responseId = isoReader.Transmit(apduId); //Leggo il file id tessera var apduRead = new CommandApdu(IsoCase.Case4Short, isoReader.ActiveProtocol) { CLA = 0x00, // Class Instruction = InstructionCode.ReadBinary, P1 = 0x00, // Parameter 1 P2 = 0x00, // Parameter 2 Data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; var responseRead = isoReader.Transmit(apduRead); if (!responseRead.HasData) { return(""); } else { var data = responseRead.GetData(); return(System.Text.Encoding.ASCII.GetString(data)); } } } } catch (Exception) { return(""); } }
private void MnemonicProvisionCardButton_Click(object sender, RoutedEventArgs e) { MnemonicErrorLabel.Content = ""; MnemonicKeyLabel.Content = ""; if (Mnemonicpassphrase.Password.Length == 0 || MnemonicpassphraseConfirmation.Password.Length == 0) { MnemonicErrorLabel.Content = "A passphrase was not entered."; return; } if (Mnemonicpassphrase.Password != MnemonicpassphraseConfirmation.Password) { MnemonicErrorLabel.Content = "Passphrases entered did not match."; return; } if (MnemonicEntryTextBox.Text.Length == 0) { MnemonicErrorLabel.Content = "No private key data to store."; return; } if (CardPkType != PKType.Mnemonic) { MnemonicErrorLabel.Content = "Invalid application state. Please restart app."; return; } byte[] privateKeyToEncrypt = null; byte[] publicKeyData = CryptographicBuffer.ConvertStringToBinary("Mnemonic seed backed up.", BinaryStringEncoding.Utf8).ToArray(); try { privateKeyToEncrypt = BIP39Helpers.GenerateEntropyFromWords(MnemonicEntryTextBox.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries), NBitcoin.Wordlist.English); } // TODO: Implement better exception types to ease debugging catch (Exception ex) { Logger.Log(ex); MnemonicErrorLabel.Content = "Failed to automatically parse mnemonic phrase."; return; } if (privateKeyToEncrypt.Length > BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA) { CreateKeyErrorLabel.Content = $"Private key was {PrivateKeyTextBox.Text.Length} bytes, {Math.Abs(PrivateKeyTextBox.Text.Length - BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA)} bytes over the limit."; return; } string friendlyName = MnemonicFriendlyNameTextBox.Text; ProvisionMnemonicPhraseViewGrid.Dispatcher.BeginInvoke(new Action(() => { ProvisionMnemonicPhraseViewGrid.IsEnabled = false; })); Task.Run(new Action(() => { try { UpdateTextLabel(MnemonicKeyLabel, "Setting up bChip! Do not remove card."); // Encrypt data BChipMemoryLayout_BCHIP bchip = LoadedBChips.SmartCardData as BChipMemoryLayout_BCHIP; bchip.EncryptPrivateKeyData(CardPkType, Mnemonicpassphrase.Password, privateKeyToEncrypt, publicKeyData); bchip.SetFriendlyName(friendlyName); using (var context = _contextFactory.Establish(SCardScope.System)) { using (var isoReader = new IsoReader(context, LoadedBChips.ReaderName, SCardShareMode.Shared, SCardProtocol.Any)) { if (LoadedBChips.AdpuInterface.RequiresInit) { Response initResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.InitCard()); if (initResponse.SW1 != 0x90) { Logger.Log("Error initializing smart card reader"); } } var unlockResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.UnblockCard()); Logger.Log($"ADPU response from pin request: {unlockResponse.StatusWord:X}"); if (unlockResponse.SW1 != 0x90) { UpdateTextLabel(MnemonicKeyLabel, ""); UpdateTextLabel(MnemonicErrorLabel, "Could not be unlock bchip for writing."); return; } var writeResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.WriteCard(bchip)); Logger.Log($"ADPU response from write card data: {unlockResponse.StatusWord:X}"); if (writeResponse.SW1 != 0x90) { UpdateTextLabel(MnemonicKeyLabel, ""); UpdateTextLabel(MnemonicErrorLabel, "Failure writing data to the bchip."); return; } } } UpdateTextLabel(MnemonicKeyLabel, string.Empty); ClearTextBox(MnemonicFriendlyNameTextBox); // Done? clear loaded card, reload card LoadedBChips = null; ScanAndLoadConnectedCards(); } catch (Exception ex) { Logger.Log(ex); } finally { ProvisionMnemonicPhraseViewGrid.Dispatcher.BeginInvoke(new Action(() => { ProvisionMnemonicPhraseViewGrid.IsEnabled = true; })); } })); }
private void ProvisionCardButton_Click(object sender, RoutedEventArgs e) { CreateKeyErrorLabel.Content = ""; CreatingKeyLabel.Content = ""; if (passphrase.Password.Length == 0 || passphraseConfirmation.Password.Length == 0) { CreateKeyErrorLabel.Content = "A passphrase was not entered."; return; } if (passphrase.Password != passphraseConfirmation.Password) { CreateKeyErrorLabel.Content = "Passphrases entered did not match."; return; } if (PrivateKeyTextBox.Text.Length == 0) { CreateKeyErrorLabel.Content = "No private key data to store."; return; } if (CardPkType == PKType.BTC || CardPkType == PKType.BTC_TestNet) { // Check if we are importing a user's wif or mnemonic, update public key field // to allow the user to confirm if (CardGeneratedKey.GetBitcoinSecret(Network).ToWif() != PrivateKeyTextBox.Text) { try { NBitcoin.Key importedKey = null; int spacesDetected = PrivateKeyTextBox.Text.Count(a => a == ' '); // Check for mnemonic if (spacesDetected >= 11) { NBitcoin.Mnemonic mnemonic = new NBitcoin.Mnemonic(PrivateKeyTextBox.Text); // Force bitcoin and first address importedKey = mnemonic.DeriveExtKey().Derive(KeyPath.Parse("m/44'/0'/0'/0/0")).PrivateKey; } else { // Check for wif importedKey = NBitcoin.Key.Parse(PrivateKeyTextBox.Text); } // Replace CardGeneratedKey with imported key. Only valid for bitcoin addresses. CardGeneratedKey = importedKey; PublicKeyTextBox.Text = importedKey.PubKey.GetAddress(Network).ToString(); PrivateKeyTextBox.Text = importedKey.GetBitcoinSecret(Network).ToWif(); CreatingKeyLabel.Content = "Key data imported, ready to setup your bChip."; return; } catch (Exception ex) { Logger.Log(ex); CreateKeyErrorLabel.Content = "Failed to automatically parse private key data."; return; } } } byte[] privateKeyToEncrypt = null; byte[] publicKeyData = null; if (CardGeneratedKey != null) { // Users can optionally remove the public key portion, so we'll skip saving it. if (PublicKeyTextBox.Text.Length > 0) { publicKeyData = CardGeneratedKey.PubKey.ToBytes(); } byte[] privateKeyBytes = CardGeneratedKey.GetWif(Network.Main).ToBytes(); // Always seem to get an extra bit at the end... if (privateKeyBytes.Length == 33 && privateKeyBytes[32] == 0x1) { privateKeyToEncrypt = privateKeyBytes.Take(32).ToArray(); } else { privateKeyToEncrypt = privateKeyBytes; } } else { if (PublicKeyTextBox.Text.Length > 0) { publicKeyData = CryptographicBuffer.ConvertStringToBinary(PublicKeyTextBox.Text, BinaryStringEncoding.Utf8).ToArray(); } privateKeyToEncrypt = CryptographicBuffer.ConvertStringToBinary(PrivateKeyTextBox.Text, BinaryStringEncoding.Utf8).ToArray(); } if (privateKeyToEncrypt.Length > BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA) { CreateKeyErrorLabel.Content = $"Private key was {PrivateKeyTextBox.Text.Length} bytes, {Math.Abs(PrivateKeyTextBox.Text.Length - BChipMemoryLayout_BCHIP.PRIVATEKEY_MAX_DATA)} bytes over the limit."; return; } if (publicKeyData != null) { if (publicKeyData.Length > BChipMemoryLayout_BCHIP.PUBKEY_MAX_DATA) { CreateKeyErrorLabel.Content = $"Public key was {PublicKeyTextBox.Text.Length} bytes, {Math.Abs(PublicKeyTextBox.Text.Length - BChipMemoryLayout_BCHIP.PUBKEY_MAX_DATA)} bytes over the limit."; return; } } string friendlyName = FriendlyNameTextBox.Text; ProvisionNewKeysViewGrid.Dispatcher.BeginInvoke(new Action(() => { ProvisionNewKeysViewGrid.IsEnabled = false; })); Task.Run(new Action(() => { try { UpdateTextLabel(CreatingKeyLabel, "Setting up bChip! Do not remove card."); // Encrypt data BChipMemoryLayout_BCHIP bchip = LoadedBChips.SmartCardData as BChipMemoryLayout_BCHIP; bchip.EncryptPrivateKeyData(CardPkType, passphrase.Password, privateKeyToEncrypt, publicKeyData); bchip.SetFriendlyName(friendlyName); using (var context = _contextFactory.Establish(SCardScope.System)) { using (var isoReader = new IsoReader(context, LoadedBChips.ReaderName, SCardShareMode.Shared, SCardProtocol.Any)) { if (LoadedBChips.AdpuInterface.RequiresInit) { Response initResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.InitCard()); if (initResponse.SW1 != 0x90) { Logger.Log("Error initializing smart card reader"); } } var unlockResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.UnblockCard()); Logger.Log($"ADPU response from pin request: {unlockResponse.StatusWord:X}"); if (unlockResponse.SW1 != 0x90) { UpdateTextLabel(CreatingKeyLabel, ""); UpdateTextLabel(CreateKeyErrorLabel, "Could not be unlock bchip for writing."); return; } var writeResponse = isoReader.Transmit(LoadedBChips.AdpuInterface.WriteCard(bchip)); Logger.Log($"ADPU response from write card data: {unlockResponse.StatusWord:X}"); if (writeResponse.StatusWord != 0x00009000) { UpdateTextLabel(CreatingKeyLabel, ""); UpdateTextLabel(CreateKeyErrorLabel, "Failure writing data to the bchip."); return; } } } UpdateTextLabel(CreatingKeyLabel, string.Empty); ClearTextBox(FriendlyNameTextBox); // Done? clear loaded card, reload card LoadedBChips = null; ChangePageUi(PageToShow.NoCard, null); ScanAndLoadConnectedCards(); } catch (Exception ex) { Logger.Log(ex); } finally { ProvisionNewKeysViewGrid.Dispatcher.BeginInvoke(new Action(() => { ProvisionNewKeysViewGrid.IsEnabled = true; })); } })); }
// ---------------------------------------------------------------------- private void Monitor_CardInserted(object sender, CardStatusEventArgs e) { logger.Trace("card inserted:"); try { using (var context = ContextFactory.Instance.Establish(SCardScope.System)) { using (var isoReader = new IsoReader( context: context, readerName: readerName, mode: SCardShareMode.Shared, protocol: SCardProtocol.Any, releaseContextOnDispose: true)) { // get UID var command = new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.GetData, P1 = 0x00, P2 = 0x00, Le = 0 // We don't know the ID tag size }; logger.Debug(command.Log()); var response = isoReader.Transmit(command); if (response.Count > 0 && response.StatusWord == 0x9000) { logger.Debug(command.LogData(response)); } else { logger.Debug(command.Log(response)); } // load key command = new CommandApdu(IsoCase.Case3Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.ExternalAuthenticate, P1 = 0x00, P2 = 0x00, Data = new byte[6] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; logger.Debug(command.Log()); response = isoReader.Transmit(command); logger.Debug(command.Log(response)); // authenticate command = new CommandApdu(IsoCase.Case3Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.InternalAuthenticate, P1 = 0x00, P2 = 0x00, Data = new byte[5] { 0x01, 0x00, 0x01, 0x60, 0x00 } }; logger.Debug(command.Log()); response = isoReader.Transmit(command); logger.Debug(command.Log(response)); // read data command = new CommandApdu(IsoCase.Case2Short, SCardProtocol.Any) { CLA = 0xFF, Instruction = InstructionCode.ReadBinary, P1 = 0x00, P2 = 0x01, Le = 0x10 }; logger.Debug(command.Log()); response = isoReader.Transmit(command); if (response.Count > 0 && response.StatusWord == 0x9000) { logger.Debug(command.LogData(response)); } else { logger.Debug(command.Log(response)); } } } } catch (Exception ex) { logger.Error(ex); } }