|
|
@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|