Browse Source

Incorporate pubkey in signature, check based on address

Include the public key in the signature string, to allow verification
based on address.
miguelfreitas
Pieter Wuille 13 years ago
parent
commit
b53d6284eb
  1. 80
      src/bitcoinrpc.cpp

80
src/bitcoinrpc.cpp

@ -526,6 +526,8 @@ Value sendtoaddress(const Array& params, bool fHelp)
return wtx.GetHash().GetHex(); return wtx.GetHash().GetHex();
} }
static const string strMessageMagic = "Bitcoin Signed Message:\n";
Value signmessage(const Array& params, bool fHelp) Value signmessage(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() != 2) if (fHelp || params.size() != 2)
@ -533,61 +535,71 @@ Value signmessage(const Array& params, bool fHelp)
"signmessage <bitcoinaddress> <message>\n" "signmessage <bitcoinaddress> <message>\n"
"Sign a message with the private key of an address"); "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 strAddress = params[0].get_str();
string strMessage = params[1].get_str(); string strMessage = params[1].get_str();
strMessage.insert(0, "Padding text - ");
uint160 hash160; CBitcoinAddress addr(strAddress);
if(!AddressToHash160(strAddress, hash160)) if (!addr.IsValid())
throw JSONRPCError(-3, "Invalid address"); throw JSONRPCError(-3, "Invalid address");
vector<unsigned char>& vchPubKey = mapPubKeys[hash160];
CKey key; CKey key;
if(!key.SetPubKey(vchPubKey)) if (!pwalletMain->GetKey(addr, key))
throw JSONRPCError(-3, "Public key not found"); throw JSONRPCError(-4, "Private key not available");
strMessage.insert(0, HexStr(vchPubKey.begin(), vchPubKey.end()).c_str());
CDataStream ss(SER_GETHASH);
ss << strMessageMagic;
ss << strMessage;
vector<unsigned char> vchMsg(strMessage.begin(), strMessage.end());
vector<unsigned char> vchSig; vector<unsigned char> vchSig;
if (!CKey::Sign(mapKeys[vchPubKey], Hash(vchMsg.begin(), vchMsg.end()), vchSig)) if (!key.Sign(Hash(ss.begin(), ss.end()), vchSig))
throw JSONRPCError(-3, "Sign failed"); throw JSONRPCError(-5, "Sign failed");
Object obj; CDataStream sres(SER_NETWORK);
obj.push_back(Pair("address", strAddress)); sres << key.GetPubKey(); // public key
obj.push_back(Pair("pubkey", HexStr(vchPubKey.begin(), vchPubKey.end()).c_str())); sres << vchSig; // signature;
obj.push_back(Pair("sign", HexStr(vchSig.begin(), vchSig.end()).c_str()));
return obj; return HexStr(sres.begin(), sres.end());
} }
Value verifymessage(const Array& params, bool fHelp) Value verifymessage(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() != 3) if (fHelp || params.size() != 3)
throw runtime_error( throw runtime_error(
"verifymessage <pubkey> <sign> <message>\n" "verifymessage <bitcoinaddress> <signature> <message>\n"
"Verify a signed message with the public key"); "Verify a signed message");
string strPubKey = params[0].get_str(); string strAddress = params[0].get_str();
string strSign = params[1].get_str(); string strSign = params[1].get_str();
string strMessage = params[2].get_str(); string strMessage = params[2].get_str();
strMessage.insert(0, "Padding text - ");
strMessage.insert(0, strPubKey.c_str());
vector<unsigned char> vchPubKey = ParseHex(strPubKey); CBitcoinAddress addr(strAddress);
vector<unsigned char> vchSig = ParseHex(strSign); if (!addr.IsValid())
vector<unsigned char> vchMsg(strMessage.begin(), strMessage.end()); throw JSONRPCError(-3, "Invalid address");
CKey key; vector<unsigned char> vchResult = ParseHex(strSign);
if(!key.SetPubKey(vchPubKey)) CDataStream sres(vchResult);
throw JSONRPCError(-3, "Invalid pubkey");
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) std::vector<unsigned char> vchPubKey;
throw JSONRPCError(-3, "Verify failed"); sres >> vchPubKey;
std::vector<unsigned char> vchSig;
sres >> vchSig;
Object obj; CKey key;
obj.push_back(Pair("address", PubKeyToAddress(vchPubKey))); if (!key.SetPubKey(vchPubKey))
obj.push_back(Pair("pubkey", strPubKey.c_str())); throw JSONRPCError(-5, "Invalid public key in signature");
return obj;
if (key.GetAddress() == addr)
{
CDataStream ss(SER_GETHASH);
ss << strMessageMagic;
ss << strMessage;
return key.Verify(Hash(ss.begin(), ss.end()), vchSig);
}
else
return false;
} }

Loading…
Cancel
Save