diff --git a/README.md b/README.md index 96d0b34..5dacb21 100644 --- a/README.md +++ b/README.md @@ -4,73 +4,62 @@ [![PyPI](https://github.com/radumarias/zeroize-python/actions/workflows/PyPI.yml/badge.svg)](https://github.com/radumarias/zeroize-python/actions/workflows/PyPI.yml) [![tests](https://github.com/radumarias/zeroize-python/actions/workflows/tests.yml/badge.svg)](https://github.com/radumarias/zeroize-python/actions/workflows/tests.yml) -Securely clear secrets from memory. Built on stable Rust primitives which guarantee memory is zeroed using an operation will not be 'optimized away' by the compiler. +Clear secrets from memory. Built on stable Rust primitives which guarantee memory is zeroed using an operation will not be 'optimized away' by the compiler. Uses a portable pure Rust implementation that works everywhere. It uses [zeroize](https://crates.io/crates/zeroize) crate under the hood. -It can work with `bytearray` and numpy array. +It can work with `bytearray` and `numpy array`. > ⚠️ **Warning** -> **Currently it doens't work in the case of [Copy-on-write fork](https://en.wikipedia.org/wiki/Copy-on-write) -> Also it doesn't work if memory is moved or moved to swap file. You can use `crypes` with `libc.mlockall` to lock the memory from being swapped, see example below.*** +> **Currently it doens't work in the case of [Copy-on-write fork](https://en.wikipedia.org/wiki/Copy-on-write), you can follow this [issue](https://github.com/radumarias/zeroize-python/issues/1) +> Also by itself it doesn't work if memory is moved or moved to swap file. You can use `crypes` with `libc.mlockall()` to lock the memory, see example below.*** # Example ```python import zeroize import numpy as np +import ctypes + + +# Lock memory using ctypes +def lock_memory(): + libc = ctypes.CDLL("libc.so.6") + # Lock all current and future pages from being swapped out + libc.mlockall(ctypes.c_int(0x02 | 0x04)) # MCL_CURRENT | MCL_FUTURE + + +def unlock_memory(): + libc = ctypes.CDLL("libc.so.6") + # Unlock all locked pages + libc.munlockall() + +print("locking memory") +lock_memory() + +print("allocate memory") # regular array -arr = bytearray(b'1234567890') +arr = bytearray(b"1234567890") # numpy array arr_np = np.array([0] * 10, dtype=np.uint8) arr_np[:] = arr -assert arr_np.tobytes() == b'1234567890' +assert arr_np.tobytes() == b"1234567890" print("zeroize'ing...: ") zeroize.zeroize1(arr) zeroize.zeroize_np(arr_np) -print("checking if is zeroized...") -assert arr == bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +print("checking if is zeroized") +assert arr == bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") assert all(arr_np == 0) -print("all good, bye!") -``` +print("unlocking memory") +unlock_memory() -# Use `crypes` with `libc.mlockall()` to lock the memory from being swapped - -```python -import ctypes - -MCL_CURRENT = 1 -MCL_FUTURE = 2 - -libc = ctypes.CDLL('libc.so.6', use_errno=True) - -def mlockall(flags=MCL_CURRENT|MCL_FUTURE): - result = libc.mlockall(flags) - if result != 0: - raise Exception("cannot lock memmory, errno=%s" % ctypes.get_errno()) - -def munlockall(): - result = libc.munlockall() - if result != 0: - raise Exception("cannot lock memmory, errno=%s" % ctypes.get_errno()) - - -if __name__ == '__main__': - mlockall() - print("memmory locked") - - # allocate your data here - # ... - # zeroize it - - munlockall() - print("memmory unlocked") +print("all good, bye!") ``` # Building from source