---
title: SAIF.NetCore.HashUtil operations and processes
summary: Business and technical operations supported by this library.
status: draft
owner: SAIF Platform Team
last_reviewed: 2026-10-02
library: SAIF.NetCore.HashUtil
reference_type: package
---

# SAIF.NetCore.HashUtil operations and processes

This page is the operation catalog and cross-operation hub for this library. Each operation's detailed, step-by-step logic lives in its own page under `operations/`.

## Operation catalog
| Operation | Intent | Trigger | Inputs | Outputs | Rules |
| --- | --- | --- | --- | --- | --- |
| [Construct a salting SaltShaker](operations/op-hu-01-construct-salting-saltshaker.md) | Build a `SaltShaker` instance that can salt a hash | Caller needs to salt a hash | `createDate` (`DateTime`) | Instance with populated `_dateParts` | [BR-HU-02](business-rules.md#br-hu-02-fixed-hex-encoded-date-part-lengths), [BR-HU-03](business-rules.md#br-hu-03-millisecond-precision%2C-24-hour%2C-culture-sensitive-timestamp) |
| [Construct a de-salting SaltShaker](operations/op-hu-02-construct-desalting-saltshaker.md) | Build a `SaltShaker` instance that can de-salt a hash | Caller needs to de-salt a hash | none | Instance with `_dateParts` left `null` | [BR-HU-04](business-rules.md#br-hu-04-constructor-split-between-salting-and-de-salting) |
| [Salt a system hash](operations/op-hu-03-salt-a-system-hash.md) | Embed a create date into a hash string at random positions | Called after constructing a salting `SaltShaker` | `systemHash` (string) | Salted hash string: a location map that is 42 characters wide only when every post-insertion body-length field renders as exactly two digits (each insertion keeps the body between 10 and 99 characters), followed by the salted body, whose total length varies with `systemHash.Length`; inputs outside that range may still produce a returned string, but without a guaranteed-width location map or a supported round trip | [BR-HU-01](business-rules.md#br-hu-01-fixed-42-character-location-map-prefix), [BR-HU-04](business-rules.md#br-hu-04-constructor-split-between-salting-and-de-salting), [BR-HU-05](business-rules.md#br-hu-05-random-insertion-position-per-part), [BR-HU-06](business-rules.md#br-hu-06-insertion-and-removal-order), [BR-HU-07](business-rules.md#br-hu-07-random-pad-character%2C-ignored-on-decode) |
| [De-salt a system hash and recover the embedded date](operations/op-hu-04-de-salt-a-system-hash.md) | Remove the location map, recover the embedded create date, and return the original hash | Called after constructing a de-salting `SaltShaker` | `saltyHash` produced by salting | Original hash (return value); embedded create date (`out expireDate`) | [BR-HU-01](business-rules.md#br-hu-01-fixed-42-character-location-map-prefix), [BR-HU-02](business-rules.md#br-hu-02-fixed-hex-encoded-date-part-lengths), [BR-HU-03](business-rules.md#br-hu-03-millisecond-precision%2C-24-hour%2C-culture-sensitive-timestamp), [BR-HU-06](business-rules.md#br-hu-06-insertion-and-removal-order), [BR-HU-07](business-rules.md#br-hu-07-random-pad-character%2C-ignored-on-decode), [BR-HU-08](business-rules.md#br-hu-08-map-stripped-by-full-string-replace) |
| [Signal an expired system hash](operations/op-hu-05-signal-expired-system-hash.md) | Construct the exception a consumer throws once it decides a recovered date has expired | Consumer decides a hash has expired | `nowDate`, `hashDate` | `SystemHashExpiredException` with a fixed-format message | [BR-HU-09](business-rules.md#br-hu-09-fixed-format-expiry-message) |

## Process flow diagram
The following diagram visualizes the primary salt/de-salt round trip across operations.

```mermaid
flowchart TD
	Start([Caller needs a salted hash]) --> OP1["OP-HU-01: Construct salting SaltShaker"]
	OP1 --> OP3["OP-HU-03: Salt a system hash"]
	OP3 --> Stored([Salted hash returned to caller])

	Stored --> OP2["OP-HU-02: Construct de-salting SaltShaker"]
	OP2 --> OP4["OP-HU-04: De-salt a system hash"]
	OP4 --> Decision{Consumer evaluates<br>recovered create date}
	Decision -->|Still valid| EndOk([Original hash returned to caller])
	Decision -->|Expired| OP5["OP-HU-05: Signal expired system hash"]
	OP5 --> EndErr([SystemHashExpiredException thrown by consumer])
```

## Failure and edge-case behavior
- A `SaltShaker` built with the parameterless constructor (OP-HU-02) has a `null` `_dateParts`; calling `SaltHash` on it throws an unguarded `NullReferenceException` ([BR-HU-04](business-rules.md#br-hu-04-constructor-split-between-salting-and-de-salting)).
- `BlandHash` performs no lifetime check of its own and never throws `SystemHashExpiredException` — the expiry decision and throw belong entirely to the calling consumer (OP-HU-05).
- A `saltyHash` shorter than 42 characters, a malformed map, an out-of-range insertion index, or an unparseable date string under the current culture each surface as an unguarded BCL exception (`ArgumentOutOfRangeException` or `FormatException`) rather than a library-specific error.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)

## Sources
- `src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs`
- `src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SystemHashExpiredException.cs`
- `src/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SystemHashService.cs`
