---
title: Get the current application's system hash
summary: Resolve the calling application's own identity and issue a credential for it.
status: draft
owner: SAIF Platform Team
last_reviewed: 2026-10-02
library: SAIF.NetCore.SystemHash
reference_type: package
operation_id: OP-SH-03
trigger: An application or library needs its own identity credential, e.g. to attach to a secure-setting request.
---

# Get the current application's system hash

Resolves the current application's assembly name and issues a salted credential for it, without the caller having to supply a system name explicitly.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-SH-03 |
| **Trigger** | Direct call by application startup code or a consuming library. |
| **Inputs** | `type` (`SystemType`) |
| **Outputs** | Salted hash for `"{assemblyName}-{(int)type}"` |
| **Primary components** | `SystemHashService.Get` |
| **Entry point** | `src/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SystemHashService.cs` |

## Steps

1. Resolve the identity assembly ([BR-SH-06](../business-rules.md#br-sh-06-system-name-from-assembly)):
   - If the stored constructor-supplied assembly is non-null (`_assembly != null`), use it.
   - Otherwise, use `Assembly.GetCallingAssembly()` as evaluated inside `GetAssembly`. Because `GetAssembly` is called from within `Get`, the "calling assembly" at that point is `Get`'s own containing assembly (`SAIF.NetCore.SystemHash`), not the application that originally called `Get` — unless JIT inlining collapses the call stack.*

   See [Resolve the identity assembly](resolve-identity-assembly.md) for the full step-by-step detail of this delegation.

   > **Origin**: Step 1 is implemented in [Resolve the identity assembly](resolve-identity-assembly.md) and executed on behalf of this operation.
2. Read the resolved assembly's simple name as `systemName`.
3. Compute a salted credential for `type` and `systemName` ([BR-SH-01](../business-rules.md#br-sh-01-identity-hash-encoding)–[BR-SH-04](../business-rules.md#br-sh-04-credential-randomized-per-call)):
   - Compute the deterministic identity hash: build `"{systemName}-{(int)type}"` (using the `SystemType` ordinal), encode as UTF-16LE, SHA-256, Base64-encode.
   - Construct a salting `SaltShaker` pre-populated with the hex-encoded parts of the current host-local time (`DateTime.Now`, millisecond precision): create the `_dateParts` dictionary and, for each date part, format the create date with the current culture and hex-encode it, inserting entries in this order: Minute (`"mm"`), Year (`"yyyy"`), Day (`"dd"`), Millisecond (`"fff"`), Second (`"ss"`), Hour (`"HH"`, 24-hour), Month (`"MM"`).
   - Salt the identity hash by inserting the hex-encoded date parts at pseudo-random positions within the hash string: for each date part, in order Minute, Year, Day, Millisecond, Second, Hour, Month, pick a random insertion index in `[0, currentLength)` using the `SaltShaker`'s own `Random` instance, pick a random pad character in `'A'`–`'Y'`, insert the hex-encoded part at the chosen index, and append the zero-padded index, the pad character, and the new body length to a 42-character location map.
   - Return the concatenation of the 42-character location map and the fully salted hash body.

   See [Compute a salted system hash](compute-salted-system-hash.md) for the full step-by-step detail of this delegation.

   > **Origin**: Step 3 is implemented in [Compute a salted system hash](compute-salted-system-hash.md) and executed on behalf of this operation.
4. Return the salted credential.
   - Contrary to the method's own XML documentation (which states the value is computed once and reused), no field caches the result — every call recomputes and re-salts ([BR-SH-07](../business-rules.md#br-sh-07-credential-is-not-cached)).

## Process flow

The following diagram shows the credential-issuance path for the calling application's own identity, delegating assembly resolution and salted-hash computation; it issues a credential and performs no lifetime checking or external identity comparison.

```mermaid
flowchart TD
	Start([Caller requests its own credential]) --> ResolveAssembly[Resolve identity assembly]
	ResolveAssembly --> ComputeSalted[Compute salted system hash for assembly name]
	ComputeSalted --> Return(["Return salted credential — recomputed every call"])
```

## Failure and edge-case behavior
- Because `Get` calls `GetAssembly` internally rather than passing its own calling assembly down, `Assembly.GetCallingAssembly()` inside `GetAssembly` most likely resolves to the `SAIF.NetCore.SystemHash` assembly itself rather than the true calling application, unless the JIT inlines the call or an assembly was injected via the constructor ([BR-SH-06](../business-rules.md#br-sh-06-system-name-from-assembly)).*
- No caching occurs despite the documented intent, so repeated calls are more expensive than the XML comment implies ([BR-SH-07](../business-rules.md#br-sh-07-credential-is-not-cached)).

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

> **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.SystemHash/SAIF.NetCore.SystemHash/SAIF.NetCore.SystemHash/SystemHashService.cs`
