Skip to content

Commit 106d929

Browse files
committed
Merge #13056: [tests] Make rpcauth.py testable and add unit tests
6674a75 [tests] Make rpcauth.py testable and add unit tests (Qasim Javed) Pull request description: refs #12995 Tree-SHA512: 609a85a75dafe46723f050db1e96098f6859519afd5e1b141a332f34ab715144d32fdd8f10d245d6dc0765e77f82158fe7b8aa2e4317f0e893de491d2e0acf1f
2 parents e074097 + 6674a75 commit 106d929

File tree

4 files changed

+81
-19
lines changed

4 files changed

+81
-19
lines changed

Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ EXTRA_DIST += \
269269
test/util/data/txcreatescript4.json \
270270
test/util/data/txcreatesignv1.hex \
271271
test/util/data/txcreatesignv1.json \
272-
test/util/data/txcreatesignv2.hex
272+
test/util/data/txcreatesignv2.hex \
273+
test/util/rpcauth-test.py
273274

274275
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
275276

share/rpcauth/rpcauth.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22
# Copyright (c) 2015-2017 The Bitcoin Core developers
3-
# Distributed under the MIT software license, see the accompanying
3+
# Distributed under the MIT software license, see the accompanying
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

66
import sys
@@ -9,26 +9,36 @@
99
import base64
1010
import hmac
1111

12-
if len(sys.argv) < 2:
13-
sys.stderr.write('Please include username as an argument.\n')
14-
sys.exit(0)
12+
def generate_salt():
13+
# This uses os.urandom() underneath
14+
cryptogen = SystemRandom()
1515

16-
username = sys.argv[1]
16+
# Create 16 byte hex salt
17+
salt_sequence = [cryptogen.randrange(256) for _ in range(16)]
18+
return ''.join([format(r, 'x') for r in salt_sequence])
1719

18-
#This uses os.urandom() underneath
19-
cryptogen = SystemRandom()
20+
def generate_password(salt):
21+
"""Create 32 byte b64 password"""
22+
password = base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8')
2023

21-
#Create 16 byte hex salt
22-
salt_sequence = [cryptogen.randrange(256) for i in range(16)]
23-
hexseq = list(map(hex, salt_sequence))
24-
salt = "".join([x[2:] for x in hexseq])
24+
m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), 'SHA256')
25+
password_hmac = m.hexdigest()
2526

26-
#Create 32 byte b64 password
27-
password = base64.urlsafe_b64encode(os.urandom(32)).decode("utf-8")
27+
return password, password_hmac
2828

29-
m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), "SHA256")
30-
result = m.hexdigest()
29+
def main():
30+
if len(sys.argv) < 2:
31+
sys.stderr.write('Please include username as an argument.\n')
32+
sys.exit(0)
3133

32-
print("String to be appended to bitcoin.conf:")
33-
print("rpcauth="+username+":"+salt+"$"+result)
34-
print("Your password:\n"+password)
34+
username = sys.argv[1]
35+
36+
salt = generate_salt()
37+
password, password_hmac = generate_password(salt)
38+
39+
print('String to be appended to bitcoin.conf:')
40+
print('rpcauth={0}:{1}${2}'.format(username, salt, password_hmac))
41+
print('Your password:\n{0}'.format(password))
42+
43+
if __name__ == '__main__':
44+
main()

src/Makefile.test.include

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ bitcoin_test_clean : FORCE
156156
check-local: $(BITCOIN_TESTS:.cpp=.cpp.test)
157157
@echo "Running test/util/bitcoin-util-test.py..."
158158
$(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py
159+
@echo "Running test/util/rpcauth-test.py..."
160+
$(PYTHON) $(top_builddir)/test/util/rpcauth-test.py
159161
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
160162
if EMBEDDED_UNIVALUE
161163
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check

test/util/rpcauth-test.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2015-2018 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+
"""Test share/rpcauth/rpcauth.py
6+
"""
7+
import base64
8+
import configparser
9+
import hmac
10+
import importlib
11+
import os
12+
import sys
13+
import unittest
14+
15+
class TestRPCAuth(unittest.TestCase):
16+
def setUp(self):
17+
config = configparser.ConfigParser()
18+
config_path = os.path.abspath(
19+
os.path.join(os.sep, os.path.abspath(os.path.dirname(__file__)),
20+
"../config.ini"))
21+
with open(config_path) as config_file:
22+
config.read_file(config_file)
23+
sys.path.insert(0, os.path.dirname(config['environment']['RPCAUTH']))
24+
self.rpcauth = importlib.import_module('rpcauth')
25+
26+
def test_generate_salt(self):
27+
self.assertLessEqual(len(self.rpcauth.generate_salt()), 32)
28+
self.assertGreaterEqual(len(self.rpcauth.generate_salt()), 16)
29+
30+
def test_generate_password(self):
31+
salt = self.rpcauth.generate_salt()
32+
password, password_hmac = self.rpcauth.generate_password(salt)
33+
34+
expected_password = base64.urlsafe_b64encode(
35+
base64.urlsafe_b64decode(password)).decode('utf-8')
36+
self.assertEqual(expected_password, password)
37+
38+
def test_check_password_hmac(self):
39+
salt = self.rpcauth.generate_salt()
40+
password, password_hmac = self.rpcauth.generate_password(salt)
41+
42+
m = hmac.new(bytearray(salt, 'utf-8'),
43+
bytearray(password, 'utf-8'), 'SHA256')
44+
expected_password_hmac = m.hexdigest()
45+
46+
self.assertEqual(expected_password_hmac, password_hmac)
47+
48+
if __name__ == '__main__':
49+
unittest.main()

0 commit comments

Comments
 (0)