Skip to content

SAIF.NetCore.HashUtil business rules

This page captures business rules enforced by this library.

BR-HU-01 Fixed 42-character location map prefix

Field Value
Statement A salted hash is prefixed with a location map composed of seven 6-character entries (3-digit zero-padded index + pad char + unpadded decimal body length), one per embedded date part. The map is a fixed 42 characters wide only when each entry's body-length field happens to render as two digits (total salted string length between 10 and 99 characters at that insertion step); SaltHash appends systemHash.Length with no padding or width validation.
Trigger SaltHash / BlandHash
Enforcement SaltShaker.MAP_LENGTH (= 42); SaltShaker.SaltHash; SaltShaker.BlandHash
Outcome BlandHash always reads exactly 42 characters as the map, so any entry whose body-length field is not two digits shifts every following map entry and corrupts or breaks decoding; SaltHash does not enforce or validate that the salted length stays in the 10–99 range before emitting output.
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-02 Fixed hex-encoded date-part lengths

Field Value
Statement Each date part is embedded as lowercase 2-digit hex per character, with fixed encoded lengths: Year 8, Millisecond 6, Minute/Day/Second/Hour/Month 4.
Trigger Construction with a create date; BlandHash decode
Enforcement SaltShaker._datePartLength; SaltShaker.EncodePart; SaltShaker.DecodePart
Outcome Encoded parts round-trip to the original formatted digits.
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-03 Millisecond-precision, 24-hour, culture-sensitive timestamp

Field Value
Statement The embedded timestamp has millisecond precision and uses 24-hour hours; it is captured with culture-sensitive DateTime.ToString and reconstructed with culture-sensitive Convert.ToDateTime("yyyy/MM/dd HH:mm:ss.fff"). No time-zone/DateTimeKind information is embedded.*
Trigger SaltShaker(DateTime); BlandHash
Enforcement SaltShaker..ctor(DateTime); SaltShaker.BlandHash
Outcome The recovered DateTime equals the create date to the millisecond under a culture whose date/time parsing accepts this layout; the recovered DateTimeKind is unspecified/local.*
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-04 Constructor split between salting and de-salting

Field Value
Statement Only a SaltShaker constructed with a create date can salt; a parameterless instance can only de-salt.
Trigger Calling SaltHash on a parameterless instance
Enforcement SaltShaker() leaves _dateParts null; SaltShaker.SaltHash iterates _dateParts without a null guard
Outcome Calling SaltHash on a parameterless instance throws an unguarded NullReferenceException.
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-05 Random insertion position per part

Field Value
Statement Each date part is inserted at a uniformly random index in [0, currentLength) of the progressively salted string, so placement is randomized rather than fixed across calls.
Trigger Each loop iteration in SaltHash
Enforcement SaltShaker.SaltHash using System.Random
Outcome Output is randomized and typically differs between salts of the same hash and date, but Random.Next can produce the same index or pad character on different calls — the source performs no duplicate-detection or uniqueness check, so distinct output is not guaranteed.
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-06 Insertion and removal order

Field Value
Statement Parts are inserted in order Minute→Year→Day→Millisecond→Second→Hour→Month and removed in exact reverse order using the reversed map, so every recorded index is valid at removal time.
Trigger SaltHash, BlandHash
Enforcement SaltShaker._dateParts population order; SaltShaker._datePartLength order; SaltShaker.BlandHash reversal and SplitAndReverse
Outcome Lossless recovery of the original hash. Relies on Dictionary enumeration order remaining stable.*
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-07 Random pad character, ignored on decode

Field Value
Statement Each map entry carries one random filler character in the range 'A'–'Y' that has no meaning on decode.
Trigger SaltHash
Enforcement SaltShaker.SaltHash — Random.Next(65, 90) (exclusive upper bound, so 'Z' is never produced)
Outcome Obfuscates the map; ignored by BlandHash, which reads only the first 3 characters of each entry.
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-08 Map stripped by full-string replace

Field Value
Statement The map is stripped from the salted hash by removing all occurrences of the 42-character map string, not only the prefix.
Trigger BlandHash
Enforcement SaltShaker.BlandHash — string.Replace(map, string.Empty)
Outcome Correct when the map appears only as the prefix (practically always); would corrupt the body if the 42-character sequence recurred elsewhere in the body.*
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SaltShaker.cs

BR-HU-09 Fixed-format expiry message

Field Value
Statement An expired system hash is reported with a fixed message containing the hash's embedded date and the evaluation date, both formatted MM/dd/yyyy hh:mm:ss.ffffff.
Trigger Consumer constructs and throws the exception
Enforcement SystemHashExpiredException..ctor
Outcome The exception message is fixed as described; the 12-hour clock without an AM/PM designator makes the times ambiguous. The decision to throw is made entirely by SAIF.NetCore.SystemHash (SystemHashService.RemoveSystemHashSaltAndValidateLifetime), not by this library.
Source src/SAIF.NetCore.HashUtil/SAIF.NetCore.HashUtil/SystemHashExpiredException.cs

Notes

  • No rule on this page is enforced by an inherited base class or service from a dependency package — HashUtil has no package dependencies.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

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