|
| 1 | +// This file is dual licensed under the terms of the Apache License, Version |
| 2 | +// 2.0, and the BSD License. See the LICENSE file in the root of this repository |
| 3 | +// for complete details. |
| 4 | + |
| 5 | +use crate::backend::hashes; |
| 6 | +use crate::buf::CffiBuf; |
| 7 | +use crate::error::CryptographyResult; |
| 8 | + |
| 9 | +#[pyo3::prelude::pyfunction] |
| 10 | +fn derive_pbkdf2_hmac<'p>( |
| 11 | + py: pyo3::Python<'p>, |
| 12 | + key_material: CffiBuf<'_>, |
| 13 | + algorithm: &pyo3::PyAny, |
| 14 | + salt: &[u8], |
| 15 | + iterations: usize, |
| 16 | + length: usize, |
| 17 | +) -> CryptographyResult<&'p pyo3::types::PyBytes> { |
| 18 | + let md = hashes::message_digest_from_algorithm(py, algorithm)?; |
| 19 | + |
| 20 | + Ok(pyo3::types::PyBytes::new_with(py, length, |b| { |
| 21 | + openssl::pkcs5::pbkdf2_hmac(key_material.as_bytes(), salt, iterations, md, b).unwrap(); |
| 22 | + Ok(()) |
| 23 | + })?) |
| 24 | +} |
| 25 | + |
| 26 | +#[cfg(not(CRYPTOGRAPHY_IS_LIBRESSL))] |
| 27 | +#[pyo3::prelude::pyfunction] |
| 28 | +#[allow(clippy::too_many_arguments)] |
| 29 | +fn derive_scrypt<'p>( |
| 30 | + py: pyo3::Python<'p>, |
| 31 | + key_material: CffiBuf<'_>, |
| 32 | + salt: &[u8], |
| 33 | + n: u64, |
| 34 | + r: u64, |
| 35 | + p: u64, |
| 36 | + max_mem: u64, |
| 37 | + length: usize, |
| 38 | +) -> CryptographyResult<&'p pyo3::types::PyBytes> { |
| 39 | + Ok(pyo3::types::PyBytes::new_with(py, length, |b| { |
| 40 | + openssl::pkcs5::scrypt(key_material.as_bytes(), salt, n, r, p, max_mem, b).map_err(|_| { |
| 41 | + // memory required formula explained here: |
| 42 | + // https://blog.filippo.io/the-scrypt-parameters/ |
| 43 | + let min_memory = 128 * n * r / (1024 * 1024); |
| 44 | + pyo3::exceptions::PyMemoryError::new_err(format!( |
| 45 | + "Not enough memory to derive key. These parameters require {}MB of memory.", |
| 46 | + min_memory |
| 47 | + )) |
| 48 | + }) |
| 49 | + })?) |
| 50 | +} |
| 51 | + |
| 52 | +pub(crate) fn create_module(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { |
| 53 | + let m = pyo3::prelude::PyModule::new(py, "kdf")?; |
| 54 | + |
| 55 | + m.add_wrapped(pyo3::wrap_pyfunction!(derive_pbkdf2_hmac))?; |
| 56 | + #[cfg(not(CRYPTOGRAPHY_IS_LIBRESSL))] |
| 57 | + m.add_wrapped(pyo3::wrap_pyfunction!(derive_scrypt))?; |
| 58 | + |
| 59 | + Ok(m) |
| 60 | +} |
0 commit comments