Exemplo n.º 1
0
 public HwiDeviceClient(HwiClient hwiClient, DeviceSelector deviceSelector, HardwareWalletModels model, HDFingerprint?fingerprint)
 {
     HwiClient      = hwiClient ?? throw new ArgumentNullException(nameof(hwiClient));
     DeviceSelector = deviceSelector ?? throw new ArgumentNullException(nameof(deviceSelector));
     Model          = model;
     Fingerprint    = fingerprint;
 }
Exemplo n.º 2
0
        // DeviceSelector is keijiro's library.
        // injected with zenject binding on hierarchy
        // TODO: simple data flow
        public TimecodeDecoderRepository(DeviceSelector audioDeviceSelector)
        {
            this.deviceSelector = audioDeviceSelector;
            audioDeviceSelector.Initialize();

            SetSavedValuesToDropdown(); // because of dropdown initialization is not stable order
        }
Exemplo n.º 3
0
        internal async Task <string> SendCommandAsync(DeviceSelector deviceSelector, IEnumerable <HwiOption> options, HwiCommands?command, string[] commandArguments, CancellationToken cancel)
        {
            try
            {
                return(await SendCommandCoreAsync(deviceSelector, options, command, commandArguments, cancel).ConfigureAwait(false));
            }
            catch (Exception ex) when(ex is OperationCanceledException || ex is TaskCanceledException || ex is TimeoutException)
            {
                throw new OperationCanceledException($"'hwi operation is canceled.", ex);
            }
            // HWI is inconsistent with error codes here.
            catch (HwiException ex) when(ex.ErrorCode == HwiErrorCode.DeviceConnError || ex.ErrorCode == HwiErrorCode.DeviceNotReady)
            {
                // Probably didn't find device with specified fingerprint.
                // Enumerate and call again, but not forever.
                if (!(deviceSelector is FingerprintDeviceSelector))
                {
                    throw;
                }

                IEnumerable <HwiEnumerateEntry> hwiEntries = await EnumerateEntriesAsync(cancel);

                // Trezor T won't give Fingerprint info so we'll assume that the first device that doesn't give fingerprint is what we need.
                HwiEnumerateEntry firstNoFingerprintEntry = hwiEntries.Where(x => x.Fingerprint is null).FirstOrDefault();

                if (firstNoFingerprintEntry is null)
                {
                    throw;
                }
                deviceSelector = DeviceSelectors.FromDeviceType(firstNoFingerprintEntry.Model, firstNoFingerprintEntry.Path);
                return(await SendCommandCoreAsync(deviceSelector, options, command, commandArguments, cancel).ConfigureAwait(false));
            }
        }
Exemplo n.º 4
0
        private async Task <string> SendCommandCoreAsync(DeviceSelector deviceSelector       = null,
                                                         IEnumerable <HwiOption> options     = null,
                                                         HwiCommands?command                 = null,
                                                         string[] commandArguments           = null,
                                                         CancellationToken cancellationToken = default)
        {
            var arguments = HwiParser.ToArgumentString(deviceSelector, Network, options, command, commandArguments);
            var response  = await Transport.SendCommandAsync(arguments, cancellationToken).ConfigureAwait(false);

            ThrowIfError(response);
            return(response);
        }
Exemplo n.º 5
0
        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            var devices = await _capture.GetDevicesAsync();

            var binding = new Binding
            {
                Mode   = BindingMode.OneTime,
                Source = devices
            };

            BridgeSelector.IsEnabled = false;
            DeviceSelector.SetBinding(ComboBox.ItemsSourceProperty, binding);
        }
Exemplo n.º 6
0
        private bool SameSelector(DeviceSelector a, DeviceSelector b)
        {
            var aargs = new List <string>();

            a.AddArgs(aargs);
            var bargs = new List <string>();

            b.AddArgs(bargs);
            if (aargs.Count != bargs.Count)
            {
                return(false);
            }
            for (int i = 0; i < aargs.Count; i++)
            {
                if (aargs[i] != bargs[i])
                {
                    return(false);
                }
            }
            return(true);
        }
 public HwiEnumerateEntry(
     HardwareWalletModels model,
     string path,
     string serialNumber,
     HDFingerprint?fingerprint,
     bool?needsPinSent,
     bool?needsPassphraseSent,
     string error,
     HwiErrorCode?code)
 {
     Model               = model;
     Path                = path;
     SerialNumber        = serialNumber;
     Fingerprint         = fingerprint;
     NeedsPinSent        = needsPinSent;
     NeedsPassphraseSent = needsPassphraseSent;
     Error               = error;
     Code                = code;
     DeviceSelector      = fingerprint is HDFingerprint fp?DeviceSelectors.FromFingerprint(fp) :
                               DeviceSelectors.FromDeviceType(Model, path);
 }
Exemplo n.º 8
0
        internal static string[] ToArgumentString(DeviceSelector deviceSelector, Network network, IEnumerable <HwiOption> options, HwiCommands?command, string[] commandArguments)
        {
            List <string> arguments = new List <string>();

            options ??= Enumerable.Empty <HwiOption>();
            var fullOptions = new List <HwiOption>(options);

            chainNames.TryGetValue(network.ChainName, out var val);
            val ??= network.ChainName.ToString().ToLowerInvariant();
            arguments.Add("--chain");
            arguments.Add(val);

            foreach (var option in fullOptions)
            {
                arguments.Add($"--{option.Type.ToString().ToLowerInvariant()}");
                if (!string.IsNullOrEmpty(option.Arguments))
                {
                    arguments.Add(option.Arguments);
                }
            }

            deviceSelector?.AddArgs(arguments);
            if (command != null)
            {
                arguments.Add(command.ToString().ToLowerInvariant());
            }

            if (commandArguments != null)
            {
                foreach (var commandArgument in commandArguments)
                {
                    arguments.Add(commandArgument);
                }
            }
            return(arguments.ToArray());
        }
Exemplo n.º 9
0
        internal static string[] ToArgumentString(DeviceSelector deviceSelector, Network network, IEnumerable <HwiOption> options, HwiCommands?command, string[] commandArguments)
        {
            List <string> arguments = new List <string>();

            options ??= Enumerable.Empty <HwiOption>();
            var fullOptions = new List <HwiOption>(options);

            if (network.NetworkType != NetworkType.Mainnet)
            {
                fullOptions.Insert(0, HwiOption.TestNet);
            }

            foreach (var option in fullOptions)
            {
                arguments.Add($"--{option.Type.ToString().ToLowerInvariant()}");
                if (!string.IsNullOrEmpty(option.Arguments))
                {
                    arguments.Add(option.Arguments);
                }
            }

            deviceSelector?.AddArgs(arguments);
            if (command != null)
            {
                arguments.Add(command.ToString().ToLowerInvariant());
            }

            if (commandArguments != null)
            {
                foreach (var commandArgument in commandArguments)
                {
                    arguments.Add(commandArgument);
                }
            }
            return(arguments.ToArray());
        }
Exemplo n.º 10
0
        public async Task <IActionResult> VaultBridgeConnection(string cryptoCode = null,
                                                                [ModelBinder(typeof(WalletIdModelBinder))]
                                                                WalletId walletId = null)
        {
            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                return(NotFound());
            }
            cryptoCode = cryptoCode ?? walletId.CryptoCode;
            using (var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10)))
            {
                var cancellationToken = cts.Token;
                var network           = Networks.GetNetwork <BTCPayNetwork>(cryptoCode);
                if (network == null)
                {
                    return(NotFound());
                }
                var websocket = await HttpContext.WebSockets.AcceptWebSocketAsync();

                var hwi = new Hwi.HwiClient(network.NBitcoinNetwork)
                {
                    Transport = new HwiWebSocketTransport(websocket)
                };
                Hwi.HwiDeviceClient device      = null;
                HwiEnumerateEntry   deviceEntry = null;
                HDFingerprint?      fingerprint = null;
                string password        = null;
                bool   pinProvided     = false;
                var    websocketHelper = new WebSocketHelper(websocket);

                async Task <bool> RequireDeviceUnlocking()
                {
                    if (deviceEntry == null)
                    {
                        await websocketHelper.Send("{ \"error\": \"need-device\"}", cancellationToken);

                        return(true);
                    }
                    if (deviceEntry.Code is HwiErrorCode.DeviceNotInitialized)
                    {
                        await websocketHelper.Send("{ \"error\": \"need-initialized\"}", cancellationToken);

                        return(true);
                    }
                    if ((deviceEntry.Code is HwiErrorCode.DeviceNotReady || deviceEntry.NeedsPinSent is true) &&
                        !pinProvided)
                    {
                        if (!IsTrezorT(deviceEntry))
                        {
                            await websocketHelper.Send("{ \"error\": \"need-pin\"}", cancellationToken);

                            return(true);
                        }
                        else
                        {
                            try
                            {
                                // On trezor T this will prompt the password! (https://github.com/bitcoin-core/HWI/issues/283)
                                await device.GetXPubAsync(new KeyPath("44'"), cancellationToken);
                            }
                            catch (HwiException ex) when(ex.ErrorCode == HwiErrorCode.DeviceAlreadyUnlocked)
                            {
                                pinProvided = true;
                            }
                            await websocketHelper.Send("{ \"error\": \"need-passphrase-on-device\"}", cancellationToken);

                            return(true);
                        }
                    }
                    if ((deviceEntry.Code is HwiErrorCode.DeviceNotReady || deviceEntry.NeedsPassphraseSent is true) && password == null)
                    {
                        if (IsTrezorT(deviceEntry))
                        {
                            await websocketHelper.Send("{ \"error\": \"need-passphrase-on-device\"}", cancellationToken);
                        }
                        else
                        {
                            await websocketHelper.Send("{ \"error\": \"need-passphrase\"}", cancellationToken);
                        }
                        return(true);
                    }
                    return(false);
                }

                JObject o = null;
                try
                {
                    while (true)
                    {
                        var command = await websocketHelper.NextMessageAsync(cancellationToken);

                        switch (command)
                        {
                        case "set-passphrase":
                            device.Password = await websocketHelper.NextMessageAsync(cancellationToken);

                            password = device.Password;
                            break;

                        case "ask-sign":
                            if (await RequireDeviceUnlocking())
                            {
                                continue;
                            }
                            if (walletId == null)
                            {
                                await websocketHelper.Send("{ \"error\": \"invalid-walletId\"}", cancellationToken);

                                continue;
                            }
                            if (fingerprint is null)
                            {
                                fingerprint = (await device.GetXPubAsync(new KeyPath("44'"), cancellationToken)).ExtPubKey.ParentFingerprint;
                            }
                            await websocketHelper.Send("{ \"info\": \"ready\"}", cancellationToken);

                            o = JObject.Parse(await websocketHelper.NextMessageAsync(cancellationToken));
                            var authorization = await _authorizationService.AuthorizeAsync(User, Policies.CanModifyStoreSettings.Key);

                            if (!authorization.Succeeded)
                            {
                                await websocketHelper.Send("{ \"error\": \"not-authorized\"}", cancellationToken);

                                continue;
                            }
                            var psbt = PSBT.Parse(o["psbt"].Value <string>(), network.NBitcoinNetwork);
                            var derivationSettings = GetDerivationSchemeSettings(walletId);
                            derivationSettings.RebaseKeyPaths(psbt);
                            var signing = derivationSettings.GetSigningAccountKeySettings();
                            if (signing.GetRootedKeyPath()?.MasterFingerprint != fingerprint)
                            {
                                await websocketHelper.Send("{ \"error\": \"wrong-wallet\"}", cancellationToken);

                                continue;
                            }
                            var signableInputs = psbt.Inputs
                                                 .SelectMany(i => i.HDKeyPaths)
                                                 .Where(i => i.Value.MasterFingerprint == fingerprint)
                                                 .ToArray();
                            if (signableInputs.Length > 0)
                            {
                                var actualPubKey = (await device.GetXPubAsync(signableInputs[0].Value.KeyPath)).GetPublicKey();
                                if (actualPubKey != signableInputs[0].Key)
                                {
                                    await websocketHelper.Send("{ \"error\": \"wrong-keypath\"}", cancellationToken);

                                    continue;
                                }
                            }
                            try
                            {
                                psbt = await device.SignPSBTAsync(psbt, cancellationToken);
                            }
                            catch (Hwi.HwiException)
                            {
                                await websocketHelper.Send("{ \"error\": \"user-reject\"}", cancellationToken);

                                continue;
                            }
                            o = new JObject();
                            o.Add("psbt", psbt.ToBase64());
                            await websocketHelper.Send(o.ToString(), cancellationToken);

                            break;

                        case "ask-pin":
                            if (device == null)
                            {
                                await websocketHelper.Send("{ \"error\": \"need-device\"}", cancellationToken);

                                continue;
                            }
                            try
                            {
                                await device.PromptPinAsync(cancellationToken);
                            }
                            catch (HwiException ex) when(ex.ErrorCode == HwiErrorCode.DeviceAlreadyUnlocked)
                            {
                                pinProvided = true;
                                await websocketHelper.Send("{ \"error\": \"device-already-unlocked\"}", cancellationToken);

                                continue;
                            }
                            await websocketHelper.Send("{ \"info\": \"prompted, please input the pin\"}", cancellationToken);

                            var pin = int.Parse(await websocketHelper.NextMessageAsync(cancellationToken), CultureInfo.InvariantCulture);
                            if (await device.SendPinAsync(pin, cancellationToken))
                            {
                                pinProvided = true;
                                await websocketHelper.Send("{ \"info\": \"the pin is correct\"}", cancellationToken);
                            }
                            else
                            {
                                await websocketHelper.Send("{ \"error\": \"incorrect-pin\"}", cancellationToken);

                                continue;
                            }
                            break;

                        case "ask-xpub":
                            if (await RequireDeviceUnlocking())
                            {
                                continue;
                            }
                            await websocketHelper.Send("{ \"info\": \"ok\"}", cancellationToken);

                            var     askedXpub     = JObject.Parse(await websocketHelper.NextMessageAsync(cancellationToken));
                            var     addressType   = askedXpub["addressType"].Value <string>();
                            var     accountNumber = askedXpub["accountNumber"].Value <int>();
                            JObject result        = new JObject();
                            var     factory       = network.NBXplorerNetwork.DerivationStrategyFactory;
                            if (fingerprint is null)
                            {
                                fingerprint = (await device.GetXPubAsync(new KeyPath("44'"), cancellationToken)).ExtPubKey.ParentFingerprint;
                            }
                            result["fingerprint"] = fingerprint.Value.ToString();

                            DerivationStrategyBase strategy = null;
                            KeyPath          keyPath        = null;
                            BitcoinExtPubKey xpub           = null;

                            if (!network.NBitcoinNetwork.Consensus.SupportSegwit && addressType != "legacy")
                            {
                                await websocketHelper.Send("{ \"error\": \"segwit-notsupported\"}", cancellationToken);

                                continue;
                            }

                            if (addressType == "segwit")
                            {
                                keyPath = new KeyPath("84'").Derive(network.CoinType).Derive(accountNumber, true);
                                xpub    = await device.GetXPubAsync(keyPath);

                                strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
                                {
                                    ScriptPubKeyType = ScriptPubKeyType.Segwit
                                });
                            }
                            else if (addressType == "segwitWrapped")
                            {
                                keyPath = new KeyPath("49'").Derive(network.CoinType).Derive(accountNumber, true);
                                xpub    = await device.GetXPubAsync(keyPath);

                                strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
                                {
                                    ScriptPubKeyType = ScriptPubKeyType.SegwitP2SH
                                });
                            }
                            else if (addressType == "legacy")
                            {
                                keyPath = new KeyPath("44'").Derive(network.CoinType).Derive(accountNumber, true);
                                xpub    = await device.GetXPubAsync(keyPath);

                                strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
                                {
                                    ScriptPubKeyType = ScriptPubKeyType.Legacy
                                });
                            }
                            else
                            {
                                await websocketHelper.Send("{ \"error\": \"invalid-addresstype\"}", cancellationToken);

                                continue;
                            }
                            result.Add(new JProperty("strategy", strategy.ToString()));
                            result.Add(new JProperty("accountKey", xpub.ToString()));
                            result.Add(new JProperty("keyPath", keyPath.ToString()));
                            await websocketHelper.Send(result.ToString(), cancellationToken);

                            break;

                        case "refresh-device":
                        case "ask-device":
                            DeviceSelector deviceSelector = (command == "refresh-device" && deviceEntry != null ? deviceEntry.DeviceSelector : null);
                            password    = null;
                            pinProvided = false;
                            deviceEntry = null;
                            device      = null;
                            var entries = (await hwi.EnumerateEntriesAsync(cancellationToken)).ToList();
                            deviceEntry = entries.Where(h => deviceSelector == null || SameSelector(deviceSelector, h.DeviceSelector)).FirstOrDefault();
                            if (deviceEntry == null)
                            {
                                await websocketHelper.Send("{ \"error\": \"no-device\"}", cancellationToken);

                                continue;
                            }
                            device      = new HwiDeviceClient(hwi, deviceEntry.DeviceSelector, deviceEntry.Model, deviceEntry.Fingerprint);
                            fingerprint = device.Fingerprint;
                            JObject json = new JObject();
                            json.Add("model", device.Model.ToString());
                            json.Add("fingerprint", device.Fingerprint?.ToString());
                            await websocketHelper.Send(json.ToString(), cancellationToken);

                            break;
                        }
                    }
                }
                catch (FormatException ex)
                {
                    JObject obj = new JObject();
                    obj.Add("error", "invalid-network");
                    obj.Add("details", ex.ToString());
                    try
                    {
                        await websocketHelper.Send(obj.ToString(), cancellationToken);
                    }
                    catch { }
                }
                catch (Exception ex)
                {
                    JObject obj = new JObject();
                    obj.Add("error", "unknown-error");
                    obj.Add("message", ex.Message);
                    obj.Add("details", ex.ToString());
                    try
                    {
                        await websocketHelper.Send(obj.ToString(), cancellationToken);
                    }
                    catch { }
                }
                finally
                {
                    await websocketHelper.DisposeAsync(cancellationToken);
                }
            }
            return(new EmptyResult());
        }
        /// <summary>
        /// Erzeugt ein neues Auswahlfenster.
        /// </summary>
        /// <param name="parameters">Die aktuelle Wahl der Parameter.</param>
        public AdditionalFilterSelector(List <ProfileParameter> parameters)
        {
            // Load designer stuff
            InitializeComponent();

            // Load the supression mode
            switch (GetSuppression(null, parameters))
            {
            case SuppressionMode.Complete: ckReset.Checked = true; ckResetTune.Checked = false; break;

            case SuppressionMode.Startup: ckReset.Checked = true; break;

            default: ckResetTune.Enabled = false; break;
            }

            // Load flag
            bool disableOnChange;

            if (bool.TryParse(parameters.GetParameter(CancelEncryptionOnChangedStream), out disableOnChange))
            {
                ckDisableOnChange.Checked = disableOnChange;
            }
            else
            {
                ckDisableOnChange.Checked = false;
            }

            // Load delay
            int delay;

            if (int.TryParse(parameters.GetParameter(DelayOnChangedStream), out delay))
            {
                udChangeDelay.Value = Math.Max(Math.Min(delay, udChangeDelay.Maximum), udChangeDelay.Minimum);
            }
            else
            {
                udChangeDelay.Value = udChangeDelay.Minimum;
            }

            // Load
            foreach (var information in DeviceAndFilterInformations.Cache.AllFilters)
            {
                selFilter.Items.Add(new DeviceSelector(information));
            }

            // Check for done
            selFilter.Enabled = (selFilter.Items.Count > 0);
            if (!selFilter.Enabled)
            {
                return;
            }

            // Forget about sorting
            selFilter.Sorted = false;

            // Add a null option
            selFilter.Items.Insert(0, Properties.Resources.Select_NoDevice);

            // Pre select
            selFilter.SelectedIndex = 0;

            // Load name
            var displayName = parameters.GetParameter(FilterName);

            if (string.IsNullOrEmpty(displayName))
            {
                return;
            }

            // Load flag
            bool flag;

            if (bool.TryParse(parameters.GetParameter(IgnoreMoniker), out flag))
            {
                ckDisplayOnly.Checked = flag;
            }

            // Load moniker
            var moniker = flag ? null : parameters.GetParameter(FilterMoniker);

            // Try to re-select
            DeviceSelector.Select(selFilter, displayName, moniker);
        }
Exemplo n.º 12
0
 public TimecodeDecoderDataStore(DeviceSelector audioDeviceSelector)
 {
     this.deviceSelector = audioDeviceSelector;
 }