Allow user to input a passphrase for Trezor v1 (Fix #5794) (#5980)

This commit is contained in:
Nicolas Dorier
2024-05-15 09:18:20 +09:00
committed by GitHub
parent 69e0ae76c7
commit 7793c5e5df
4 changed files with 42 additions and 25 deletions

View File

@@ -60,7 +60,11 @@ namespace BTCPayServer.Controllers
HDFingerprint? fingerprint = null;
string password = null;
var websocketHelper = new WebSocketHelper(websocket);
async Task FetchFingerprint()
{
fingerprint = (await device.GetXPubAsync(new KeyPath("44'"), cancellationToken)).ExtPubKey.ParentFingerprint;
device = new HwiDeviceClient(hwi, DeviceSelectors.FromFingerprint(fingerprint.Value), deviceEntry.Model, fingerprint) { Password = password };
}
async Task<bool> RequireDeviceUnlocking()
{
if (deviceEntry == null)
@@ -91,6 +95,13 @@ namespace BTCPayServer.Controllers
return true;
}
}
if (IsTrezorOne(deviceEntry) && password is null)
{
fingerprint = null; // There will be a new fingerprint
device = new HwiDeviceClient(hwi, DeviceSelectors.FromDeviceType("trezor", deviceEntry.Path), deviceEntry.Model, null);
await websocketHelper.Send("{ \"error\": \"need-passphrase\"}", cancellationToken);
return true;
}
return false;
}
@@ -118,7 +129,7 @@ namespace BTCPayServer.Controllers
}
if (fingerprint is null)
{
fingerprint = (await device.GetXPubAsync(new KeyPath("44'"), cancellationToken)).ExtPubKey.ParentFingerprint;
await FetchFingerprint();
}
await websocketHelper.Send("{ \"info\": \"ready\"}", cancellationToken);
o = JObject.Parse(await websocketHelper.NextMessageAsync(cancellationToken));
@@ -211,14 +222,26 @@ namespace BTCPayServer.Controllers
var factory = network.NBXplorerNetwork.DerivationStrategyFactory;
if (fingerprint is null)
{
fingerprint = (await device.GetXPubAsync(new KeyPath("44'"), cancellationToken)).ExtPubKey.ParentFingerprint;
await FetchFingerprint();
}
result["fingerprint"] = fingerprint.Value.ToString();
DerivationStrategyBase strategy = null;
KeyPath keyPath = null;
BitcoinExtPubKey xpub = null;
KeyPath keyPath = (addressType switch
{
"taproot" => new KeyPath("86'"),
"segwit" => new KeyPath("84'"),
"segwitWrapped" => new KeyPath("49'"),
"legacy" => new KeyPath("44'"),
_ => null
})?.Derive(network.CoinType).Derive(accountNumber, true);
if (keyPath is null)
{
await websocketHelper.Send("{ \"error\": \"invalid-addresstype\"}", cancellationToken);
continue;
}
BitcoinExtPubKey xpub = await device.GetXPubAsync(keyPath);
if (!network.NBitcoinNetwork.Consensus.SupportSegwit && addressType != "legacy")
{
await websocketHelper.Send("{ \"error\": \"segwit-notsupported\"}", cancellationToken);
@@ -232,8 +255,6 @@ namespace BTCPayServer.Controllers
}
if (addressType == "taproot")
{
keyPath = new KeyPath("86'").Derive(network.CoinType).Derive(accountNumber, true);
xpub = await device.GetXPubAsync(keyPath);
strategy = factory.CreateDirectDerivationStrategy(xpub, new DerivationStrategyOptions()
{
ScriptPubKeyType = ScriptPubKeyType.TaprootBIP86
@@ -241,8 +262,6 @@ namespace BTCPayServer.Controllers
}
else 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
@@ -250,8 +269,6 @@ namespace BTCPayServer.Controllers
}
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
@@ -259,18 +276,12 @@ namespace BTCPayServer.Controllers
}
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()));
@@ -315,7 +326,6 @@ askdevice:
fingerprint = device.Fingerprint;
JObject json = new JObject();
json.Add("model", model);
json.Add("fingerprint", device.Fingerprint?.ToString());
await websocketHelper.Send(json.ToString(), cancellationToken);
break;
}
@@ -386,6 +396,10 @@ askdevice:
{
return deviceEntry.Model.Contains("Trezor_T", StringComparison.OrdinalIgnoreCase);
}
private static bool IsTrezorOne(HwiEnumerateEntry deviceEntry)
{
return deviceEntry.Model.Contains("trezor_1", StringComparison.OrdinalIgnoreCase);
}
public StoreData CurrentStore
{