diff options
Diffstat (limited to 'cffi_random.py')
-rw-r--r-- | cffi_random.py | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/cffi_random.py b/cffi_random.py new file mode 100644 index 0000000..5f62e43 --- /dev/null +++ b/cffi_random.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 + +import sys +from typing import Optional + +from cffi import FFI + +class RandError(RuntimeError): + pass + +ffi = FFI() +ffi.cdef(''' + void RAND_seed(const void *buf, int num); + + void RAND_add(const void *buf, int num, double entropy); + + int RAND_status(void); + + int RAND_event(unsigned int iMsg, void* wParam, void* lParam); + void RAND_screen(void); + + int RAND_bytes(unsigned char *buf, int num); + + int RAND_pseudo_bytes(unsigned char *buf, int num); + + const char *ERR_reason_error_string(unsigned long); + + unsigned long ERR_get_error(void); +''') + +lib = ffi.dlopen('crypto') + +def rand_add(buf: bytes, num: int, entropy: float) -> None: + assert isinstance(entropy, float) + lib.RAND_add(buf, num, entropy) + +def rand_seed(buf: bytes, num: int) -> None: + lib.RAND_seed(buf, num) + +def rand_status() -> int: + return lib.RAND_status() + +def rand_event(iMsg: int, wParam: int, lParam: int) -> Optional[int]: + if sys.platform == 'win32': + return lib.RAND_event(iMsg, wParam, lParam) + else: + return None + +def rand_screen() -> None: + if sys.platform == 'win32': + lib.RAND_screen() + +def rand_bytes(n: int = 8) -> bytes: + buf = ffi.new('unsigned char buf[{:d}]'.format(n)) + ret = lib.RAND_bytes(buf, n) + if ret == 1: + return bytes(buf) + elif ret == 0: + RandError("Not enough randomness.") + elif ret == -1: + RandError("Not supported by the current RAND method.") + else: + err_msg = lib.ERR_reason_error_string(lib.ERR_get_error()) + if err_msg is not None: + RandError(err_msg) + else: + RandError("Unknown error in function RAND_bytes") + +def rand_pseudo_bytes(n: int) -> bytes: + blob = ffi.new('unsigned char buf[{:d}]'.format(n)) + ret = lib.RAND_pseudo_bytes(blob, n) + + if ret == -1: + RandError("Not supported by the current RAND method.") + elif ret in [0, 1]: + return (blob, ret) + else: + RandError("Unknown error in RAND_pseudo_bytes") + + +if __name__=='__main__': + print(rand_bytes()) |