De-salt a system hash and recover the embedded date¶
This operation (BlandHash) reads the 42-character location map off the front of a salted hash, walks it in reverse insertion order to remove and hex-decode each embedded date part, and reconstructs both the original (unsalted) hash and the create date that was embedded at salting time. In-repo, SystemHashService.RemoveSystemHashSaltAndValidateLifetime calls this immediately after constructing a de-salting SaltShaker (OP-HU-02).
| Field | Value |
|---|---|
| Operation ID | OP-HU-04 |
| Trigger | Called after OP-HU-02 (in-repo: SystemHashService.RemoveSystemHashSaltAndValidateLifetime) |
| Inputs | saltyHash produced by OP-HU-03 |
| Outputs | Return value: original (unsalted) hash; out expireDate: the create date embedded at salting time |
| Primary components | SaltShaker.BlandHash(string saltyHash, out DateTime expireDate) |
| Entry point | src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs |
Steps¶
- Take the first 42 characters of
saltyHashas the location map (BR-HU-01). - On failure: a
saltyHashshorter than 42 characters throws anArgumentOutOfRangeException. - Split the map into 6-character chunks and reverse their order, producing entries in Month → Minute order (BR-HU-01, BR-HU-06).
- Remove every occurrence of the map string from
saltyHash(BR-HU-08). - Enumerate the date-part lengths in reverse order (Month, Hour, Second, Millisecond, Day, Year, Minute), with a parallel index into the reversed map entries (BR-HU-06). For each part:
- Parse the insertion index from the first 3 characters of the map entry; the pad character and body-length digits are ignored.
- Read the appropriate number of characters (4, 6, or 8, depending on the part) at that index and hex-decode them (BR-HU-02).
- On failure: malformed hexadecimal digits in the salted body produce a
FormatException; an out-of-range insertion index produces anArgumentOutOfRangeException.
- On failure: malformed hexadecimal digits in the salted body produce a
- Remove those characters from the working string, undoing the insertion in LIFO order.
- Map the dictionary key back to the matching local variable (
minute,year,day,millisecond,second,hour,month). - Build the recovered
DateTimefrom the decoded parts (BR-HU-03). - On failure: an unparseable date string under the current culture produces a
FormatException. - Return the remaining string as the original (unsalted) hash.
Process flow¶
The following diagram visualizes this operation's control flow.
flowchart TD
Start([Called after OP-HU-02]) --> S1[Take first 42 chars as map]
S1 --> S2["Split map into 6-char chunks,<br>reverse to Month..Minute order"]
S2 --> S3[Remove map string from saltyHash]
S3 --> Loop{For each part in<br>Month..Minute order}
Loop -->|next part| S4[Parse insertion index from map entry]
S4 --> S5["Read + hex-decode date-part chars"]
S5 --> S6[Remove decoded chars from working string]
S6 --> Loop
Loop -->|all parts done| S7[Build recovered DateTime]
S7 --> S8[Return remaining string as original hash]
S8 --> EndOk(["Original hash + create date returned"])
S1 -->|saltyHash < 42 chars| EndErr([ArgumentOutOfRangeException])
Failure and edge-case behavior¶
saltyHashshorter than 42 characters:ArgumentOutOfRangeExceptionat step 1.- Malformed decimal digits in the location map (step 4.1 index parse):
FormatException. - Malformed hexadecimal digits in the salted body (step 4.2 date-part decode):
FormatException. - Out-of-range insertion index used as a substring/removal bound:
ArgumentOutOfRangeExceptionat steps 4.2–4.3 (step 4.1 only converts the fixed three-character decimal field and does not itself use the parsed value as an index). - Unparseable date string under the current culture:
FormatExceptionat step 5. nullinput:NullReferenceException.- This operation performs no lifetime check of its own and never throws
SystemHashExpiredException; that decision belongs entirely to the calling consumer (see Signal an expired system hash).
Related documentation¶
Sources¶
src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cssrc/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SystemHashService.cs