diff --git a/Cargo.lock b/Cargo.lock index 58df6b6..18bfa89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,6 +277,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hex-literal" version = "0.4.1" @@ -361,7 +367,7 @@ checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "picca" -version = "0.4.0" +version = "0.5.0" dependencies = [ "ascon-hash", "belt-hash", @@ -372,6 +378,7 @@ dependencies = [ "fsb", "gost94", "groestl", + "hex", "jh", "k12", "md-5", diff --git a/Cargo.toml b/Cargo.toml index 9d50ef8..ad439c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "picca" -version = "0.4.0" -edition = "2021" +version = "0.5.0" +edition = "2024" [dependencies] sha2 = "0.10.9" @@ -29,3 +29,4 @@ tiger = "0.2.1" whirlpool = "0.10.4" blake3 = "1.8.2" quit = "2.0.0" +hex = "0.4.3" diff --git a/docker/Dockerfile b/docker/Dockerfile index 0ae8f70..a07ce05 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -21,7 +21,6 @@ LABEL org.opencontainers.image.source="https://forge.steck.dev/bryson/picca" LABEL org.opencontainers.image.created="${DATE}" RUN apk upgrade --no-cache -RUN mkdir /etc/picca COPY ./docker/entrypoint.sh /usr/local/bin/entrypoint.sh COPY --from=build /usr/src/picca /usr/src diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 5d9bf19..670fbe0 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -2,13 +2,13 @@ # Entrypoint file for picca Docker containers if [ -z "$UID" ]; then - echo "UID not set! Setting to id $(id -u)" - export UID=$(id -u) + echo "UID not set! Setting to default 1000" >> /dev/stderr + export UID=1000 fi if [ -z "$GID" ]; then - echo "GID not set! Setting to id $(id -g)" - export GID=$(id -g) + echo "GID not set! Setting to default 1000" >> /dev/stderr + export GID=1000 fi addgroup -g $GID dockeruser diff --git a/src/hashers.rs b/src/hashers.rs index 84e58b9..dbdb0b2 100644 --- a/src/hashers.rs +++ b/src/hashers.rs @@ -15,87 +15,131 @@ use sha1::Sha1; use sha2::{Digest as _, Sha224, Sha256, Sha384, Sha512}; use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256}; use shabal::{Shabal192, Shabal224, Shabal256, Shabal384, Shabal512}; -use skein::{consts::U32, Skein1024, Skein256, Skein512}; +use skein::{Skein256, Skein512, Skein1024, consts::U32}; use sm3::Sm3; -use std::io; +use std::io::{self, Write}; use std::{fs::File, io::Read}; use streebog::{Streebog256, Streebog512}; use tiger::Tiger; use whirlpool::Whirlpool; -pub fn hash_streebog256(mut file: File) -> String { +pub fn hash_streebog256(file: Option, stdin: Option) -> String { let mut hasher = Streebog256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_streebog512(mut file: File) -> String { +pub fn hash_streebog512(file: Option, stdin: Option) -> String { let mut hasher = Streebog512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_tiger(mut file: File) -> String { +pub fn hash_tiger(file: Option, stdin: Option) -> String { let mut hasher = Tiger::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_whirlpool(mut file: File) -> String { +pub fn hash_whirlpool(file: Option, stdin: Option) -> String { let mut hasher = Whirlpool::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha224(mut file: File) -> String { +pub fn hash_sha224(file: Option, stdin: Option) -> String { let mut hasher = Sha224::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sm3(mut file: File) -> String { +pub fn hash_sm3(file: Option, stdin: Option) -> String { let mut hasher = Sm3::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha3_224(mut file: File) -> String { +pub fn hash_sha3_224(file: Option, stdin: Option) -> String { let mut hasher = Sha3_224::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha3_256(mut file: File) -> String { +pub fn hash_sha3_256(file: Option, stdin: Option) -> String { let mut hasher = Sha3_256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha3_384(mut file: File) -> String { +pub fn hash_sha3_384(file: Option, stdin: Option) -> String { let mut hasher = Sha3_384::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha3_512(mut file: File) -> String { +pub fn hash_sha3_512(file: Option, stdin: Option) -> String { let mut hasher = Sha3_512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_shake128(mut file: File) -> String { +pub fn hash_shake128(file: Option, stdin: Option) -> String { let mut hasher = Shake128::default(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + _ = hasher.write_fmt(format_args!("{}", stdin.unwrap())); + } let mut result = String::new(); let mut finalized = hasher.finalize_xof(); @@ -104,9 +148,13 @@ pub fn hash_shake128(mut file: File) -> String { return format!("{}", result); } -pub fn hash_shake256(mut file: File) -> String { +pub fn hash_shake256(file: Option, stdin: Option) -> String { let mut hasher = Shake256::default(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + _ = hasher.write_fmt(format_args!("{}", stdin.unwrap())); + } let mut result = String::new(); let mut finalized = hasher.finalize_xof(); @@ -115,128 +163,200 @@ pub fn hash_shake256(mut file: File) -> String { return format!("{}", result); } -pub fn hash_shabal192(mut file: File) -> String { +pub fn hash_shabal192(file: Option, stdin: Option) -> String { let mut hasher = Shabal192::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_shabal224(mut file: File) -> String { +pub fn hash_shabal224(file: Option, stdin: Option) -> String { let mut hasher = Shabal224::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_shabal256(mut file: File) -> String { +pub fn hash_shabal256(file: Option, stdin: Option) -> String { let mut hasher = Shabal256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_shabal384(mut file: File) -> String { +pub fn hash_shabal384(file: Option, stdin: Option) -> String { let mut hasher = Shabal384::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_shabal512(mut file: File) -> String { +pub fn hash_shabal512(file: Option, stdin: Option) -> String { let mut hasher = Shabal512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_skein256(mut file: File) -> String { +pub fn hash_skein256(file: Option, stdin: Option) -> String { let mut hasher = Skein256::::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_skein512(mut file: File) -> String { +pub fn hash_skein512(file: Option, stdin: Option) -> String { let mut hasher = Skein512::::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_skein1024(mut file: File) -> String { +pub fn hash_skein1024(file: Option, stdin: Option) -> String { let mut hasher = Skein1024::::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_gost94(mut file: File) -> String { +pub fn hash_gost94(file: Option, stdin: Option) -> String { let mut hasher = Gost94CryptoPro::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_groestl224(mut file: File) -> String { +pub fn hash_groestl224(file: Option, stdin: Option) -> String { let mut hasher = Groestl224::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_groestl256(mut file: File) -> String { +pub fn hash_groestl256(file: Option, stdin: Option) -> String { let mut hasher = Groestl256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_groestl384(mut file: File) -> String { +pub fn hash_groestl384(file: Option, stdin: Option) -> String { let mut hasher = Groestl384::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_groestl512(mut file: File) -> String { +pub fn hash_groestl512(file: Option, stdin: Option) -> String { let mut hasher = Groestl512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_jh224(mut file: File) -> String { +pub fn hash_jh224(file: Option, stdin: Option) -> String { let mut hasher = Jh224::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_jh256(mut file: File) -> String { +pub fn hash_jh256(file: Option, stdin: Option) -> String { let mut hasher = Jh256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_jh384(mut file: File) -> String { +pub fn hash_jh384(file: Option, stdin: Option) -> String { let mut hasher = Jh384::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_jh512(mut file: File) -> String { +pub fn hash_jh512(file: Option, stdin: Option) -> String { let mut hasher = Jh512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_k12(mut file: File) -> String { +pub fn hash_k12(file: Option, stdin: Option) -> String { let mut hasher = KangarooTwelve::default(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + _ = hasher.write_fmt(format_args!("{}", stdin.unwrap())); + } let mut result = String::new(); let mut finalized = hasher.finalize_xof(); @@ -245,149 +365,233 @@ pub fn hash_k12(mut file: File) -> String { return format!("{}", result); } -pub fn hash_md2(mut file: File) -> String { +pub fn hash_md2(file: Option, stdin: Option) -> String { let mut hasher = Md2::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_md4(mut file: File) -> String { +pub fn hash_md4(file: Option, stdin: Option) -> String { let mut hasher = Md4::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_ripemd128(mut file: File) -> String { +pub fn hash_ripemd128(file: Option, stdin: Option) -> String { let mut hasher = Ripemd128::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_ripemd160(mut file: File) -> String { +pub fn hash_ripemd160(file: Option, stdin: Option) -> String { let mut hasher = Ripemd160::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_ripemd256(mut file: File) -> String { +pub fn hash_ripemd256(file: Option, stdin: Option) -> String { let mut hasher = Ripemd256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_ripemd320(mut file: File) -> String { +pub fn hash_ripemd320(file: Option, stdin: Option) -> String { let mut hasher = Ripemd320::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_ascon(mut file: File) -> String { +pub fn hash_ascon(file: Option, stdin: Option) -> String { let mut hasher = AsconHash256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_belt(mut file: File) -> String { +pub fn hash_belt(file: Option, stdin: Option) -> String { let mut hasher = BeltHash::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_blake3(mut file: File) -> String { +pub fn hash_blake3(file: Option, stdin: Option) -> String { let mut hasher = Blake3::default(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + _ = hasher.write_fmt(format_args!("{}", stdin.unwrap())); + } return format!("{}", hasher.finalize().to_hex()); } -pub fn hash_blake2b512(mut file: File) -> String { +pub fn hash_blake2b512(file: Option, stdin: Option) -> String { let mut hasher = Blake2b512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_blake2s256(mut file: File) -> String { +pub fn hash_blake2s256(file: Option, stdin: Option) -> String { let mut hasher = Blake2s256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_fsb160(mut file: File) -> String { +pub fn hash_fsb160(file: Option, stdin: Option) -> String { let mut hasher = Fsb160::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_fsb224(mut file: File) -> String { +pub fn hash_fsb224(file: Option, stdin: Option) -> String { let mut hasher = Fsb224::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_fsb256(mut file: File) -> String { +pub fn hash_fsb256(file: Option, stdin: Option) -> String { let mut hasher = Fsb256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_fsb384(mut file: File) -> String { +pub fn hash_fsb384(file: Option, stdin: Option) -> String { let mut hasher = Fsb384::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_fsb512(mut file: File) -> String { +pub fn hash_fsb512(file: Option, stdin: Option) -> String { let mut hasher = Fsb512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_md5(mut file: File) -> String { +pub fn hash_md5(file: Option, stdin: Option) -> String { let mut hasher = Md5::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha1(mut file: File) -> String { +pub fn hash_sha1(file: Option, stdin: Option) -> String { let mut hasher = Sha1::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha256(mut file: File) -> String { +pub fn hash_sha256(file: Option, stdin: Option) -> String { let mut hasher = Sha256::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha384(mut file: File) -> String { +pub fn hash_sha384(file: Option, stdin: Option) -> String { let mut hasher = Sha384::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } -pub fn hash_sha512(mut file: File) -> String { +pub fn hash_sha512(file: Option, stdin: Option) -> String { let mut hasher = Sha512::new(); - _ = io::copy(&mut file, &mut hasher); + if file.is_some() { + _ = io::copy(&mut file.unwrap(), &mut hasher); + } else if stdin.is_some() { + hasher.update(stdin.unwrap()); + } return format!("{:x}", hasher.finalize()); } diff --git a/src/main.rs b/src/main.rs index 2813e52..0ea7ecc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ use clap::Parser; use std::collections::{HashMap, VecDeque}; -use std::fs::{self, read_to_string, File}; +use std::fs::{self, File, read_to_string}; +use std::io::{self, Read}; use std::path::PathBuf; use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::{Arc, Mutex}; -use std::thread::{self, available_parallelism, JoinHandle}; +use std::thread::{self, JoinHandle, available_parallelism}; mod common; mod hashers; @@ -128,7 +129,7 @@ struct Args { )] quiet: bool, - #[arg(trailing_var_arg = true, required_unless_present("check"))] + #[arg(trailing_var_arg = true)] files: Vec, } @@ -145,6 +146,8 @@ struct ThreadInfo { fn hash(info: ThreadInfo) -> Result<(), String> { loop { + let mut stdin = None; + let mut file = None; let filename = match info.filenames.lock().unwrap().pop_front() { Some(f) => f, None => break, @@ -158,73 +161,81 @@ fn hash(info: ThreadInfo) -> Result<(), String> { )); } - if filename.is_dir() { + if filename.display().to_string() == "-" { + let mut buffer = String::new(); + match io::stdin().lock().read_to_string(&mut buffer) { + Ok(_) => (), + Err(e) => common::error(format!("stdin: {}", e)), + } + + stdin = Some(buffer) + } else if filename.is_dir() { common::error(format!("{}: Is a directory", filename.as_path().display())); info.file_errors.fetch_add(1, Ordering::SeqCst); continue; + } else { + file = Some(match File::open(&filename) { + Err(e) => { + println!("{}: FAILED ({})", filename.as_path().display(), e); + info.file_errors.fetch_add(1, Ordering::SeqCst); + continue; + }, + Ok(f) => f, + }); } - let file = match File::open(&filename) { - Err(e) => { - println!("{}: FAILED ({})", filename.as_path().display(), e); - info.file_errors.fetch_add(1, Ordering::SeqCst); - continue; - }, - Ok(f) => f, - }; - let res = match &*info.algorithm.as_str() { - "ascon" => hashers::hash_ascon(file), - "belt" => hashers::hash_belt(file), - "blake2b512" => hashers::hash_blake2b512(file), - "blake2s256" => hashers::hash_blake2s256(file), - "blake3" => hashers::hash_blake3(file), - "fsb160" => hashers::hash_fsb160(file), - "fsb224" => hashers::hash_fsb224(file), - "fsb256" => hashers::hash_fsb256(file), - "fsb384" => hashers::hash_fsb384(file), - "fsb512" => hashers::hash_fsb512(file), - "gost94" => hashers::hash_gost94(file), - "groestl224" => hashers::hash_groestl224(file), - "groestl256" => hashers::hash_groestl256(file), - "groestl384" => hashers::hash_groestl384(file), - "groestl512" => hashers::hash_groestl512(file), - "jh224" => hashers::hash_jh224(file), - "jh256" => hashers::hash_jh256(file), - "jh384" => hashers::hash_jh384(file), - "jh512" => hashers::hash_jh512(file), - "k12" => hashers::hash_k12(file), - "md2" => hashers::hash_md2(file), - "md4" => hashers::hash_md4(file), - "md5" => hashers::hash_md5(file), - "ripemd128" => hashers::hash_ripemd128(file), - "ripemd160" => hashers::hash_ripemd160(file), - "ripemd256" => hashers::hash_ripemd256(file), - "ripemd320" => hashers::hash_ripemd320(file), - "sha1" => hashers::hash_sha1(file), - "sha224" => hashers::hash_sha224(file), - "sha256" => hashers::hash_sha256(file), - "sha384" => hashers::hash_sha384(file), - "sha512" => hashers::hash_sha512(file), - "sha3_224" => hashers::hash_sha3_224(file), - "sha3_256" => hashers::hash_sha3_256(file), - "sha3_384" => hashers::hash_sha3_384(file), - "sha3_512" => hashers::hash_sha3_512(file), - "shabal192" => hashers::hash_shabal192(file), - "shabal224" => hashers::hash_shabal224(file), - "shabal256" => hashers::hash_shabal256(file), - "shabal384" => hashers::hash_shabal384(file), - "shabal512" => hashers::hash_shabal512(file), - "shake128" => hashers::hash_shake128(file), - "shake256" => hashers::hash_shake256(file), - "skein256" => hashers::hash_skein256(file), - "skein512" => hashers::hash_skein512(file), - "skein1024" => hashers::hash_skein1024(file), - "sm3" => hashers::hash_sm3(file), - "streebog256" => hashers::hash_streebog256(file), - "streebog512" => hashers::hash_streebog512(file), - "tiger" => hashers::hash_tiger(file), - "whirlpool" => hashers::hash_whirlpool(file), + "ascon" => hashers::hash_ascon(file, stdin), + "belt" => hashers::hash_belt(file, stdin), + "blake2b512" => hashers::hash_blake2b512(file, stdin), + "blake2s256" => hashers::hash_blake2s256(file, stdin), + "blake3" => hashers::hash_blake3(file, stdin), + "fsb160" => hashers::hash_fsb160(file, stdin), + "fsb224" => hashers::hash_fsb224(file, stdin), + "fsb256" => hashers::hash_fsb256(file, stdin), + "fsb384" => hashers::hash_fsb384(file, stdin), + "fsb512" => hashers::hash_fsb512(file, stdin), + "gost94" => hashers::hash_gost94(file, stdin), + "groestl224" => hashers::hash_groestl224(file, stdin), + "groestl256" => hashers::hash_groestl256(file, stdin), + "groestl384" => hashers::hash_groestl384(file, stdin), + "groestl512" => hashers::hash_groestl512(file, stdin), + "jh224" => hashers::hash_jh224(file, stdin), + "jh256" => hashers::hash_jh256(file, stdin), + "jh384" => hashers::hash_jh384(file, stdin), + "jh512" => hashers::hash_jh512(file, stdin), + "k12" => hashers::hash_k12(file, stdin), + "md2" => hashers::hash_md2(file, stdin), + "md4" => hashers::hash_md4(file, stdin), + "md5" => hashers::hash_md5(file, stdin), + "ripemd128" => hashers::hash_ripemd128(file, stdin), + "ripemd160" => hashers::hash_ripemd160(file, stdin), + "ripemd256" => hashers::hash_ripemd256(file, stdin), + "ripemd320" => hashers::hash_ripemd320(file, stdin), + "sha1" => hashers::hash_sha1(file, stdin), + "sha224" => hashers::hash_sha224(file, stdin), + "sha256" => hashers::hash_sha256(file, stdin), + "sha384" => hashers::hash_sha384(file, stdin), + "sha512" => hashers::hash_sha512(file, stdin), + "sha3_224" => hashers::hash_sha3_224(file, stdin), + "sha3_256" => hashers::hash_sha3_256(file, stdin), + "sha3_384" => hashers::hash_sha3_384(file, stdin), + "sha3_512" => hashers::hash_sha3_512(file, stdin), + "shabal192" => hashers::hash_shabal192(file, stdin), + "shabal224" => hashers::hash_shabal224(file, stdin), + "shabal256" => hashers::hash_shabal256(file, stdin), + "shabal384" => hashers::hash_shabal384(file, stdin), + "shabal512" => hashers::hash_shabal512(file, stdin), + "shake128" => hashers::hash_shake128(file, stdin), + "shake256" => hashers::hash_shake256(file, stdin), + "skein256" => hashers::hash_skein256(file, stdin), + "skein512" => hashers::hash_skein512(file, stdin), + "skein1024" => hashers::hash_skein1024(file, stdin), + "sm3" => hashers::hash_sm3(file, stdin), + "streebog256" => hashers::hash_streebog256(file, stdin), + "streebog512" => hashers::hash_streebog512(file, stdin), + "tiger" => hashers::hash_tiger(file, stdin), + "whirlpool" => hashers::hash_whirlpool(file, stdin), _ => panic!("Somehow did not pass a supported algorithm"), }; @@ -290,11 +301,18 @@ fn verify( }; } + let threads; + if buffer.len() >= cpus { + threads = cpus + } else { + threads = buffer.len() + } + let arc_fe = Arc::new(AtomicI32::new(0)); let arc_he = Arc::new(AtomicI32::new(0)); let arc_buf = Arc::new(Mutex::new(buffer)); let arc_hash = Arc::new(Mutex::new(hash_map)); - for i in 0..cpus { + for i in 0..threads { let safe_fe = Arc::clone(&arc_fe); let safe_he = Arc::clone(&arc_he); let safe_buf = Arc::clone(&arc_buf); @@ -328,11 +346,18 @@ fn generate( Arc, Arc, ) { + let threads; + if buffer.len() >= cpus { + threads = cpus + } else { + threads = buffer.len() + } + let mut handles = vec![]; let arc_fe = Arc::new(AtomicI32::new(0)); let arc_he = Arc::new(AtomicI32::new(0)); let arc_buf = Arc::new(Mutex::new(buffer)); - for i in 0..cpus { + for i in 0..threads { let safe_fe = Arc::clone(&arc_fe); let safe_he = Arc::clone(&arc_he); let safe_buf = Arc::clone(&arc_buf); @@ -357,6 +382,14 @@ fn generate( #[quit::main] fn main() { let args = Args::parse(); + let docker = match option_env!("PICCA_DOCKER") { + Some(v) => match v { + "true" => true, + _ => false, + }, + None => false, + }; + let cpus = match args.threads { 0 => available_parallelism().unwrap().get(), _ => args.threads, @@ -364,9 +397,13 @@ fn main() { if args.debug { common::debug(format!( - "Starting psha using algorithm {} with {} threads", + "Starting picca using algorithm {} with a max of {} threads", args.algorithm, cpus )); + + if docker { + common::debug(format!("Docker is detected")); + } } if UNSECURE_ALGORITHMS.contains(&args.algorithm.as_str()) { @@ -379,20 +416,25 @@ fn main() { let handles; let arc_fe; let arc_he; - let check_mode = ! args.check.is_empty(); + let check_mode = !args.check.is_empty(); if &args.check.len() >= &1 { (handles, arc_fe, arc_he) = verify(cpus, args.algorithm, args.debug, args.quiet, args.check); } else { let mut buffer = VecDeque::new(); - for file in args.files { - if args.canonicalize { - match fs::canonicalize(file.as_path()) { - Ok(p) => buffer.push_back(p), - Err(e) => panic!("unable to canonicalize {}: {}", file.as_path().display(), e), - }; - } else { - buffer.push_back(file); + if &args.files.len() >= &1 { + for file in args.files { + if args.canonicalize { + match fs::canonicalize(file.as_path()) { + Ok(p) => buffer.push_back(p), + Err(e) => panic!("unable to canonicalize {}: {}", file.as_path().display(), e), + }; + } else { + buffer.push_back(file); + } } + } else { + // read from stdin instead + buffer.push_back(PathBuf::from("-")); } (handles, arc_fe, arc_he) = generate(cpus, buffer, args.algorithm, args.debug, args.quiet);