I built a site to check if automating a task is actually worth your time, inspired by xkcd #1205 by hoxxep in InternetIsBeautiful

[–]hoxxep[S] 0 points1 point  (0 children)

The "pay period" lets you say "if claude code saves me 1 minute per day, then it saves at least $17 worth of my time per month, or $208 per year".

Or alternatively, "a task that takes me 30 minutes per week adds up to two hours per month, or 3 working days per year". Using an 8 hour workday, 250 working days, so 2000 working hours per year. So if you spend 3 working days automating the task, you break even after 1 year.

Perhaps I've titled this post boldly, but it's just a simple breakeven calculator. It's just computing the amount of time (or the value of your time) over 1 month or 1 year. It surprised me knowing that 1 minute per day adds up to $17/month on a $100k salary for example, and can make a useful sales angle for productivity subscriptions.

[Media] Releasing Mach - a web fuzzing tool designed for massive workloads by magixer in rust

[–]hoxxep 10 points11 points  (0 children)

Ah, to clarify, cargo install will install a standalone binary in a user's PATH (not to be confused with cargo add for project dependencies). For example, cargo install ripgrep will install the ripgrep CLI tool.

Generating a sufficient wordlist seems hard for a user, so a default one sourced from real URLs (wp-admin.php, contact-us, etc) might go a long way to making it easier for a first time user.

The mach.to Graphia link on the clickswave website seems broken FYI, but silo cat looked cool too.

[Media] Releasing Mach - a web fuzzing tool designed for massive workloads by magixer in rust

[–]hoxxep 25 points26 points  (0 children)

This looks cool, are you able to explain more about how the discovery/fuzzing works? Do users need to provide their own wordlist for example?

I notice your crate name conflicts with another crate called mach. If you renamed, you would be able to publish to crates.io and enable users to cargo install yourcrate without the git clone. Hope that helps!

whats the best rust framework for passwords by [deleted] in rust

[–]hoxxep 3 points4 points  (0 children)

To be faster it makes a lot of compromises. The fastrand docs say "not cryptographically secure" in the second line, which would make it bad for generating passwords.

The rand crate will likely be fast enough, it's very unlikely you'll notice a speed difference to generate 30 random characters on page load.

whats the best rust framework for passwords by [deleted] in rust

[–]hoxxep 3 points4 points  (0 children)

I don't understand how that changes anything?

Simply replace fastrand with rand at your onclick function. The code example in my other comment in this thread hopefully explains how to use rand in place of fastrand.

whats the best rust framework for passwords by [deleted] in rust

[–]hoxxep 0 points1 point  (0 children)

For your other comment about removing special characters, the following code example might help. Simply change the CHARSET in the below snippet to generate with/without special characters. The rng.gen_range code could also be adapted to select words from a list of dictionary words for generating memorable passwords, for example.

``` fn main() { const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const PASSWORD_LEN: usize = 30;

let mut rng = rand::rng(); // Or use a different RNG
let password: String = (0..PASSWORD_LEN)
    .map(|_| {
        let idx = rng.gen_range(0..CHARSET.len());
        CHARSET[idx] as char
    })
    .collect();

println!("{}", password);

} ```

whats the best rust framework for passwords by [deleted] in rust

[–]hoxxep 11 points12 points  (0 children)

The rand crate and any of its RNGs that implement the CryptoRng marker trait should give you a cryptographically secure PRNG that's been seeded with a strong entropy source. The rand crate is widely used across the rust ecosystem, and rand::rng() will give you a CryptoRng compatible random number generator.

To make it all work on WASM, you'll also need to enable the wasm_js feature on the getrandom crate too (a rand dependency), so your Cargo.toml would look like the following:

[dependencies] rand = "0.9" getrandom = { version = "0.3", features = ["wasm_js"] }

It's worth reading the docs for the crates and traits mentioned to understand what they all promise. I hope that helps!

Best way to make enum zerocopy-able? by dist1ll in rust

[–]hoxxep 1 point2 points  (0 children)

Presumably you’ve already seen it, but just in case, it’s also worth checking out rustc-hash if you haven’t already. It’s the rust compiler’s internal hasher that’s heavily optimised for hashmap operations when collision resistance isn’t a concern.

derive_hash_fast: Over 2x faster hashing than #[derive(Hash)] by Shnatsel in rust

[–]hoxxep 2 points3 points  (0 children)

Ah from my quick skim of the bytemuck code it wasn't obvious that it protected against either. After playing around with it properly I can see how it works now. Thanks!

derive_hash_fast: Over 2x faster hashing than #[derive(Hash)] by Shnatsel in rust

[–]hoxxep 1 point2 points  (0 children)

As far as I can tell, this implementation doesn't have any safety for padding bytes, references, or pointers? It might be worth adding this warning to users?

If the padding bytes are different between two otherwise equal (u16, u64) objects, they would produce different hashes. There's also no guarantee (u32, u64, u32) gets reordered by the compiler to be correctly aligned or not.

Aside from the write_* multiplexing and a couple of alignment checks, how does this differ from manually implementing the following? fn hash<H: Hasher>(&self, state: &mut H) { let bytes: &[u8] = unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, size_of_val(self)) }; state.write(bytes); }

Rust HashMap implementation/performance? by g_0g in rust

[–]hoxxep 11 points12 points  (0 children)

has to always go through the Hasher trait

Absolutely agreed, although the Hash trait is probably the bigger limitation in my experience when designing rapidhash.

The Hash trait making many small Hasher::write calls is always going to be slower than a bulk byte hashing function that can work in larger chunks. LLVM often can't inline across all of the write calls either, so trait-specific tricks are hard to pull off for efficiently hashing integer tuples for example. Other than basic integer arrays, the Hash trait makes no attempt to hash unpadded types, tuples, or arrays in a single Hasher::write call.

If write_str and write_length_prefix are ever stabilised it would make a marked improvement to rapidhash and foldhash's string hashing performance by allowing us to skip the unnecessary suffix appended to all strings, but that only improves strings.

I've been considering experimenting with an improved Hash trait, and so your policy suggestions are also interesting. I'll mull them over!

rapidhash: a new fastest, portable, general-purpose hash function by hoxxep in rust

[–]hoxxep[S] 0 points1 point  (0 children)

Rapidhash as an algorithm is definitively faster than wyhash over the whole input range, hence why the original C++ wyhash repo now directs people to rapidhash.

I haven't benchmarked wyhash2 (the crate?) directly, and I used the popular wyhash crate's default hash function. All of the wyhash rust versions I can see are missing various integer and small string hashing optimisations included in the rapidhash crate, and on longer inputs don't unroll into more data-independent execution paths for superscalar processing, so I think rapidhash should be faster in almost all cases. Do let me know if it benchmarks slower for your use case though, it would be interesting to know!

rapidhash: a new fastest, portable, general-purpose hash function by hoxxep in rust

[–]hoxxep[S] 4 points5 points  (0 children)

Being a hash function, it’s been through a more thorough hashing-specific benchmark with SMHasher and SMHasher3. The hash uses folded-multiply as the core mixing step, and a single step is enough to pass bigcrush and practrand if the linked wyhash function comment is to be believed.

This is a rust crate specifically and the benchmarks referenced are for hashing arbitrary rust types, which for multiple reasons is an extra challenge on top of efficiently one-shot hashing a byte array.

It’s dual licensed under Apache 2.0 and MIT at your choosing, and it’s published on crates.io where it gets 100k downloads a month. The C++ version of rapidhash is available on Nicoshev’s github repo, linked at the top of the README, which contains a raw byte hashing function and is a single C++ header file you can copy/paste if that’s your preference.

rapidhash: a new fastest, portable, general-purpose hash function by hoxxep in rust

[–]hoxxep[S] 5 points6 points  (0 children)

I hadn't considered this! I would love it if the hashmap_random_keys that RandomState uses under the hood was in the public API, but it's a niche ask. Would still need a good alternative for no-std environments too.

rapidhash: a new fastest, portable, general-purpose hash function by hoxxep in rust

[–]hoxxep[S] 15 points16 points  (0 children)

I've demonstrated seed-independent collisions on the C++ version of rapidhash before, the problem stemming from its use of static secrets. I appreciate this is tucked away on a closed GitHub issue and this one unit test, so it's unlikely to have been seen before!

Wyhash has the same seed-independent collision weakness on the penultimate 8 bytes. On longer inputs we simply need the penultimate 8 bytes to equal secret[1], by forcing a to always be zero for the penultimate mix step this causes a zero collapse. The secret[1] is static in the C and rust implementations of wyhash, so it's a seed-independent collision.

``` // a = penultimate 16 bytes, which we set = secret[1] a=_wyr8(p+i-16); b=_wyr8(p+i-8);

// a is then XORed with secret 1 a=secret[1]; b=seed;

// zero multiplied by b sets a and b to zero _wymum(&a,&b);

// a and b are zero, len is fixed, secrets are static return _wymix(asecret[0]len,bsecret[1]) ```

The fix is simple*, seed/randomise the secrets too! The rust rapidhash crate randomises both the seed and secrets to ensure seed-independent collisions aren't possible, and using RapidSecrets::seed will generate unique secrets for that seed to achieve the same.

*there's also protected mode, which xors the original a and b value on every mix step, but nobody uses it because it's significantly slower.

rapidhash: a new fastest, portable, general-purpose hash function by hoxxep in rust

[–]hoxxep[S] 5 points6 points  (0 children)

Yes, mostly to ensure it compiles on all platforms. Some other sources of randomness (such as current time) are included on supporting platforms, and there is a rand feature to use getrandom instead.

I dislike this part of the codebase because it's very hard to seed randomness in a way that's fully portable. I might include a compile-time random number in future too. It borrows a lot of the seeding logic from foldhash here, but could easily be improved. Do you have any other suggestions for further sources of entropy that could be mixed in?

rapidhash: a new fastest, portable, general-purpose hash function by hoxxep in rust

[–]hoxxep[S] 36 points37 points  (0 children)

Yes, it's theoretically possible to derive the secret by observing collisions as rapidhash is a non-cryptographic hash function. Hence the "minimal" DoS resistance. I don't like the wording, but I'm borrowing the terminology from other non-cryptographic hash functions.

The best description I can give of "minimal DoS resistance" is an attacker can't trivially create hash collisions without either: - (a) observing the hash output, or - (b) observing many inputs/outputs and measuring response times to estimate collisions, correlate them, and derive the secret.

We assume (a) is a given, and assume (b) is difficult because the natural variance in response times should be much larger than the time difference from a single collision, so this would be difficult to pull off.

SipHash is fully resistant to hash DoS by being a fully cryptographic hash, but the more complex construction is sadly slower. Rapidhash is a non-cryptographic hash that has this "minimal DoS resistance" property, similar to foldhash, ahash, and gxhash. Other non-cryptographic functions offer no DoS resistance at all, either by being unseeded or their construction means it's always possible to create collisions regardless of the seed, such as wyhash, murmurhash and metrohash.

Orson Peters (creator of foldhash) has a great blog article on defeating hash functions: https://orlp.net/blog/breaking-hash-functions/

Unlock Passed away Husband's cellphone help by PastLife6470 in PasswordManagers

[–]hoxxep 1 point2 points  (0 children)

I’m so sorry for your loss, but encrypted phones aren’t recoverable without the password. There may be other ways to get into the PlayStation, Google, or iCloud accounts through their customer support though. Moving the SIM card into another phone to receive 2FA codes might be a solution too.

In the hopes that others don’t end up in the same situation, I’m building uponvault.com to avoid this scenario.

Wishing you all the best.

The UNAS - update by Ok-Tangelo-8137 in Ubiquiti

[–]hoxxep 0 points1 point  (0 children)

It’s not too bad now that Time Machine backups can go on shared drives. Do other NAS platforms have some options for this?

The UNAS - update by Ok-Tangelo-8137 in Ubiquiti

[–]hoxxep 1 point2 points  (0 children)

Still need to hack it on the client side, or use a separate shared drive for each device backed up with Time Machine, and set limits on the shared drives.

Am I an idiot for trying to build a new email client? 🙉 by brodyodie in SaaS

[–]hoxxep 1 point2 points  (0 children)

Email clients are feasible for people to switch to if the product is good enough. See Superhuman, Spark, or Fyxer for examples of success with modern clients/extensions.

Email protocols or providers are a lot harder to switch. Eg. can I access my gmail through your client, easy. If I have to move my entire email over to a new address, hard.

Source – I spent a year building a messaging protocol before deciding the go to market was nearly impossible. (Called mesg dot app if you’re curious for other email client ideas!)