Files
luci/libs/rpcd-mod-rad3-enc/files/rad3-enc
Daniel F. Dickinson 7e25a5c32a rpcd-mod-rad3-enc: add radicale3 password hasher
There are a number of changes to radicale, passlib and bcrypt,
which means a new rpcd function is needed.

Signed-off-by: Daniel F. Dickinson <dfdpublic@wildtechgarden.ca>
2026-01-15 18:20:51 +01:00

72 lines
2.2 KiB
Python
Executable File

#!/usr/bin/python3
# cspell:words encpass enctype hpasswd jsonin passlib plainpass radicale
import sys
import json
from passlib.hash import apr_md5_crypt, sha256_crypt, sha512_crypt # pyright: ignore[reportMissingModuleSource]
from radicale import utils # pyright: ignore[reportMissingImports]
def main():
if len(sys.argv) < 2:
return -1
if sys.argv[1] == 'list':
print('{ "encrypt": { "type": "str", "plainpass": "str" } }\n')
return 0
if sys.argv[1] == 'call':
if len(sys.argv) < 3:
return -1
if sys.argv[2] != 'encrypt':
return -1
encpass = ""
error = ""
try:
jsonin = json.loads(sys.stdin.readline())
enctype = jsonin['type'].strip()
plainpass = jsonin['plainpass']
if enctype == 'plain':
encpass = plainpass
elif enctype == 'md5':
encpass = apr_md5_crypt.hash(plainpass).strip()
elif enctype == 'sha256':
encpass = sha256_crypt.using(rounds=5000).hash(plainpass).strip()
elif enctype == 'sha512':
encpass = sha512_crypt.using(rounds=5000).hash(plainpass).strip()
elif enctype == 'bcrypt':
try:
from passlib.hash import bcrypt # pyright: ignore[reportMissingModuleSource]
except ImportError as e:
raise RuntimeError("hpasswd encryption method 'bcrypt' requires the bcrypt module, which is missing") from e
else:
encpass = bcrypt.hash(plainpass).strip()
elif enctype == 'argon2':
try:
import argon2 # pyright: ignore[reportMissingImports]
except ImportError as e:
raise RuntimeError("hpasswd encryption method 'argon2' requires the argon2 module, which is missing") from e
else:
encpass = argon2.using(type="ID").hash(plainpass).strip()
except Exception as e:
encpass = ""
error = str(e)
if ((encpass == "") and (error == "")):
error = "unable to encrypt password"
if error:
print(json.dumps({ "encrypted_password": encpass, "error": error}))
else:
print(json.dumps({ "encrypted_password": encpass}))
return 0
main()