Skip to content

Salt a system hash

This operation (SaltHash) inserts each hex-encoded date part from _dateParts into the progressively growing hash string at a random position, recording each insertion in a location map prefixed to the result; the map is a fixed 42 characters wide only while each entry's unpadded body-length field renders as two digits (BR-HU-01). In-repo, SystemHashService.ComputeHash calls this immediately after constructing a salting SaltShaker (OP-HU-01).

Field Value
Operation ID OP-HU-03
Trigger Called after OP-HU-01 (in-repo: SystemHashService.ComputeHash)
Inputs systemHash (in-repo, a 44-char Base64 SHA-256 string)
Outputs Salted hash string: a fixed 42-character location map (only while each entry's unpadded body-length field stays two digits) followed by the salted body, whose total string length varies with systemHash.Length plus the seven inserted date parts
Primary components SaltShaker.SaltHash(string systemHash)
Entry point src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

Steps

  1. Create an empty StringBuilder to accumulate the location map.
  2. For each entry of _dateParts, in enumeration order Minute, Year, Day, Millisecond, Second, Hour, Month (BR-HU-04, BR-HU-06):
  3. Pick a random insertion index in [0, currentLength) of the string as it currently stands, after any prior insertions in this loop (BR-HU-05).
  4. Pick a random filler pad character in the range 'A'–'Y' (BR-HU-07).
  5. Insert the hex-encoded date part at the chosen index.
  6. Append the insertion index (zero-padded to 3 digits), the pad character, and the new total body length (an unpadded decimal number, two digits for the observed/assumed input shape) to the map (BR-HU-01).
  7. On failure: if the instance was built with the parameterless constructor (OP-HU-02), this step throws an unguarded NullReferenceException because _dateParts is null (BR-HU-04).
  8. Return the concatenation of the location map and the fully salted systemHash body — the map is 42 characters wide only when every body-length field rendered as two digits (bodies of 10–99 characters after each insertion); the total returned string length is otherwise variable, and unsupported body lengths may still be returned without a round-trip guarantee (BR-HU-01).
  9. On failure: if systemHash is null, this operation throws an unguarded NullReferenceException; if systemHash is empty, Random.Next(0,0) returns 0 and insertion proceeds without error.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([Called after OP-HU-01]) --> S1[Create empty map StringBuilder]
    S1 --> Loop{For each date part in<br>Minute..Month order}
    Loop -->|next part| S2[Pick random insertion index]
    S2 --> S3["Pick random pad char 'A'-'Y'"]
    S3 --> S4[Insert hex-encoded part at index]
    S4 --> S5["Append index + pad + body length to map"]
    S5 --> Loop
    Loop -->|all parts done| S6["Return map + salted systemHash"]
    S6 --> EndOk([Salted hash string returned])
    S2 -->|_dateParts null| EndErr([NullReferenceException])

Failure and edge-case behavior

  • Parameterless-constructed instance (OP-HU-02): NullReferenceException iterating _dateParts.
  • null systemHash: NullReferenceException reading systemHash.Length.
  • Empty systemHash: proceeds without error; Random.Next(0,0) returns 0.
  • No validation exists for the post-insertion body length staying within the 2-digit (10–99 character) range assumed by the fixed-width map (BR-HU-01).

Sources

  • src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs
  • src/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SystemHashService.cs