diff --git a/Cargo.lock b/Cargo.lock index 35435cabd..4fe14d22d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,6 +113,17 @@ name = "bitflags" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blake2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "blake2-rfc" version = "0.2.18" @@ -225,6 +236,15 @@ dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "diff" version = "0.1.11" @@ -232,7 +252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "digest" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -357,6 +377,11 @@ dependencies = [ "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hexf" version = "0.1.0" @@ -416,6 +441,11 @@ dependencies = [ "wasm-bindgen 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -505,6 +535,16 @@ name = "maplit" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "md-5" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memchr" version = "2.2.0" @@ -964,9 +1004,12 @@ version = "0.1.0" dependencies = [ "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hexf 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -974,6 +1017,7 @@ dependencies = [ "lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-complex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -989,6 +1033,9 @@ dependencies = [ "rustpython_parser 0.0.1", "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "statrs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-casing 0.1.0 (git+https://github.com/OddCoincidence/unicode-casing?rev=90d6d1f02b9cc04ffb55a5f1c3fa1455a84231fb)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1091,17 +1138,40 @@ dependencies = [ "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha2" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha3" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "siphasher" version = "0.2.3" @@ -1179,6 +1249,11 @@ name = "strsim" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "syn" version = "0.11.11" @@ -1544,6 +1619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" @@ -1559,8 +1635,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" @@ -1576,6 +1653,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hexf 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e54653cc32d838771a36532647afad59c4bf7155745eeeec406f71fd5d7e7538" "checksum hexf-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22eadcfadba76a730b2764eaa577d045f35e0ef5174b9c5b46adf1ee42b85e12" "checksum hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79296f72d53a89096cbc9a88c9547ee8dfe793388674620e2207593d370550ac" @@ -1584,6 +1662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum js-sys 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "9987e7c13a91d9cf0efe59cca48a3a7a70e2b11695d5a4640f85ae71e28f5e73" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lalrpop 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2e80bee40b22bca46665b4ef1f3cd88ed0fb043c971407eac17a0712c02572" "checksum lalrpop-util 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "33b27d8490dbe1f9704b0088d61e8d46edc10d5673a8829836c6ded26a9912c7" @@ -1594,6 +1673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" +"checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" "checksum nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b" @@ -1651,7 +1731,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde-wasm-bindgen 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee6f12f7ed0e7ad2e55200da37dbabc2cadeb942355c5b629aa3771f5ac5636" "checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" @@ -1663,6 +1745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.15.35 (registry+https://github.com/rust-lang/crates.io-index)" = "641e117d55514d6d918490e47102f7e08d096fdde360247e4a10f7a91a8478d3" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" diff --git a/tests/snippets/test_hashlib.py b/tests/snippets/test_hashlib.py new file mode 100644 index 000000000..796f6aefd --- /dev/null +++ b/tests/snippets/test_hashlib.py @@ -0,0 +1,33 @@ + +import hashlib + +# print(hashlib.md5) +h = hashlib.md5() +h.update(b'a') +assert h.name == 'md5' +print(h.hexdigest()) + +assert h.hexdigest() == '0cc175b9c0f1b6a831c399e269772661' +assert h.digest_size == 16 + +h = hashlib.sha256() +h.update(b'a') +assert h.name == 'sha256' +assert h.digest_size == 32 +print(h.hexdigest()) + +assert h.hexdigest() == 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb' + +h = hashlib.sha512() +assert h.name == 'sha512' +h.update(b'a') +print(h.hexdigest()) + +assert h.hexdigest() == '1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75' + +h = hashlib.new("blake2s", b"fubar") +print(h.hexdigest()) +assert h.hexdigest() == 'a0e1ad0c123c9c65e8ef850db2ce4b5cef2c35b06527c615b0154353574d0415' +h.update(b'bla') +print(h.hexdigest()) +assert h.hexdigest() == '25738bfe4cc104131e1b45bece4dfd4e7e1d6f0dffda1211e996e9d5d3b66e81' diff --git a/vm/Cargo.toml b/vm/Cargo.toml index d2dc30e42..0a1b79c6f 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -5,6 +5,14 @@ authors = ["Shing Lyu "] edition = "2018" [dependencies] +# Crypto: +digest = "0.8.1" +md-5 = "0.8" +sha-1 = "0.8" +sha2 = "0.8" +sha3 = "0.8" +blake2 = "0.8" + num-complex = { version = "0.2", features = ["serde"] } num-bigint = { version = "0.2.1", features = ["serde"] } num-traits = "0.2" @@ -27,6 +35,7 @@ unicode-xid = "0.1.0" lazy_static = "^1.0.1" lexical = "2.0.0" itertools = "^0.8.0" +hex = "0.3.2" hexf = "0.1.0" indexmap = "1.0.2" crc = "^1.0.0" diff --git a/vm/src/stdlib/hashlib.rs b/vm/src/stdlib/hashlib.rs new file mode 100644 index 000000000..719e3a329 --- /dev/null +++ b/vm/src/stdlib/hashlib.rs @@ -0,0 +1,282 @@ +use crate::function::{OptionalArg, PyFuncArgs}; +use crate::obj::objbytes::{PyBytes, PyBytesRef}; +use crate::obj::objstr::PyStringRef; +use crate::obj::objtype::PyClassRef; +use crate::pyobject::{PyClassImpl, PyObjectRef, PyResult, PyValue}; +use crate::vm::VirtualMachine; +use std::cell::RefCell; +use std::fmt; + +use blake2::{Blake2b, Blake2s}; +use digest::DynDigest; +use md5::Md5; +use sha1::Sha1; +use sha2::{Sha224, Sha256, Sha384, Sha512}; +use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; // TODO: , Shake128, Shake256}; + +#[pyclass(name = "hasher")] +struct PyHasher { + name: String, + buffer: RefCell, +} + +impl fmt::Debug for PyHasher { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "hasher {}", self.name) + } +} + +impl PyValue for PyHasher { + fn class(vm: &VirtualMachine) -> PyClassRef { + vm.class("hashlib", "hasher") + } +} + +#[pyimpl] +impl PyHasher { + fn new(name: &str, d: HashWrapper) -> Self { + PyHasher { + name: name.to_string(), + buffer: RefCell::new(d), + } + } + + #[pymethod(name = "__new__")] + fn py_new(_cls: PyClassRef, _args: PyFuncArgs, vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("md5", HashWrapper::md5()) + .into_ref(vm) + .into_object()) + } + + #[pyproperty(name = "name")] + fn name(&self, _vm: &VirtualMachine) -> String { + self.name.clone() + } + + #[pyproperty(name = "digest_size")] + fn digest_size(&self, vm: &VirtualMachine) -> PyResult { + Ok(vm.ctx.new_int(self.buffer.borrow().digest_size())) + } + + #[pymethod(name = "update")] + fn update(&self, data: PyBytesRef, vm: &VirtualMachine) -> PyResult { + self.buffer.borrow_mut().input(data.get_value()); + Ok(vm.get_none()) + } + + #[pymethod(name = "digest")] + fn digest(&self, _vm: &VirtualMachine) -> PyBytes { + let result = self.get_digest(); + PyBytes::new(result) + } + + #[pymethod(name = "hexdigest")] + fn hexdigest(&self, _vm: &VirtualMachine) -> String { + let result = self.get_digest(); + hex::encode(result) + } + + fn get_digest(&self) -> Vec { + self.buffer.borrow().get_digest() + } +} + +fn hashlib_new( + name: PyStringRef, + data: OptionalArg, + vm: &VirtualMachine, +) -> PyResult { + let hasher = match name.value.as_ref() { + "md5" => Ok(PyHasher::new("md5", HashWrapper::md5())), + "sha1" => Ok(PyHasher::new("sha1", HashWrapper::sha1())), + "sha224" => Ok(PyHasher::new("sha224", HashWrapper::sha224())), + "sha256" => Ok(PyHasher::new("sha256", HashWrapper::sha256())), + "sha384" => Ok(PyHasher::new("sha384", HashWrapper::sha384())), + "sha512" => Ok(PyHasher::new("sha512", HashWrapper::sha512())), + "sha3_224" => Ok(PyHasher::new("sha3_224", HashWrapper::sha3_224())), + "sha3_256" => Ok(PyHasher::new("sha3_256", HashWrapper::sha3_256())), + "sha3_384" => Ok(PyHasher::new("sha3_384", HashWrapper::sha3_384())), + "sha3_512" => Ok(PyHasher::new("sha3_512", HashWrapper::sha3_512())), + // TODO: "shake128" => Ok(PyHasher::new("shake128", HashWrapper::shake128())), + // TODO: "shake256" => Ok(PyHasher::new("shake256", HashWrapper::shake256())), + "blake2b" => Ok(PyHasher::new("blake2b", HashWrapper::blake2b())), + "blake2s" => Ok(PyHasher::new("blake2s", HashWrapper::blake2s())), + other => Err(vm.new_value_error(format!("Unknown hashing algorithm: {}", other))), + }?; + + if let OptionalArg::Present(data) = data { + hasher.update(data, vm)?; + } + + Ok(hasher) +} + +fn md5(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("md5", HashWrapper::md5())) +} + +fn sha1(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha1", HashWrapper::sha1())) +} + +fn sha224(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha224", HashWrapper::sha224())) +} + +fn sha256(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha256", HashWrapper::sha256())) +} + +fn sha384(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha384", HashWrapper::sha384())) +} + +fn sha512(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha512", HashWrapper::sha512())) +} + +fn sha3_224(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha3_224", HashWrapper::sha3_224())) +} + +fn sha3_256(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha3_256", HashWrapper::sha3_256())) +} + +fn sha3_384(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha3_384", HashWrapper::sha3_384())) +} + +fn sha3_512(_vm: &VirtualMachine) -> PyResult { + Ok(PyHasher::new("sha3_512", HashWrapper::sha3_512())) +} + +fn shake128(vm: &VirtualMachine) -> PyResult { + Err(vm.new_not_implemented_error("shake256".to_string())) + // Ok(PyHasher::new("shake128", HashWrapper::shake128())) +} + +fn shake256(vm: &VirtualMachine) -> PyResult { + Err(vm.new_not_implemented_error("shake256".to_string())) + // TODO: Ok(PyHasher::new("shake256", HashWrapper::shake256())) +} + +fn blake2b(_vm: &VirtualMachine) -> PyResult { + // TODO: handle parameters + Ok(PyHasher::new("blake2b", HashWrapper::blake2b())) +} + +fn blake2s(_vm: &VirtualMachine) -> PyResult { + // TODO: handle parameters + Ok(PyHasher::new("blake2s", HashWrapper::blake2s())) +} + +pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { + let ctx = &vm.ctx; + + let hasher_type = PyHasher::make_class(ctx); + + py_module!(vm, "hashlib", { + "new" => ctx.new_rustfunc(hashlib_new), + "md5" => ctx.new_rustfunc(md5), + "sha1" => ctx.new_rustfunc(sha1), + "sha224" => ctx.new_rustfunc(sha224), + "sha256" => ctx.new_rustfunc(sha256), + "sha384" => ctx.new_rustfunc(sha384), + "sha512" => ctx.new_rustfunc(sha512), + "sha3_224" => ctx.new_rustfunc(sha3_224), + "sha3_256" => ctx.new_rustfunc(sha3_256), + "sha3_384" => ctx.new_rustfunc(sha3_384), + "sha3_512" => ctx.new_rustfunc(sha3_512), + "shake128" => ctx.new_rustfunc(shake128), + "shake256" => ctx.new_rustfunc(shake256), + "blake2b" => ctx.new_rustfunc(blake2b), + "blake2s" => ctx.new_rustfunc(blake2s), + "hasher" => hasher_type, + }) +} + +/// Generic wrapper patching around the hashing libraries. +struct HashWrapper { + inner: Box, +} + +impl HashWrapper { + fn new(d: D) -> Self + where + D: DynDigest, + D: Sized, + { + HashWrapper { inner: Box::new(d) } + } + + fn md5() -> Self { + Self::new(Md5::default()) + } + + fn sha1() -> Self { + Self::new(Sha1::default()) + } + + fn sha224() -> Self { + Self::new(Sha224::default()) + } + + fn sha256() -> Self { + Self::new(Sha256::default()) + } + + fn sha384() -> Self { + Self::new(Sha384::default()) + } + + fn sha512() -> Self { + Self::new(Sha512::default()) + } + + fn sha3_224() -> Self { + Self::new(Sha3_224::default()) + } + + fn sha3_256() -> Self { + Self::new(Sha3_256::default()) + } + + fn sha3_384() -> Self { + Self::new(Sha3_384::default()) + } + + fn sha3_512() -> Self { + Self::new(Sha3_512::default()) + } + + /* TODO: + fn shake128() -> Self { + Self::new(Shake128::default()) + } + + fn shake256() -> Self { + Self::new(Shake256::default()) + } + */ + fn blake2b() -> Self { + Self::new(Blake2b::default()) + } + + fn blake2s() -> Self { + Self::new(Blake2s::default()) + } + + fn input(&mut self, data: &[u8]) { + self.inner.input(data); + } + + fn digest_size(&self) -> usize { + self.inner.output_size() + } + + fn get_digest(&self) -> Vec { + let cloned = self.inner.clone(); + cloned.result().to_vec() + } +} diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index 8329b3092..f62d073d4 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -1,6 +1,7 @@ mod ast; mod binascii; mod dis; +mod hashlib; mod imp; mod itertools; mod json; @@ -39,6 +40,7 @@ pub fn get_module_inits() -> HashMap { "ast".to_string() => Box::new(ast::make_module) as StdlibInitFunc, "binascii".to_string() => Box::new(binascii::make_module), "dis".to_string() => Box::new(dis::make_module), + "hashlib".to_string() => Box::new(hashlib::make_module), "itertools".to_string() => Box::new(itertools::make_module), "json".to_string() => Box::new(json::make_module), "keyword".to_string() => Box::new(keyword::make_module),