Skip to content

Commit 0630353

Browse files
committed
Merge #7953: Create signmessagewithprivkey rpc
7db0ecb Test for signing messages (Andrew Chow) f90efbf Create signmessagewithprivkey rpc (Andrew)
2 parents e8d9175 + 7db0ecb commit 0630353

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

qa/pull-tester/rpc-tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
'abandonconflict.py',
124124
'p2p-versionbits-warning.py',
125125
'importprunedfunds.py',
126+
'signmessages.py'
126127
]
127128
if ENABLE_ZMQ:
128129
testScripts.append('zmq_test.py')

qa/rpc-tests/signmessages.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python2
2+
# Copyright (c) 2016 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
from test_framework.test_framework import BitcoinTestFramework
7+
from test_framework.util import *
8+
9+
10+
class SignMessagesTest(BitcoinTestFramework):
11+
"""Tests RPC commands for signing and verifying messages."""
12+
13+
def setup_chain(self):
14+
print('Initializing test directory ' + self.options.tmpdir)
15+
initialize_chain_clean(self.options.tmpdir, 1)
16+
17+
def setup_network(self, split=False):
18+
self.nodes = start_nodes(1, self.options.tmpdir)
19+
self.is_network_split = False
20+
21+
def run_test(self):
22+
message = 'This is just a test message'
23+
24+
# Test the signing with a privkey
25+
privKey = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N'
26+
address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB'
27+
signature = self.nodes[0].signmessagewithprivkey(privKey, message)
28+
29+
# Verify the message
30+
assert(self.nodes[0].verifymessage(address, signature, message))
31+
32+
# Test the signing with an address with wallet
33+
address = self.nodes[0].getnewaddress()
34+
signature = self.nodes[0].signmessage(address, message)
35+
36+
# Verify the message
37+
assert(self.nodes[0].verifymessage(address, signature, message))
38+
39+
if __name__ == '__main__':
40+
SignMessagesTest().main()

src/rpc/misc.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,48 @@ UniValue verifymessage(const UniValue& params, bool fHelp)
366366
return (pubkey.GetID() == keyID);
367367
}
368368

369+
UniValue signmessagewithprivkey(const UniValue& params, bool fHelp)
370+
{
371+
if (fHelp || params.size() != 2)
372+
throw runtime_error(
373+
"signmessagewithprivkey \"privkey\" \"message\"\n"
374+
"\nSign a message with the private key of an address\n"
375+
"\nArguments:\n"
376+
"1. \"privkey\" (string, required) The private key to sign the message with.\n"
377+
"2. \"message\" (string, required) The message to create a signature of.\n"
378+
"\nResult:\n"
379+
"\"signature\" (string) The signature of the message encoded in base 64\n"
380+
"\nExamples:\n"
381+
"\nCreate the signature\n"
382+
+ HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
383+
"\nVerify the signature\n"
384+
+ HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
385+
"\nAs json rpc\n"
386+
+ HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
387+
);
388+
389+
string strPrivkey = params[0].get_str();
390+
string strMessage = params[1].get_str();
391+
392+
CBitcoinSecret vchSecret;
393+
bool fGood = vchSecret.SetString(strPrivkey);
394+
if (!fGood)
395+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
396+
CKey key = vchSecret.GetKey();
397+
if (!key.IsValid())
398+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
399+
400+
CHashWriter ss(SER_GETHASH, 0);
401+
ss << strMessageMagic;
402+
ss << strMessage;
403+
404+
vector<unsigned char> vchSig;
405+
if (!key.SignCompact(ss.GetHash(), vchSig))
406+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
407+
408+
return EncodeBase64(&vchSig[0], vchSig.size());
409+
}
410+
369411
UniValue setmocktime(const UniValue& params, bool fHelp)
370412
{
371413
if (fHelp || params.size() != 1)
@@ -404,6 +446,7 @@ static const CRPCCommand commands[] =
404446
{ "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
405447
{ "util", "createmultisig", &createmultisig, true },
406448
{ "util", "verifymessage", &verifymessage, true },
449+
{ "util", "signmessagewithprivkey", &signmessagewithprivkey, true },
407450

408451
/* Not shown in help */
409452
{ "hidden", "setmocktime", &setmocktime, true },

0 commit comments

Comments
 (0)