---
title: Validate system hash lifetime
summary: Remove hash salt and reject expired system hashes.
status: draft
owner: SAIF Framework
last_reviewed: 2026-07-30
library: SAIF.Framework.Security.EnvironmentApi
reference_type: package
operation_id: OP-ENV-012
trigger: Caller validates a previously issued system hash
---

# Validate system hash lifetime

This operation reverses the `SaltShaker` wrapper around a previously issued system hash, recovers its embedded creation timestamp, and applies the library's buffered expiry test before handing back the unsalted hash value. It is the counterpart to [Generate a system hash](generate-system-hash.md) and is what prevents a stale hash from being reused indefinitely.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-ENV-012 |
| **Trigger** | Caller validates an existing system hash |
| **Inputs** | `systemHashValue`, `expireSeconds`, `nowBufferSeconds` |
| **Outputs** | Unsalted hash string or `SystemHashExpiredException` |
| **Primary components** | `SystemHashUtil.RemoveSystemHashSaltAndValidateLifetime` |
| **Entry point** | `SAIF.Framework.Security.EnvironmentApi\Services.Common\SystemHashUtil.cs` |

## Steps

1. Create a default `SaltShaker` instance and call `BlandHash(systemHashValue, out createDate)` so the original hash value and its embedded creation timestamp are both recovered from the salted wrapper.
2. Compute `now = DateTime.Now` and `expires = createDate.AddSeconds(expireSeconds)`.
3. Apply the method's buffered lifetime rule: the recovered creation timestamp must fall inside the valid window once `nowBufferSeconds` has been applied to the current time, accounting for reasonable clock drift between caller and issuer.
4. If the buffered window test fails, throw `SystemHashExpiredException(now, createDate)` so an expired hash can never be reused for a secure-setting request ([BR-008](../business-rules.md#br-008-system-hash-must-not-be-expired)).
5. If the buffered window test passes, return the unsalted hash string to the caller.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Caller validates system hash]) --> Unwrap[Remove salt and recover createDate]
	Unwrap --> Window[Compute expiry window]
	Window --> Valid{Within buffered lifetime?}
	Valid -->|No| Expired([Throw SystemHashExpiredException])
	Valid -->|Yes| ReturnHash([Return unsalted hash])
```

## Failure and edge-case behavior

- Validation applies the method's exact buffered-window expression rather than a naive `createDate <= now < expires` check, so callers should not assume a simple inequality reproduces this behavior.
- Invalid or expired hashes surface through the external `SystemHashExpiredException` type rather than a generic exception.
- Salt removal and timestamp recovery are implemented entirely by the external `SAIF.HashUtil` package; this operation supplies only the expiry-window evaluation around that recovered timestamp.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Dependencies](../dependencies.md)

## Sources
- SAIF.Framework.Security.EnvironmentApi\Services.Common\SystemHashUtil.cs
