aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rwxr-xr-xshare/rpcauth/rpcauth.py46
-rw-r--r--src/Makefile.test.include2
-rwxr-xr-xtest/util/rpcauth-test.py49
4 files changed, 81 insertions, 19 deletions
diff --git a/Makefile.am b/Makefile.am
index f554501b2e..8a8debb079 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -269,7 +269,8 @@ EXTRA_DIST += \
test/util/data/txcreatescript4.json \
test/util/data/txcreatesignv1.hex \
test/util/data/txcreatesignv1.json \
- test/util/data/txcreatesignv2.hex
+ test/util/data/txcreatesignv2.hex \
+ test/util/rpcauth-test.py
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
diff --git a/share/rpcauth/rpcauth.py b/share/rpcauth/rpcauth.py
index f9b9787514..da84deb5e2 100755
--- a/share/rpcauth/rpcauth.py
+++ b/share/rpcauth/rpcauth.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2017 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
+# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import sys
@@ -9,26 +9,36 @@ from random import SystemRandom
import base64
import hmac
-if len(sys.argv) < 2:
- sys.stderr.write('Please include username as an argument.\n')
- sys.exit(0)
+def generate_salt():
+ # This uses os.urandom() underneath
+ cryptogen = SystemRandom()
-username = sys.argv[1]
+ # Create 16 byte hex salt
+ salt_sequence = [cryptogen.randrange(256) for _ in range(16)]
+ return ''.join([format(r, 'x') for r in salt_sequence])
-#This uses os.urandom() underneath
-cryptogen = SystemRandom()
+def generate_password(salt):
+ """Create 32 byte b64 password"""
+ password = base64.urlsafe_b64encode(os.urandom(32)).decode('utf-8')
-#Create 16 byte hex salt
-salt_sequence = [cryptogen.randrange(256) for i in range(16)]
-hexseq = list(map(hex, salt_sequence))
-salt = "".join([x[2:] for x in hexseq])
+ m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), 'SHA256')
+ password_hmac = m.hexdigest()
-#Create 32 byte b64 password
-password = base64.urlsafe_b64encode(os.urandom(32)).decode("utf-8")
+ return password, password_hmac
-m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), "SHA256")
-result = m.hexdigest()
+def main():
+ if len(sys.argv) < 2:
+ sys.stderr.write('Please include username as an argument.\n')
+ sys.exit(0)
-print("String to be appended to bitcoin.conf:")
-print("rpcauth="+username+":"+salt+"$"+result)
-print("Your password:\n"+password)
+ username = sys.argv[1]
+
+ salt = generate_salt()
+ password, password_hmac = generate_password(salt)
+
+ print('String to be appended to bitcoin.conf:')
+ print('rpcauth={0}:{1}${2}'.format(username, salt, password_hmac))
+ print('Your password:\n{0}'.format(password))
+
+if __name__ == '__main__':
+ main()
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index c4f18bb371..f7eb712089 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -156,6 +156,8 @@ bitcoin_test_clean : FORCE
check-local: $(BITCOIN_TESTS:.cpp=.cpp.test)
@echo "Running test/util/bitcoin-util-test.py..."
$(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py
+ @echo "Running test/util/rpcauth-test.py..."
+ $(PYTHON) $(top_builddir)/test/util/rpcauth-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
diff --git a/test/util/rpcauth-test.py b/test/util/rpcauth-test.py
new file mode 100755
index 0000000000..dfbb5ea3a7
--- /dev/null
+++ b/test/util/rpcauth-test.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test share/rpcauth/rpcauth.py
+"""
+import base64
+import configparser
+import hmac
+import importlib
+import os
+import sys
+import unittest
+
+class TestRPCAuth(unittest.TestCase):
+ def setUp(self):
+ config = configparser.ConfigParser()
+ config_path = os.path.abspath(
+ os.path.join(os.sep, os.path.abspath(os.path.dirname(__file__)),
+ "../config.ini"))
+ with open(config_path) as config_file:
+ config.read_file(config_file)
+ sys.path.insert(0, os.path.dirname(config['environment']['RPCAUTH']))
+ self.rpcauth = importlib.import_module('rpcauth')
+
+ def test_generate_salt(self):
+ self.assertLessEqual(len(self.rpcauth.generate_salt()), 32)
+ self.assertGreaterEqual(len(self.rpcauth.generate_salt()), 16)
+
+ def test_generate_password(self):
+ salt = self.rpcauth.generate_salt()
+ password, password_hmac = self.rpcauth.generate_password(salt)
+
+ expected_password = base64.urlsafe_b64encode(
+ base64.urlsafe_b64decode(password)).decode('utf-8')
+ self.assertEqual(expected_password, password)
+
+ def test_check_password_hmac(self):
+ salt = self.rpcauth.generate_salt()
+ password, password_hmac = self.rpcauth.generate_password(salt)
+
+ m = hmac.new(bytearray(salt, 'utf-8'),
+ bytearray(password, 'utf-8'), 'SHA256')
+ expected_password_hmac = m.hexdigest()
+
+ self.assertEqual(expected_password_hmac, password_hmac)
+
+if __name__ == '__main__':
+ unittest.main()