review suggestions and updates [skip ci]

This commit is contained in:
Matthew Fosse 2024-04-17 08:45:18 -07:00
parent 5aa384c06a
commit 65ecb7cd60
4 changed files with 101 additions and 23 deletions

View file

@ -1236,7 +1236,6 @@ abstract class ElectrumWalletBase
: null;
final HD = index == null ? hd : hd.derive(index);
final priv = ECPrivate.fromHex(HD.privKey!);
print(priv.getPublic().toHex());
String messagePrefix = '\x18Bitcoin Signed Message:\n';
return priv.signMessage(utf8.encode(message), messagePrefix: messagePrefix);
}
@ -1251,7 +1250,7 @@ abstract class ElectrumWalletBase
if (sigDecodedBytes.length != 64 && sigDecodedBytes.length != 65) {
throw ArgumentException(
"bitcoin signature must be 64 bytes without recover-id or 65 bytes with recover-id");
"litecoin signature must be 64 bytes without recover-id or 65 bytes with recover-id");
}
String messagePrefix = '\x18Bitcoin Signed Message:\n';

View file

@ -1,4 +1,13 @@
import 'dart:convert';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/crypto/crypto/cdsa/curve/curves.dart';
import 'package:blockchain_utils/crypto/crypto/cdsa/ecdsa/signature.dart';
import 'package:blockchain_utils/crypto/quick_crypto.dart';
import 'package:blockchain_utils/exception/exception.dart';
import 'package:blockchain_utils/hex/hex.dart';
import 'package:blockchain_utils/numbers/bigint_utils.dart';
import 'package:blockchain_utils/signer/bitcoin_signer.dart';
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_core/crypto_currency.dart';
@ -118,4 +127,69 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return 0;
}
@override
Future<String> signMessage(String message, {String? address = null}) async {
final index = address != null
? walletAddresses.allAddresses.firstWhere((element) => element.address == address).index
: null;
final HD = index == null ? hd : hd.derive(index);
final priv = ECPrivate.fromHex(HD.privKey!);
String messagePrefix = '\x19Litecoin Signed Message:\n';
return priv.signMessage(utf8.encode(message), messagePrefix: messagePrefix);
}
@override
Future<bool> verifyMessage(String message, String signature, {String? address = null}) async {
if (address == null) {
return false;
}
final sigDecodedBytes = hex.decode(signature);
if (sigDecodedBytes.length != 64 && sigDecodedBytes.length != 65) {
throw ArgumentException(
"litecoin signature must be 64 bytes without recover-id or 65 bytes with recover-id");
}
String messagePrefix = '\x19Litecoin Signed Message:\n';
final messageHash = QuickCrypto.sha256Hash(
BitcoinSignerUtils.magicMessage(utf8.encode(message), messagePrefix));
List<int> correctSignature =
sigDecodedBytes.length == 65 ? sigDecodedBytes.sublist(1) : List.from(sigDecodedBytes);
List<int> rBytes = correctSignature.sublist(0, 32);
List<int> sBytes = correctSignature.sublist(32);
final sig = ECDSASignature(BigintUtils.fromBytes(rBytes), BigintUtils.fromBytes(sBytes));
List<int> possibleRecoverIds = [0, 1, 2, 3];
if (sigDecodedBytes.length == 65) {
possibleRecoverIds = [sigDecodedBytes[0]];
}
final baseAddress = addressTypeFromStr(address, network);
for (int recoveryId in possibleRecoverIds) {
final pubKey = sig.recoverPublicKey(messageHash, Curves.generatorSecp256k1, recoveryId);
final recoveredPub = ECPublic.fromBytes(pubKey!.toBytes());
String? recoveredAddress;
if (baseAddress is P2pkAddress) {
recoveredAddress = recoveredPub.toP2pkAddress().toAddress(network);
} else if (baseAddress is P2pkhAddress) {
recoveredAddress = recoveredPub.toP2pkhAddress().toAddress(network);
} else if (baseAddress is P2wshAddress) {
recoveredAddress = recoveredPub.toP2wshAddress().toAddress(network);
} else if (baseAddress is P2wpkhAddress) {
recoveredAddress = recoveredPub.toP2wpkhAddress().toAddress(network);
}
if (recoveredAddress == address) {
return true;
}
}
return false;
}
}

View file

@ -15,6 +15,30 @@ import 'package:cw_core/wallet_info.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:blockchain_utils/numbers/bigint_utils.dart';
import 'package:blockchain_utils/signer/bitcoin_signer.dart';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/crypto/crypto/cdsa/curve/curves.dart';
import 'package:blockchain_utils/crypto/crypto/cdsa/ecdsa/signature.dart';
import 'package:blockchain_utils/crypto/quick_crypto.dart';
import 'package:blockchain_utils/exception/exception.dart';
import 'package:blockchain_utils/hex/hex.dart';
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:cw_bitcoin/litecoin_network.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'bitcoin_cash_base.dart';
@ -165,25 +189,4 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
return 0;
}
@override
Future<String> signMessage(String message, {String? address = null}) async {
final index = address != null
? walletAddresses.allAddresses
.firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address))
.index
: null;
final HD = index == null ? hd : hd.derive(index);
return base64Encode(HD.signMessage(message));
}
@override
Future<bool> verifyMessage(String message, String signature, {String? address = null}) async {
final index = address != null
? walletAddresses.allAddresses
.firstWhere((element) => element.address == AddressUtils.toLegacyAddress(address))
.index
: null;
final HD = index == null ? hd : hd.derive(index);
return HD.verify(message: message, signature: base64Decode(signature));
}
}

View file

@ -22,6 +22,8 @@ abstract class SignViewModelBase with Store {
bool get signIncludesAddress => [
WalletType.monero,
WalletType.bitcoin,
WalletType.bitcoinCash,
WalletType.litecoin,
WalletType.haven,
].contains(wallet.type);