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. 86
      src/bitcoinrpc.cpp

86
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 - ");
CBitcoinAddress addr(strAddress);
uint160 hash160; if (!addr.IsValid())
if(!AddressToHash160(strAddress, hash160))
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");
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; CKey key;
if(!key.SetPubKey(vchPubKey)) if (!key.SetPubKey(vchPubKey))
throw JSONRPCError(-3, "Invalid pubkey"); throw JSONRPCError(-5, "Invalid public key in signature");
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) if (key.GetAddress() == addr)
throw JSONRPCError(-3, "Verify failed"); {
CDataStream ss(SER_GETHASH);
Object obj; ss << strMessageMagic;
obj.push_back(Pair("address", PubKeyToAddress(vchPubKey))); ss << strMessage;
obj.push_back(Pair("pubkey", strPubKey.c_str())); return key.Verify(Hash(ss.begin(), ss.end()), vchSig);
return obj; }
else
return false;
} }

Loading…
Cancel
Save