aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2011-09-19 20:03:03 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2011-09-27 19:48:22 +0200
commitb53d6284eb5b2833ed1bde46dbce5b5a4284804a (patch)
treecc58ca90b4601e7f29615d92dddf430e8dd712d9
parentcc2567e32fb62df84f40d3f28f2ee48ab1009775 (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.cpp86
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;
}