diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2011-09-19 20:03:03 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2011-09-27 19:48:22 +0200 |
commit | b53d6284eb5b2833ed1bde46dbce5b5a4284804a (patch) | |
tree | cc58ca90b4601e7f29615d92dddf430e8dd712d9 | |
parent | cc2567e32fb62df84f40d3f28f2ee48ab1009775 (diff) |
Incorporate pubkey in signature, check based on address
Include the public key in the signature string, to allow verification
based on address.
-rw-r--r-- | src/bitcoinrpc.cpp | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 1b2a5b5f7e..3638adac38 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 <bitcoinaddress> <message>\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<unsigned char>& 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<unsigned char> vchMsg(strMessage.begin(), strMessage.end()); vector<unsigned char> 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 <pubkey> <sign> <message>\n" - "Verify a signed message with the public key"); + "verifymessage <bitcoinaddress> <signature> <message>\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<unsigned char> vchPubKey = ParseHex(strPubKey); - vector<unsigned char> vchSig = ParseHex(strSign); - vector<unsigned char> vchMsg(strMessage.begin(), strMessage.end()); + CBitcoinAddress addr(strAddress); + if (!addr.IsValid()) + throw JSONRPCError(-3, "Invalid address"); + + vector<unsigned char> vchResult = ParseHex(strSign); + CDataStream sres(vchResult); + + std::vector<unsigned char> vchPubKey; + sres >> vchPubKey; + std::vector<unsigned char> 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; } |