# Module: Azaion.Services.Security ## Purpose Static utility class providing cryptographic operations: password hashing, encryption key derivation, and AES-CBC stream encryption/decryption. > **Cycle 1 (2026-05-13) note** — `GetHWHash` was deleted and `GetApiEncryptionKey` was simplified from `(email, password, hardwareHash)` to `(email, password)` by AZ-197 (admin-side hardware-binding cleanup). The hardware-hash component of the derived key is gone; existing ciphertexts produced under the old derivation are no longer re-derivable from the new signature. See `_docs/03_implementation/batch_06_report.md`. ## Public Interface | Method | Signature | Description | |--------|-----------|-------------| | `ToHash` | `static string ToHash(this string str)` | Extension: SHA-384 hash of input, returned as Base64 | | `GetApiEncryptionKey` | `static string GetApiEncryptionKey(string email, string password)` | Derives the per-user AES encryption key string from email + password (+ static salt) | | `EncryptTo` | `static async Task EncryptTo(this Stream inputStream, Stream toStream, string key, CancellationToken ct)` | AES-256-CBC encrypts a stream; prepends IV to output | | `DecryptTo` | `static async Task DecryptTo(this Stream encryptedStream, Stream toStream, string key, CancellationToken ct)` | Reads IV prefix, then AES-256-CBC decrypts stream | ## Internal Logic - **Password hashing**: `ToHash` uses SHA-384 with UTF-8 encoding, outputting Base64. - **Encryption key derivation**: `GetApiEncryptionKey` concatenates email and password with the static salt `"-#%@AzaionKey@%#---"`, then hashes via `ToHash` (SHA-384, Base64). - **Encryption**: AES-256-CBC with PKCS7 padding. Key is SHA-256 of the derived key string. IV is randomly generated and prepended to the output stream. Uses 512 KB buffer for streaming. - **Decryption**: Reads the first 16 bytes as IV, then AES-256-CBC decrypts with PKCS7 padding. ## Dependencies - `System.Security.Cryptography` (Aes, SHA256, SHA384) - `System.Text.Encoding` ## Consumers - `Program.cs` `/resources/get/{dataFolder}` endpoint — calls `GetApiEncryptionKey(user.Email, request.Password)` - `ResourcesService.GetEncryptedResource` — uses `EncryptTo` extension - `Azaion.Test/SecurityTest` — directly tests `EncryptTo` / `DecryptTo` round-trips (no longer tests hardware-hash derivation) ## Data Models None. ## Configuration - `BUFFER_SIZE = 524288` (512 KB) — hardcoded streaming buffer size ## External Integrations None. ## Security Core cryptographic module. Key observations: - Passwords are hashed with SHA-384 (no per-user salt, no key stretching — not bcrypt/scrypt/argon2). This is unchanged by AZ-197. - AES encryption uses SHA-256 of the derived key, with random IV per encryption. - All salts/prefixes are hardcoded constants. - Per AZ-197: device hardware fingerprints no longer participate in key derivation. The threat that hardware binding mitigated (credential reuse via desktop installers) was eliminated by the architectural shift to fTPM-secured Jetsons + browser-only SaaS access. ## Tests - `Azaion.Test/SecurityTest.EncryptDecryptTest` — round-trip encrypt/decrypt of a string - `Azaion.Test/SecurityTest.EncryptDecryptLargeFileTest` — round-trip encrypt/decrypt of a ~400 MB generated file