Skip to content

Commit 0a369d8

Browse files
committed
Add initial hashlib module.
1 parent 0642412 commit 0a369d8

4 files changed

Lines changed: 164 additions & 0 deletions

File tree

tests/snippets/test_hashlib.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
import hashlib
3+
4+
# print(hashlib.md5)
5+
h = hashlib.md5()
6+
h.update(b'a')
7+
print(h.hexdigest())
8+
9+
assert h.hexdigest() == '0cc175b9c0f1b6a831c399e269772661'
10+
11+
h = hashlib.sha256()
12+
h.update(b'a')
13+
print(h.hexdigest())
14+
15+
assert h.hexdigest() == 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb'
16+
17+
h = hashlib.sha512()
18+
h.update(b'a')
19+
print(h.hexdigest())
20+
21+
assert h.hexdigest() == '1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75'

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ serde_json = "1.0.26"
2020
byteorder = "1.2.6"
2121
regex = "1"
2222
rustc_version_runtime = "0.1.*"
23+
rust-crypto = "0.2.36"
2324
statrs = "0.10.0"
2425
caseless = "0.2.1"
2526
unicode-segmentation = "1.2.1"

vm/src/stdlib/hashlib.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use crate::function::PyFuncArgs;
2+
use crate::obj::objbytes::PyBytesRef;
3+
use crate::obj::objtype::PyClassRef;
4+
use crate::pyobject::{PyClassImpl, PyObjectRef, PyResult, PyValue};
5+
use crate::vm::VirtualMachine;
6+
use std::cell::RefCell;
7+
use std::fmt;
8+
9+
use crypto;
10+
use crypto::digest::Digest;
11+
12+
#[pyclass(name = "hasher")]
13+
struct PyHasher {
14+
name: String,
15+
buffer: Box<RefCell<Digest>>,
16+
}
17+
18+
impl fmt::Debug for PyHasher {
19+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20+
write!(f, "hasher {}", self.name)
21+
}
22+
}
23+
24+
impl PyValue for PyHasher {
25+
fn class(vm: &VirtualMachine) -> PyClassRef {
26+
vm.class("hashlib", "hasher")
27+
}
28+
}
29+
30+
#[pyimpl]
31+
impl PyHasher {
32+
// fn new<D: 'static>(d: D) -> Self where D: Digest, D: Sized {
33+
fn new<D: 'static>(name: &str, d: D) -> Self
34+
where
35+
D: Digest,
36+
D: Sized,
37+
{
38+
/*
39+
let d = match name {
40+
"md5" => crypto::md5::Md5::new(),
41+
crypto::sha2::Sha256::new()
42+
};
43+
*/
44+
45+
PyHasher {
46+
name: name.to_string(),
47+
buffer: Box::new(RefCell::new(d)),
48+
}
49+
}
50+
51+
#[pymethod(name = "__new__")]
52+
fn py_new(_cls: PyClassRef, _args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
53+
Ok(PyHasher::new("md5", crypto::md5::Md5::new())
54+
.into_ref(vm)
55+
.into_object())
56+
}
57+
58+
#[pymethod(name = "update")]
59+
fn update(&self, data: PyBytesRef, vm: &VirtualMachine) -> PyResult {
60+
self.buffer.borrow_mut().input(data.get_value());
61+
Ok(vm.get_none())
62+
}
63+
64+
#[pymethod(name = "hexdigest")]
65+
fn hexdigest(&self, vm: &VirtualMachine) -> PyResult {
66+
Ok(vm.new_str(self.buffer.borrow_mut().result_str()))
67+
}
68+
}
69+
70+
fn md5(_vm: &VirtualMachine) -> PyResult<PyHasher> {
71+
Ok(PyHasher::new("md5", crypto::md5::Md5::new()))
72+
}
73+
74+
fn sha1(_vm: &VirtualMachine) -> PyResult<PyHasher> {
75+
Ok(PyHasher::new("sha1", crypto::sha1::Sha1::new()))
76+
}
77+
78+
fn sha224(_vm: &VirtualMachine) -> PyResult<PyHasher> {
79+
Ok(PyHasher::new("224", crypto::sha2::Sha224::new()))
80+
}
81+
82+
fn sha256(_vm: &VirtualMachine) -> PyResult<PyHasher> {
83+
Ok(PyHasher::new("sha256", crypto::sha2::Sha256::new()))
84+
}
85+
86+
fn sha384(_vm: &VirtualMachine) -> PyResult<PyHasher> {
87+
Ok(PyHasher::new("sha384", crypto::sha2::Sha384::new()))
88+
}
89+
90+
fn sha512(_vm: &VirtualMachine) -> PyResult<PyHasher> {
91+
Ok(PyHasher::new("sha512", crypto::sha2::Sha512::new()))
92+
}
93+
94+
fn sha3_224(_vm: &VirtualMachine) -> PyResult<PyHasher> {
95+
Ok(PyHasher::new("sha3_224", crypto::sha3::Sha3::sha3_224()))
96+
}
97+
98+
fn sha3_256(_vm: &VirtualMachine) -> PyResult<PyHasher> {
99+
Ok(PyHasher::new("sha3_256", crypto::sha3::Sha3::sha3_256()))
100+
}
101+
102+
fn sha3_384(_vm: &VirtualMachine) -> PyResult<PyHasher> {
103+
Ok(PyHasher::new("sha3_384", crypto::sha3::Sha3::sha3_384()))
104+
}
105+
106+
fn sha3_512(_vm: &VirtualMachine) -> PyResult<PyHasher> {
107+
Ok(PyHasher::new("sha3_512", crypto::sha3::Sha3::sha3_512()))
108+
}
109+
110+
fn blake2b(_vm: &VirtualMachine) -> PyResult<PyHasher> {
111+
// TODO: handle parameters
112+
Ok(PyHasher::new("blake2b", crypto::blake2b::Blake2b::new(0)))
113+
}
114+
115+
fn blake2s(_vm: &VirtualMachine) -> PyResult<PyHasher> {
116+
// TODO: handle parameters
117+
Ok(PyHasher::new("blake2s", crypto::blake2s::Blake2s::new(0)))
118+
}
119+
120+
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
121+
let ctx = &vm.ctx;
122+
123+
let hasher_type = PyHasher::make_class(ctx);
124+
125+
py_module!(vm, "hashlib", {
126+
"md5" => ctx.new_rustfunc(md5),
127+
"sha1" => ctx.new_rustfunc(sha1),
128+
"sha224" => ctx.new_rustfunc(sha224),
129+
"sha256" => ctx.new_rustfunc(sha256),
130+
"sha384" => ctx.new_rustfunc(sha384),
131+
"sha512" => ctx.new_rustfunc(sha512),
132+
"sha3_224" => ctx.new_rustfunc(sha3_224),
133+
"sha3_256" => ctx.new_rustfunc(sha3_256),
134+
"sha3_384" => ctx.new_rustfunc(sha3_384),
135+
"sha3_512" => ctx.new_rustfunc(sha3_512),
136+
"blake2b" => ctx.new_rustfunc(blake2b),
137+
"blake2s" => ctx.new_rustfunc(blake2s),
138+
"hasher" => hasher_type,
139+
})
140+
}

vm/src/stdlib/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod ast;
22
mod binascii;
33
mod dis;
4+
mod hashlib;
45
mod imp;
56
mod itertools;
67
mod json;
@@ -39,6 +40,7 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
3940
"ast".to_string() => Box::new(ast::make_module) as StdlibInitFunc,
4041
"binascii".to_string() => Box::new(binascii::make_module),
4142
"dis".to_string() => Box::new(dis::make_module),
43+
"hashlib".to_string() => Box::new(hashlib::make_module),
4244
"itertools".to_string() => Box::new(itertools::make_module),
4345
"json".to_string() => Box::new(json::make_module),
4446
"keyword".to_string() => Box::new(keyword::make_module),

0 commit comments

Comments
 (0)