rpcauth.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2015-2021 The Limenka 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 argparse import ArgumentParser
7 from getpass import getpass
8 from secrets import token_hex, token_urlsafe
9 import hmac
10 import json
11
12 def generate_salt(size):
13 """Create size byte hex salt"""
14 return token_hex(size)
15
16 def generate_password():
17 """Create 32 byte b64 password"""
18 return token_urlsafe(32)
19
20 def password_to_hmac(salt, password):
21 m = hmac.new(salt.encode('utf-8'), password.encode('utf-8'), 'SHA256')
22 return m.hexdigest()
23
24 def main():
25 parser = ArgumentParser(description='Create login credentials for a JSON-RPC user')
26 parser.add_argument('username', help='the username for authentication')
27 parser.add_argument('password', help='leave empty to generate a random password or specify "-" to prompt for password', nargs='?')
28 parser.add_argument("-j", "--json", help="output to json instead of plain-text", action='store_true')
29 parser.add_argument('--output', dest='output', help='file to store credentials, to be used with -rpcauthfile')
30 args = parser.parse_args()
31
32 if not args.password:
33 args.password = generate_password()
34 elif args.password == '-':
35 args.password = getpass()
36
37 # Create 16 byte hex salt
38 salt = generate_salt(16)
39 password_hmac = password_to_hmac(salt, args.password)
40 rpcauth = f'{args.username}:{salt}${password_hmac}'
41
42 if args.output:
43 file = open(args.output, "a", encoding="utf8")
44 file.write(rpcauth + "\n")
45
46 if args.json:
47 odict={'username':args.username, 'password':args.password}
48 if not args.output:
49 odict['rpcauth'] = rpcauth
50 print(json.dumps(odict))
51 else:
52 if not args.output:
53 print('String to be appended to limenka.conf:')
54 print(f'rpcauth={rpcauth}')
55 print(f'Your password:\n{args.password}')
56
57 if __name__ == '__main__':
58 main()
59