mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Fix _hashlib
This commit is contained in:
1 parent
1f290dccfe
commit
12db02eaf0
11 files changed
+362
-67
No files matched your search
Generated
+2
@@ -3226,6 +3226,7 @@ dependencies = [
|
||||
"foreign-types-shared",
|
||||
"gethostname",
|
||||
"hex",
|
||||
"hmac",
|
||||
"indexmap",
|
||||
"itertools 0.14.0",
|
||||
"libc",
|
||||
@@ -3250,6 +3251,7 @@ dependencies = [
|
||||
"page_size",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"pbkdf2",
|
||||
"pem-rfc7468 1.0.0",
|
||||
"phf 0.13.1",
|
||||
"pkcs8",
|
||||
|
||||
@@ -3717,7 +3717,7 @@ impl Compiler {
|
||||
// Compile kwdefaults and build dict
|
||||
for (arg, default) in &kw_with_defaults {
|
||||
self.emit_load_const(ConstantData::Str {
|
||||
value: arg.name.as_str().into(),
|
||||
value: self.mangle(arg.name.as_str()).into_owned().into(),
|
||||
});
|
||||
self.compile_expression(default)?;
|
||||
}
|
||||
@@ -6983,7 +6983,7 @@ impl Compiler {
|
||||
let default_kw_count = kw_with_defaults.len();
|
||||
for (arg, default) in &kw_with_defaults {
|
||||
self.emit_load_const(ConstantData::Str {
|
||||
value: arg.name.as_str().into(),
|
||||
value: self.mangle(arg.name.as_str()).into_owned().into(),
|
||||
});
|
||||
self.compile_expression(default)?;
|
||||
}
|
||||
|
||||
@@ -61,12 +61,14 @@ rand_core = { workspace = true }
|
||||
mt19937 = "3.1"
|
||||
|
||||
# Crypto:
|
||||
digest = "0.10.3"
|
||||
digest = "0.10.7"
|
||||
md-5 = "0.10.1"
|
||||
sha-1 = "0.10.0"
|
||||
sha2 = "0.10.2"
|
||||
sha3 = "0.10.1"
|
||||
blake2 = "0.10.4"
|
||||
hmac = "0.12"
|
||||
pbkdf2 = { version = "0.12", features = ["hmac"] }
|
||||
|
||||
## unicode stuff
|
||||
unicode_names2 = { workspace = true }
|
||||
|
||||
@@ -9,11 +9,11 @@ mod _blake2 {
|
||||
|
||||
#[pyfunction]
|
||||
fn blake2b(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_blake2b(args).into_pyobject(vm))
|
||||
Ok(local_blake2b(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn blake2s(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_blake2s(args).into_pyobject(vm))
|
||||
Ok(local_blake2s(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
+340
-49
@@ -1,4 +1,7 @@
|
||||
// spell-checker:ignore usedforsecurity HASHXOF
|
||||
// spell-checker:ignore usedforsecurity HASHXOF hashopenssl dklen
|
||||
// NOTE: Function names like `openssl_md5` match CPython's `_hashopenssl.c` interface
|
||||
// for compatibility, but the implementation uses pure Rust crates (md5, sha2, etc.),
|
||||
// not OpenSSL.
|
||||
|
||||
pub(crate) use _hashlib::module_def;
|
||||
|
||||
@@ -7,7 +10,9 @@ pub mod _hashlib {
|
||||
use crate::common::lock::PyRwLock;
|
||||
use crate::vm::{
|
||||
Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
|
||||
builtins::{PyBytes, PyStrRef, PyTypeRef, PyValueError},
|
||||
builtins::{
|
||||
PyBaseExceptionRef, PyBytes, PyFrozenSet, PyStr, PyStrRef, PyTypeRef, PyValueError,
|
||||
},
|
||||
class::StaticType,
|
||||
convert::ToPyObject,
|
||||
function::{ArgBytesLike, ArgStrOrBytesLike, FuncArgs, OptionalArg},
|
||||
@@ -17,17 +22,59 @@ pub mod _hashlib {
|
||||
use digest::{DynDigest, core_api::BlockSizeUser};
|
||||
use digest::{ExtendableOutput, Update};
|
||||
use dyn_clone::{DynClone, clone_trait_object};
|
||||
use hmac::Mac;
|
||||
use md5::Md5;
|
||||
use sha1::Sha1;
|
||||
use sha2::{Sha224, Sha256, Sha384, Sha512};
|
||||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
|
||||
|
||||
const HASH_ALGORITHMS: &[&str] = &[
|
||||
"md5",
|
||||
"sha1",
|
||||
"sha224",
|
||||
"sha256",
|
||||
"sha384",
|
||||
"sha512",
|
||||
"sha3_224",
|
||||
"sha3_256",
|
||||
"sha3_384",
|
||||
"sha3_512",
|
||||
"shake_128",
|
||||
"shake_256",
|
||||
"blake2b",
|
||||
"blake2s",
|
||||
];
|
||||
|
||||
#[pyattr]
|
||||
const _GIL_MINSIZE: usize = 2048;
|
||||
|
||||
#[pyattr]
|
||||
#[pyexception(name = "UnsupportedDigestmodError", base = PyValueError, impl)]
|
||||
#[derive(Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct UnsupportedDigestmodError(PyValueError);
|
||||
|
||||
#[pyattr]
|
||||
fn openssl_md_meth_names(vm: &VirtualMachine) -> PyObjectRef {
|
||||
PyFrozenSet::from_iter(
|
||||
vm,
|
||||
HASH_ALGORITHMS.iter().map(|n| vm.ctx.new_str(*n).into()),
|
||||
)
|
||||
.expect("failed to create openssl_md_meth_names frozenset")
|
||||
.into_ref(&vm.ctx)
|
||||
.into()
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
fn _constructors(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let dict = vm.ctx.new_dict();
|
||||
for name in HASH_ALGORITHMS {
|
||||
let s = vm.ctx.new_str(*name);
|
||||
dict.set_item(&*s, s.clone().into(), vm).unwrap();
|
||||
}
|
||||
dict.into()
|
||||
}
|
||||
|
||||
#[derive(FromArgs, Debug)]
|
||||
#[allow(unused)]
|
||||
struct NewHashArgs {
|
||||
@@ -37,15 +84,19 @@ pub mod _hashlib {
|
||||
data: OptionalArg<ArgBytesLike>,
|
||||
#[pyarg(named, default = true)]
|
||||
usedforsecurity: bool,
|
||||
#[pyarg(named, optional)]
|
||||
string: OptionalArg<ArgBytesLike>,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[allow(unused)]
|
||||
pub struct BlakeHashArgs {
|
||||
#[pyarg(positional, optional)]
|
||||
#[pyarg(any, optional)]
|
||||
pub data: OptionalArg<ArgBytesLike>,
|
||||
#[pyarg(named, default = true)]
|
||||
usedforsecurity: bool,
|
||||
#[pyarg(named, optional)]
|
||||
pub string: OptionalArg<ArgBytesLike>,
|
||||
}
|
||||
|
||||
impl From<NewHashArgs> for BlakeHashArgs {
|
||||
@@ -53,6 +104,7 @@ pub mod _hashlib {
|
||||
Self {
|
||||
data: args.data,
|
||||
usedforsecurity: args.usedforsecurity,
|
||||
string: args.string,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,16 +113,19 @@ pub mod _hashlib {
|
||||
#[allow(unused)]
|
||||
pub struct HashArgs {
|
||||
#[pyarg(any, optional)]
|
||||
pub string: OptionalArg<ArgBytesLike>,
|
||||
pub data: OptionalArg<ArgBytesLike>,
|
||||
#[pyarg(named, default = true)]
|
||||
usedforsecurity: bool,
|
||||
#[pyarg(named, optional)]
|
||||
pub string: OptionalArg<ArgBytesLike>,
|
||||
}
|
||||
|
||||
impl From<NewHashArgs> for HashArgs {
|
||||
fn from(args: NewHashArgs) -> Self {
|
||||
Self {
|
||||
string: args.data,
|
||||
data: args.data,
|
||||
usedforsecurity: args.usedforsecurity,
|
||||
string: args.string,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,6 +173,91 @@ pub mod _hashlib {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[allow(unused)]
|
||||
struct HmacDigestArgs {
|
||||
#[pyarg(positional)]
|
||||
key: ArgBytesLike,
|
||||
#[pyarg(positional)]
|
||||
msg: ArgBytesLike,
|
||||
#[pyarg(positional)]
|
||||
digest: PyObjectRef,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[allow(unused)]
|
||||
struct Pbkdf2HmacArgs {
|
||||
#[pyarg(any)]
|
||||
hash_name: PyStrRef,
|
||||
#[pyarg(any)]
|
||||
password: ArgBytesLike,
|
||||
#[pyarg(any)]
|
||||
salt: ArgBytesLike,
|
||||
#[pyarg(any)]
|
||||
iterations: i64,
|
||||
#[pyarg(any, optional)]
|
||||
dklen: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
fn resolve_data(
|
||||
data: OptionalArg<ArgBytesLike>,
|
||||
string: OptionalArg<ArgBytesLike>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<OptionalArg<ArgBytesLike>> {
|
||||
match (data.into_option(), string.into_option()) {
|
||||
(Some(d), None) => Ok(OptionalArg::Present(d)),
|
||||
(None, Some(s)) => Ok(OptionalArg::Present(s)),
|
||||
(None, None) => Ok(OptionalArg::Missing),
|
||||
(Some(_), Some(_)) => Err(vm.new_type_error(
|
||||
"'data' and 'string' are mutually exclusive \
|
||||
and support for 'string' keyword parameter \
|
||||
is slated for removal in a future version."
|
||||
.to_owned(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_digestmod(digestmod: &PyObjectRef, vm: &VirtualMachine) -> PyResult<String> {
|
||||
if let Some(name) = digestmod.downcast_ref::<PyStr>() {
|
||||
return Ok(name.as_str().to_lowercase());
|
||||
}
|
||||
if let Ok(name_obj) = digestmod.get_attr("__name__", vm)
|
||||
&& let Some(name) = name_obj.downcast_ref::<PyStr>()
|
||||
&& let Some(algo) = name.as_str().strip_prefix("openssl_")
|
||||
{
|
||||
return Ok(algo.to_owned());
|
||||
}
|
||||
Err(vm.new_exception_msg(
|
||||
UnsupportedDigestmodError::static_type().to_owned(),
|
||||
"unsupported digestmod".to_owned(),
|
||||
))
|
||||
}
|
||||
|
||||
fn hash_digest_size(name: &str) -> Option<usize> {
|
||||
match name {
|
||||
"md5" => Some(16),
|
||||
"sha1" => Some(20),
|
||||
"sha224" => Some(28),
|
||||
"sha256" => Some(32),
|
||||
"sha384" => Some(48),
|
||||
"sha512" => Some(64),
|
||||
"sha3_224" => Some(28),
|
||||
"sha3_256" => Some(32),
|
||||
"sha3_384" => Some(48),
|
||||
"sha3_512" => Some(64),
|
||||
"blake2b" => Some(64),
|
||||
"blake2s" => Some(32),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn unsupported_hash(name: &str, vm: &VirtualMachine) -> PyBaseExceptionRef {
|
||||
vm.new_exception_msg(
|
||||
UnsupportedDigestmodError::static_type().to_owned(),
|
||||
format!("unsupported hash type {name}"),
|
||||
)
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(module = "_hashlib", name = "HASH")]
|
||||
#[derive(PyPayload)]
|
||||
@@ -309,93 +449,163 @@ pub mod _hashlib {
|
||||
|
||||
#[pyfunction(name = "new")]
|
||||
fn hashlib_new(args: NewHashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
match args.name.as_str().to_lowercase().as_str() {
|
||||
"md5" => Ok(local_md5(args.into()).into_pyobject(vm)),
|
||||
"sha1" => Ok(local_sha1(args.into()).into_pyobject(vm)),
|
||||
"sha224" => Ok(local_sha224(args.into()).into_pyobject(vm)),
|
||||
"sha256" => Ok(local_sha256(args.into()).into_pyobject(vm)),
|
||||
"sha384" => Ok(local_sha384(args.into()).into_pyobject(vm)),
|
||||
"sha512" => Ok(local_sha512(args.into()).into_pyobject(vm)),
|
||||
"sha3_224" => Ok(local_sha3_224(args.into()).into_pyobject(vm)),
|
||||
"sha3_256" => Ok(local_sha3_256(args.into()).into_pyobject(vm)),
|
||||
"sha3_384" => Ok(local_sha3_384(args.into()).into_pyobject(vm)),
|
||||
"sha3_512" => Ok(local_sha3_512(args.into()).into_pyobject(vm)),
|
||||
"shake_128" => Ok(local_shake_128(args.into()).into_pyobject(vm)),
|
||||
"shake_256" => Ok(local_shake_256(args.into()).into_pyobject(vm)),
|
||||
"blake2b" => Ok(local_blake2b(args.into()).into_pyobject(vm)),
|
||||
"blake2s" => Ok(local_blake2s(args.into()).into_pyobject(vm)),
|
||||
"md5" => Ok(PyHasher::new("md5", HashWrapper::new::<Md5>(data)).into_pyobject(vm)),
|
||||
"sha1" => Ok(PyHasher::new("sha1", HashWrapper::new::<Sha1>(data)).into_pyobject(vm)),
|
||||
"sha224" => {
|
||||
Ok(PyHasher::new("sha224", HashWrapper::new::<Sha224>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha256" => {
|
||||
Ok(PyHasher::new("sha256", HashWrapper::new::<Sha256>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha384" => {
|
||||
Ok(PyHasher::new("sha384", HashWrapper::new::<Sha384>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha512" => {
|
||||
Ok(PyHasher::new("sha512", HashWrapper::new::<Sha512>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha3_224" => {
|
||||
Ok(PyHasher::new("sha3_224", HashWrapper::new::<Sha3_224>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha3_256" => {
|
||||
Ok(PyHasher::new("sha3_256", HashWrapper::new::<Sha3_256>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha3_384" => {
|
||||
Ok(PyHasher::new("sha3_384", HashWrapper::new::<Sha3_384>(data)).into_pyobject(vm))
|
||||
}
|
||||
"sha3_512" => {
|
||||
Ok(PyHasher::new("sha3_512", HashWrapper::new::<Sha3_512>(data)).into_pyobject(vm))
|
||||
}
|
||||
"shake_128" => Ok(
|
||||
PyHasherXof::new("shake_128", HashXofWrapper::new_shake_128(data))
|
||||
.into_pyobject(vm),
|
||||
),
|
||||
"shake_256" => Ok(
|
||||
PyHasherXof::new("shake_256", HashXofWrapper::new_shake_256(data))
|
||||
.into_pyobject(vm),
|
||||
),
|
||||
"blake2b" => Ok(
|
||||
PyHasher::new("blake2b", HashWrapper::new::<Blake2b512>(data)).into_pyobject(vm),
|
||||
),
|
||||
"blake2s" => Ok(
|
||||
PyHasher::new("blake2s", HashWrapper::new::<Blake2s256>(data)).into_pyobject(vm),
|
||||
),
|
||||
other => Err(vm.new_value_error(format!("Unknown hashing algorithm: {other}"))),
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_md5")]
|
||||
pub fn local_md5(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("md5", HashWrapper::new::<Md5>(args.string))
|
||||
pub fn local_md5(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new("md5", HashWrapper::new::<Md5>(data)))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha1")]
|
||||
pub fn local_sha1(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha1", HashWrapper::new::<Sha1>(args.string))
|
||||
pub fn local_sha1(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new("sha1", HashWrapper::new::<Sha1>(data)))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha224")]
|
||||
pub fn local_sha224(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha224", HashWrapper::new::<Sha224>(args.string))
|
||||
pub fn local_sha224(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new("sha224", HashWrapper::new::<Sha224>(data)))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha256")]
|
||||
pub fn local_sha256(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha256", HashWrapper::new::<Sha256>(args.string))
|
||||
pub fn local_sha256(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new("sha256", HashWrapper::new::<Sha256>(data)))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha384")]
|
||||
pub fn local_sha384(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha384", HashWrapper::new::<Sha384>(args.string))
|
||||
pub fn local_sha384(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new("sha384", HashWrapper::new::<Sha384>(data)))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha512")]
|
||||
pub fn local_sha512(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha512", HashWrapper::new::<Sha512>(args.string))
|
||||
pub fn local_sha512(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new("sha512", HashWrapper::new::<Sha512>(data)))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha3_224")]
|
||||
pub fn local_sha3_224(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_224", HashWrapper::new::<Sha3_224>(args.string))
|
||||
pub fn local_sha3_224(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new(
|
||||
"sha3_224",
|
||||
HashWrapper::new::<Sha3_224>(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha3_256")]
|
||||
pub fn local_sha3_256(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_256", HashWrapper::new::<Sha3_256>(args.string))
|
||||
pub fn local_sha3_256(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new(
|
||||
"sha3_256",
|
||||
HashWrapper::new::<Sha3_256>(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha3_384")]
|
||||
pub fn local_sha3_384(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_384", HashWrapper::new::<Sha3_384>(args.string))
|
||||
pub fn local_sha3_384(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new(
|
||||
"sha3_384",
|
||||
HashWrapper::new::<Sha3_384>(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_sha3_512")]
|
||||
pub fn local_sha3_512(args: HashArgs) -> PyHasher {
|
||||
PyHasher::new("sha3_512", HashWrapper::new::<Sha3_512>(args.string))
|
||||
pub fn local_sha3_512(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new(
|
||||
"sha3_512",
|
||||
HashWrapper::new::<Sha3_512>(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_shake_128")]
|
||||
pub fn local_shake_128(args: HashArgs) -> PyHasherXof {
|
||||
PyHasherXof::new("shake_128", HashXofWrapper::new_shake_128(args.string))
|
||||
pub fn local_shake_128(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasherXof> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasherXof::new(
|
||||
"shake_128",
|
||||
HashXofWrapper::new_shake_128(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_shake_256")]
|
||||
pub fn local_shake_256(args: HashArgs) -> PyHasherXof {
|
||||
PyHasherXof::new("shake_256", HashXofWrapper::new_shake_256(args.string))
|
||||
pub fn local_shake_256(args: HashArgs, vm: &VirtualMachine) -> PyResult<PyHasherXof> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasherXof::new(
|
||||
"shake_256",
|
||||
HashXofWrapper::new_shake_256(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_blake2b")]
|
||||
pub fn local_blake2b(args: BlakeHashArgs) -> PyHasher {
|
||||
PyHasher::new("blake2b", HashWrapper::new::<Blake2b512>(args.data))
|
||||
pub fn local_blake2b(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new(
|
||||
"blake2b",
|
||||
HashWrapper::new::<Blake2b512>(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction(name = "openssl_blake2s")]
|
||||
pub fn local_blake2s(args: BlakeHashArgs) -> PyHasher {
|
||||
PyHasher::new("blake2s", HashWrapper::new::<Blake2s256>(args.data))
|
||||
pub fn local_blake2s(args: BlakeHashArgs, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
let data = resolve_data(args.data, args.string, vm)?;
|
||||
Ok(PyHasher::new(
|
||||
"blake2s",
|
||||
HashWrapper::new::<Blake2s256>(data),
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_fips_mode() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
@@ -434,7 +644,6 @@ pub mod _hashlib {
|
||||
|
||||
#[pyfunction]
|
||||
fn hmac_new(args: NewHMACHashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
|
||||
// Raise UnsupportedDigestmodError so Python's hmac.py falls back to pure-Python implementation
|
||||
let _ = args;
|
||||
Err(vm.new_exception_msg(
|
||||
UnsupportedDigestmodError::static_type().to_owned(),
|
||||
@@ -442,12 +651,94 @@ pub mod _hashlib {
|
||||
))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn hmac_digest(args: HmacDigestArgs, vm: &VirtualMachine) -> PyResult<PyBytes> {
|
||||
let name = resolve_digestmod(&args.digest, vm)?;
|
||||
|
||||
let key_buf = args.key.borrow_buf();
|
||||
let msg_buf = args.msg.borrow_buf();
|
||||
|
||||
macro_rules! do_hmac {
|
||||
($hash_ty:ty) => {{
|
||||
let mut mac = <hmac::Hmac<$hash_ty> as Mac>::new_from_slice(&key_buf)
|
||||
.map_err(|_| vm.new_value_error("invalid key length".to_owned()))?;
|
||||
Mac::update(&mut mac, &msg_buf);
|
||||
Ok(mac.finalize().into_bytes().to_vec().into())
|
||||
}};
|
||||
}
|
||||
|
||||
match name.as_str() {
|
||||
"md5" => do_hmac!(Md5),
|
||||
"sha1" => do_hmac!(Sha1),
|
||||
"sha224" => do_hmac!(Sha224),
|
||||
"sha256" => do_hmac!(Sha256),
|
||||
"sha384" => do_hmac!(Sha384),
|
||||
"sha512" => do_hmac!(Sha512),
|
||||
"sha3_224" => do_hmac!(Sha3_224),
|
||||
"sha3_256" => do_hmac!(Sha3_256),
|
||||
"sha3_384" => do_hmac!(Sha3_384),
|
||||
"sha3_512" => do_hmac!(Sha3_512),
|
||||
_ => Err(unsupported_hash(&name, vm)),
|
||||
}
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn pbkdf2_hmac(args: Pbkdf2HmacArgs, vm: &VirtualMachine) -> PyResult<PyBytes> {
|
||||
let name = args.hash_name.as_str().to_lowercase();
|
||||
|
||||
if args.iterations < 1 {
|
||||
return Err(vm.new_value_error("iteration value must be greater than 0.".to_owned()));
|
||||
}
|
||||
let rounds = u32::try_from(args.iterations)
|
||||
.map_err(|_| vm.new_overflow_error("iteration value is too great.".to_owned()))?;
|
||||
|
||||
let dklen: usize = match args.dklen.into_option() {
|
||||
Some(obj) if vm.is_none(&obj) => {
|
||||
hash_digest_size(&name).ok_or_else(|| unsupported_hash(&name, vm))?
|
||||
}
|
||||
Some(obj) => {
|
||||
let len: i64 = obj.try_into_value(vm)?;
|
||||
if len < 1 {
|
||||
return Err(vm.new_value_error("key length must be greater than 0.".to_owned()));
|
||||
}
|
||||
usize::try_from(len).map_err(|_| {
|
||||
vm.new_overflow_error("key length is too great.".to_owned())
|
||||
})?
|
||||
}
|
||||
None => hash_digest_size(&name).ok_or_else(|| unsupported_hash(&name, vm))?,
|
||||
};
|
||||
|
||||
let password_buf = args.password.borrow_buf();
|
||||
let salt_buf = args.salt.borrow_buf();
|
||||
let mut dk = vec![0u8; dklen];
|
||||
|
||||
macro_rules! do_pbkdf2 {
|
||||
($hash_ty:ty) => {{
|
||||
pbkdf2::pbkdf2_hmac::<$hash_ty>(&password_buf, &salt_buf, rounds, &mut dk);
|
||||
Ok(dk.into())
|
||||
}};
|
||||
}
|
||||
|
||||
match name.as_str() {
|
||||
"md5" => do_pbkdf2!(Md5),
|
||||
"sha1" => do_pbkdf2!(Sha1),
|
||||
"sha224" => do_pbkdf2!(Sha224),
|
||||
"sha256" => do_pbkdf2!(Sha256),
|
||||
"sha384" => do_pbkdf2!(Sha384),
|
||||
"sha512" => do_pbkdf2!(Sha512),
|
||||
"sha3_224" => do_pbkdf2!(Sha3_224),
|
||||
"sha3_256" => do_pbkdf2!(Sha3_256),
|
||||
"sha3_384" => do_pbkdf2!(Sha3_384),
|
||||
"sha3_512" => do_pbkdf2!(Sha3_512),
|
||||
_ => Err(unsupported_hash(&name, vm)),
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ThreadSafeDynDigest: DynClone + DynDigest + Sync + Send {}
|
||||
impl<T> ThreadSafeDynDigest for T where T: DynClone + DynDigest + Sync + Send {}
|
||||
|
||||
clone_trait_object!(ThreadSafeDynDigest);
|
||||
|
||||
/// Generic wrapper patching around the hashing libraries.
|
||||
#[derive(Clone)]
|
||||
pub struct HashWrapper {
|
||||
block_size: usize,
|
||||
|
||||
@@ -7,6 +7,6 @@ mod _md5 {
|
||||
|
||||
#[pyfunction]
|
||||
fn md5(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_md5(args).into_pyobject(vm))
|
||||
Ok(local_md5(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,6 @@ mod _sha1 {
|
||||
|
||||
#[pyfunction]
|
||||
fn sha1(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha1(args).into_pyobject(vm))
|
||||
Ok(local_sha1(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ mod _sha256 {
|
||||
|
||||
#[pyfunction]
|
||||
fn sha224(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha224(args).into_pyobject(vm))
|
||||
Ok(local_sha224(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha256(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha256(args).into_pyobject(vm))
|
||||
Ok(local_sha256(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
|
||||
|
||||
@@ -10,31 +10,31 @@ mod _sha3 {
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_224(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_224(args).into_pyobject(vm))
|
||||
Ok(local_sha3_224(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_256(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_256(args).into_pyobject(vm))
|
||||
Ok(local_sha3_256(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_384(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_384(args).into_pyobject(vm))
|
||||
Ok(local_sha3_384(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha3_512(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha3_512(args).into_pyobject(vm))
|
||||
Ok(local_sha3_512(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn shake_128(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_shake_128(args).into_pyobject(vm))
|
||||
Ok(local_shake_128(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn shake_256(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_shake_256(args).into_pyobject(vm))
|
||||
Ok(local_shake_256(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ mod _sha512 {
|
||||
|
||||
#[pyfunction]
|
||||
fn sha384(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha384(args).into_pyobject(vm))
|
||||
Ok(local_sha384(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn sha512(args: HashArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(local_sha512(args).into_pyobject(vm))
|
||||
Ok(local_sha512(args, vm)?.into_pyobject(vm))
|
||||
}
|
||||
|
||||
pub(crate) fn module_exec(vm: &VirtualMachine, module: &Py<PyModule>) -> PyResult<()> {
|
||||
|
||||
@@ -397,7 +397,7 @@ impl VirtualMachine {
|
||||
)?;
|
||||
let mode = if write { "w" } else { "r" };
|
||||
stdio.set_attr("mode", self.ctx.new_str(mode), self)?;
|
||||
Ok(stdio)
|
||||
Ok::<_, self::PyBaseExceptionRef>(stdio)
|
||||
};
|
||||
|
||||
// Sandbox stdio: lightweight wrapper using Rust's std::io directly
|
||||
|
||||
Reference in new issue
Block a user