From b53d6284eb5b2833ed1bde46dbce5b5a4284804a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 19 Sep 2011 20:03:03 +0200 Subject: [PATCH] Incorporate pubkey in signature, check based on address Include the public key in the signature string, to allow verification based on address. --- src/bitcoinrpc.cpp | 86 ++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 1b2a5b5f..3638adac 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -526,6 +526,8 @@ Value sendtoaddress(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } +static const string strMessageMagic = "Bitcoin Signed Message:\n"; + Value signmessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) @@ -533,61 +535,71 @@ Value signmessage(const Array& params, bool fHelp) "signmessage \n" "Sign a message with the private key of an address"); + if (pwalletMain->IsLocked()) + throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first."); + string strAddress = params[0].get_str(); string strMessage = params[1].get_str(); - strMessage.insert(0, "Padding text - "); - - uint160 hash160; - if(!AddressToHash160(strAddress, hash160)) + + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) throw JSONRPCError(-3, "Invalid address"); - - vector& vchPubKey = mapPubKeys[hash160]; + CKey key; - if(!key.SetPubKey(vchPubKey)) - throw JSONRPCError(-3, "Public key not found"); - strMessage.insert(0, HexStr(vchPubKey.begin(), vchPubKey.end()).c_str()); + if (!pwalletMain->GetKey(addr, key)) + throw JSONRPCError(-4, "Private key not available"); + + CDataStream ss(SER_GETHASH); + ss << strMessageMagic; + ss << strMessage; - vector vchMsg(strMessage.begin(), strMessage.end()); vector vchSig; - if (!CKey::Sign(mapKeys[vchPubKey], Hash(vchMsg.begin(), vchMsg.end()), vchSig)) - throw JSONRPCError(-3, "Sign failed"); + if (!key.Sign(Hash(ss.begin(), ss.end()), vchSig)) + throw JSONRPCError(-5, "Sign failed"); - Object obj; - obj.push_back(Pair("address", strAddress)); - obj.push_back(Pair("pubkey", HexStr(vchPubKey.begin(), vchPubKey.end()).c_str())); - obj.push_back(Pair("sign", HexStr(vchSig.begin(), vchSig.end()).c_str())); + CDataStream sres(SER_NETWORK); + sres << key.GetPubKey(); // public key + sres << vchSig; // signature; - return obj; + return HexStr(sres.begin(), sres.end()); } Value verifymessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 3) throw runtime_error( - "verifymessage \n" - "Verify a signed message with the public key"); + "verifymessage \n" + "Verify a signed message"); - string strPubKey = params[0].get_str(); - string strSign = params[1].get_str(); - string strMessage = params[2].get_str(); - strMessage.insert(0, "Padding text - "); - strMessage.insert(0, strPubKey.c_str()); + string strAddress = params[0].get_str(); + string strSign = params[1].get_str(); + string strMessage = params[2].get_str(); - vector vchPubKey = ParseHex(strPubKey); - vector vchSig = ParseHex(strSign); - vector vchMsg(strMessage.begin(), strMessage.end()); + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) + throw JSONRPCError(-3, "Invalid address"); + + vector vchResult = ParseHex(strSign); + CDataStream sres(vchResult); + + std::vector vchPubKey; + sres >> vchPubKey; + std::vector vchSig; + sres >> vchSig; CKey key; - if(!key.SetPubKey(vchPubKey)) - throw JSONRPCError(-3, "Invalid pubkey"); - - if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) - throw JSONRPCError(-3, "Verify failed"); - - Object obj; - obj.push_back(Pair("address", PubKeyToAddress(vchPubKey))); - obj.push_back(Pair("pubkey", strPubKey.c_str())); - return obj; + if (!key.SetPubKey(vchPubKey)) + throw JSONRPCError(-5, "Invalid public key in signature"); + + if (key.GetAddress() == addr) + { + CDataStream ss(SER_GETHASH); + ss << strMessageMagic; + ss << strMessage; + return key.Verify(Hash(ss.begin(), ss.end()), vchSig); + } + else + return false; }