{"id":30715961,"url":"https://github.com/usercrixus/42ftssl","last_synced_at":"2025-09-03T07:12:07.270Z","repository":{"id":311321052,"uuid":"992661300","full_name":"usercrixus/42ftssl","owner":"usercrixus","description":"A minimal reimplementation of the classic openssl message digest utility. It supports MD5 and SHA256 hashing, with flag handling (-p, -q, -r, -s) and routing logic for stdin, string literals, and files.","archived":false,"fork":false,"pushed_at":"2025-08-23T04:15:06.000Z","size":1372,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-24T06:45:23.869Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/usercrixus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-29T14:10:08.000Z","updated_at":"2025-08-23T04:15:09.000Z","dependencies_parsed_at":"2025-08-24T07:46:17.257Z","dependency_job_id":"f43ef078-2c21-4df3-af06-beeaedf84da8","html_url":"https://github.com/usercrixus/42ftssl","commit_stats":null,"previous_names":["usercrixus/42ftssl"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/usercrixus/42ftssl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercrixus%2F42ftssl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercrixus%2F42ftssl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercrixus%2F42ftssl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercrixus%2F42ftssl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/usercrixus","download_url":"https://codeload.github.com/usercrixus/42ftssl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercrixus%2F42ftssl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273404889,"owners_count":25099492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-03T07:12:06.067Z","updated_at":"2025-09-03T07:12:07.242Z","avatar_url":"https://github.com/usercrixus.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ft_ssl\n\nA minimal reimplementation of the classic `openssl` message digest utility.  \nIt supports **MD5** and **SHA256** hashing, with flag handling (`-p`, `-q`, `-r`, `-s`) and routing logic for stdin, string literals, and files.  \nThe goal is to replicate the behavior of `openssl`/`md5sum` closely, including error handling and output formatting, while keeping the code clean and structured.\n\n\n# Build, Run \u0026 Test\n\n## Prereqs\n- POSIX shell + coreutils (`bash`, `dd`, `tr`, `grep -P`)\n- `valgrind` (for memcheck)\n- `openssl`, `md5sum`, `sha256sum` (used by the test script for cross-checks)\n- Git submodules enabled (for `42libft`)\n\n\u003e macOS note: `md5sum`/`sha256sum` aren’t standard on macOS. Install via Homebrew (`brew install coreutils`) and use `gmd5sum`/`gsha256sum`, or skip the lines in the script that call them.\n\n## Build\n```bash\n# from repo root\nmake            # builds ./ft_ssl (brings submodules + libft)\n```\n\nTargets:\n- `make` / `make all` – build `ft_ssl`\n- `make clean` – remove objects\n- `make fclean` – remove objects + binary\n- `make re` – full rebuild\n- `make test` – Full Test Suite\n\n## Quick Usage\n```bash\n# stdin\necho \"42 is nice\" | ./ft_ssl md5\necho \"42 is nice\" | ./ft_ssl sha256\n\n# flags\n./ft_ssl md5 -p\n./ft_ssl md5 -s \"foo\"\n./ft_ssl md5 -q file\n./ft_ssl md5 -r file\n\n./ft_ssl sha256 -p\n./ft_ssl sha256 -s \"foo\"\n./ft_ssl sha256 -q file\n./ft_ssl sha256 -r file\n```\n\n# ft_ssl – Flag \u0026 Routing Logic (MD5 / SHA256)\n\nThis part explains **how flags are interpreted**, **how inputs are routed** (stdin / `-s` / file), and **how errors are reported**. It intentionally focuses on **logic**, not implementation details.\n\nThe behavior below matches the provided test suite exactly.\n\n---\n\n## Commands\n\n- `ft_ssl md5 [FLAGS] [FILE] [EXTRA…]`\n- `ft_ssl sha256 [FLAGS] [FILE] [EXTRA…]`\n\nIf the first argument is neither `md5` nor `sha256`, an error is printed:\n```\nft_ssl: Error: '\u003ccmd\u003e' is an invalid command\n```\n\nIf the command is present but **no further arguments**:\n- If **stdin is piped**, hash **stdin** (labeled `(stdin)= ...`) and exit.\n- If **stdin is a TTY**, print usage error and exit.\n\n---\n\n## Supported flags\n\n- `-p` : Read **stdin** and print it **before**/with the digest.\n- `-q` : **Quiet** — print **only** the digest (flag formatting suppressed).\n- `-r` : **Reverse** formatting — for strings: `hash \"str\"`, for files: `hash filename`.\n- `-s \u003cstring\u003e` : Hash an explicit **string literal** (first one only).\n\n\u003e Notes  \n\u003e • `-s` consumes **one** following non-flag token as its value.  \n\u003e • Flags may be grouped (e.g., `-qrp`).  \n\u003e • Flags are **deduplicated** (repeating the same char has no extra effect).\n\n---\n\n## Input sources and routing\n\nThere are exactly **three** possible inputs to hash in a single run, processed in this order:\n\n1. **`-p` (stdin)** — if `-p` is set, stdin is read \u0026 printed/hashed **first**.\n2. **`-s \"\u003cstring\u003e\"`** — if `-s` is set **and** a value was captured, it’s hashed **second**.\n3. **`\u003cfile\u003e`** — if a file argument is present (first non-flag token after flags), it’s hashed **third**.\n\nAnything **after** the first file token becomes an **error** (see below).\n\n### Important routing rules\n\n- **`-p` and `-s` do not carry over to files.**  \n  When hashing a file, we drop `p` and `s` from the flag set (so file formatting is only affected by e.g. `-q`, `-r`).\n\n- **Piped stdin is ignored if a file is given**, **unless** you explicitly used `-p`.  \n  In other words, `echo hi | ft_ssl md5 file` hashes **only** `file`.\n\n- **Asymmetry (by design to match tests):**  \n  - For **MD5 only**: if you provided flags but **none produced output** (no `-p`, no valid `-s`, no file) **and** stdin is piped, MD5 will still hash piped stdin as a final fallback.  \n  - For **SHA256**, this final fallback does **not** occur.\n\n---\n\n## Output formatting \u0026 precedence\n\nFormatting depends on **what** you’re hashing and the active flags. Precedence is:\n\n1. `-q` (quiet) **overrides** everything about labels and `-r`.  \n   You only get the hex digest (plus a newline).\n2. If **not** quiet:\n   - `-r` switches to reverse formatting:  \n     - string: `digest \"string\"`  \n     - file:   `digest filename`\n   - Else default formatting:  \n     - string: `ALGO (\"string\") = digest`  \n     - file:   `ALGO (filename) = digest`  \n     - stdin (no `-p`): `(stdin)= digest` (compat label)\n\n### `-p` printing\n\n- `-p` **prints stdin bytes exactly as received**, then prints the digest line.  \n- With `-q -p`, you still get the echoed stdin (exact bytes), then the bare digest.\n\n\u003e The exact newline behavior is tuned to match the tests; you can rely on the test suite as the source of truth for expected lines.\n\n---\n\n## How flags are parsed\n\n- Flags are taken from any leading `-\u003cgroup\u003e` tokens (e.g., `-p`, `-qr`, `-pqr`…), **deduplicated**, and combined.\n- When `-s` is seen for the **first time**, the next **non-flag** token (if any) becomes the **string value** and is consumed.\n- After the flag groups:\n  - The next **non-flag** token becomes the **file** (if any).\n  - **All remaining tokens** (including more `-s` groups or words) are treated as **errors**.\n\n---\n\n## Error handling\n\nAfter all hashing output is printed, any **leftover tokens** are reported as errors in the following form (one per line):\n\n```\nft_ssl: \u003calgo\u003e: \u003ctoken\u003e: No such file or directory\n```\n\nExample:\n```\nft_ssl: sha256: -s: No such file or directory\nft_ssl: sha256: bar: No such file or directory\n```\n\nThis ordering (outputs first, then errors) is deliberate and matches the tests.\n\n---\n\n## What exactly gets hashed?\n\n- **`-p`**: stdin content.  \n- **`-s \"\u003cstring\u003e\"`**: the captured string literal (without surrounding quotes).  \n- **`file`**: the file’s bytes.\n\n**Piped stdin is only hashed if:**\n- You used **`-p`**, or\n- You ran **only the command** with **no further args** while stdin is piped (special case at the top), or\n- **MD5 only**: the “final fallback” case described above.\n\n---\n\n## Quick examples (mirroring tests)\n\n- `echo \"42 is nice\" | ft_ssl md5`  \n  → hashes stdin, prints: `(stdin)= \u003cmd5\u003e`\n\n- `echo \"42 is nice\" | ft_ssl md5 -p`  \n  → prints the line, then the digest line for stdin.\n\n- `ft_ssl md5 -s \"foo\"`  \n  → `MD5 (\"foo\") = \u003cdigest\u003e`\n\n- `ft_ssl md5 -q -r file`  \n  → `\u003cdigest\u003e` (quiet beats reverse; file is hashed, no labels)\n\n- `echo \"x\" | ft_ssl sha256 file`  \n  → hashes **file** only (pipe ignored), prints `SHA256 (file) = \u003cdigest\u003e`\n\n- `echo \"x\" | ft_ssl sha256 -p -r file`  \n  → three lines: echoed stdin, its digest, then `\u003cdigest\u003e file`\n\n- `echo \"one more thing\" | ft_ssl sha256 -r -p -s \"foo\" file -s \"bar\"`  \n  → outputs (stdin, string \"foo\", file), then errors for `-s` and `bar`.\n\n---\n\n## Symmetry between MD5 and SHA256\n\n- **Flag parsing, ordering, file-flag pruning, quiet/reverse formatting, error printing** — all symmetric.\n- **One intentional difference** (test-driven):  \n  **MD5** performs a last-chance “piped stdin” hash when no other work was dispatched and stdin is piped; **SHA256** does not.\n\nIf you later decide you want *perfect* symmetry, remove that MD5-only fallback (or add it to SHA256), but note you’ll need to adjust tests accordingly.\n\n---\n\n## TL;DR flowchart\n\n1) Validate command (`md5`/`sha256`)  \n2) If no args after command:  \n   - piped stdin → hash stdin; else → usage error  \n3) Parse flags (`-p`, `-q`, `-r`, first `-s` value), capture **one** file, collect extras as **errors**  \n4) Dispatch in order:  \n   - `-p` (stdin) → output  \n   - `-s` (string) → output  \n   - `file` → output (with `p`/`s` dropped)  \n   - **MD5 only** final stdin fallback if nothing ran and stdin is piped  \n5) Print accumulated **errors** (one per line)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusercrixus%2F42ftssl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusercrixus%2F42ftssl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusercrixus%2F42ftssl/lists"}