{"id":26053328,"url":"https://github.com/bee-san/ciphey","last_synced_at":"2026-10-18T21:08:04.833Z","repository":{"id":37309914,"uuid":"197261780","full_name":"bee-san/Ciphey","owner":"bee-san","description":"⚡ Automatically decrypt encryptions without knowing the key or cipher, decode encodings, and crack hashes ⚡","archived":false,"fork":false,"pushed_at":"2026-10-13T08:33:18.000Z","size":77727,"stargazers_count":21686,"open_issues_count":66,"forks_count":1445,"subscribers_count":224,"default_branch":"master","last_synced_at":"2026-10-18T11:27:30.511Z","etag":null,"topics":["artificial-intelligence","cipher","cpp","cryptography","ctf","ctf-tools","cyberchef-magic","decryption","deep-neural-network","encodings","encryptions","hacking","hacktoberfest","hashes","natural-language-processing","pentesting","python"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bee-san.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null},"funding":{"github":"bee-san","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2019-07-16T20:20:39.000Z","updated_at":"2026-10-18T11:20:22.000Z","dependencies_parsed_at":"2026-09-24T02:59:38.476Z","dependency_job_id":"3011cdcb-a17d-402c-a5f4-c822a941a233","html_url":"https://github.com/bee-san/Ciphey","commit_stats":{"total_commits":1403,"total_committers":51,"mean_commits":27.50980392156863,"dds":0.5958660014255168,"last_synced_commit":"de74875ac9e71b0df84bfcd1233a292c80d9b18f"},"previous_names":["brandonskerritt/ciphey","bee-san/ciphey","ciphey/ciphey"],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/bee-san/Ciphey","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bee-san%2FCiphey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bee-san%2FCiphey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bee-san%2FCiphey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bee-san%2FCiphey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bee-san","download_url":"https://codeload.github.com/bee-san/Ciphey/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bee-san%2FCiphey/sbom","scorecard":{"id":1246928,"data":{"date":"2026-04-27T05:42:20Z","repo":{"name":"github.com/bee-san/Ciphey","commit":"7298d60d0414b17efff5768d12ab2d323dd5b3ef"},"scorecard":{"version":"v5.3.0","commit":"c22063e786c11f9dd714d777a687ff7c4599b600"},"score":6.5,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/3 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#maintained"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dependency-update-tool"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dangerous-workflow"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#security-policy"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: topLevel 'contents' permission set to 'read': .github/workflows/codespell.yml:7","Warn: topLevel 'contents' permission set to 'write': .github/workflows/dependabot-auto-merge.yml:5","Info: topLevel 'contents' permission set to 'read': .github/workflows/dependency-review.yml:7","Warn: no topLevel permission defined: .github/workflows/quickstart.yml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release-builds.yml:8","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release.yml:21","Info: topLevel permissions set to 'read-all': .github/workflows/scorecards.yml:9","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codespell.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/codespell.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codespell.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/codespell.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/quickstart.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/quickstart.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/quickstart.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:72: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/quickstart.yml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/quickstart.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-builds.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-builds.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-builds.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-builds.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-builds.yml:69: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-builds.yml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-builds.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-builds.yml:110: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release-builds.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:109: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:141: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:153: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:154: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:158: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/stalePRS.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/bee-san/Ciphey/stalePRS.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating rust:alpine to rust:alpine@sha256:606fd313a0f49743ee2a7bd49a0914bab7deedb12791f3a846a34a4711db7ed2","Warn: containerImage not pinned by hash: Dockerfile:12: pin your Docker image by updating alpine:3.12 to alpine:3.12@sha256:c75ac27b49326926b803b9ed43bf088bc220d22556de1bc5f72d742c91398f69","Warn: pipCommand not pinned by hash: .github/workflows/codespell.yml:25","Warn: downloadThenRun not pinned by hash: .github/workflows/release.yml:61","Info:   5 out of  21 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of  12 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#pinned-dependencies"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: RUSTSEC-2021-0139","Warn: Project is vulnerable to: RUSTSEC-2025-0119","Warn: Project is vulnerable to: RUSTSEC-2024-0436","Warn: Project is vulnerable to: RUSTSEC-2025-0134"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: all commits (30) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#sast"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#fuzzing"}},{"name":"CI-Tests","score":10,"reason":"14 out of 14 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#ci-tests"}},{"name":"Contributors","score":10,"reason":"project has 23 contributing companies or organizations","details":["Info: found contributions from: BlockscapeNetwork, C-Omega, Ciphey, HashPals, ITISMeucciWeb, LivHackSoc, RevisionHub, RustScan, StegKraken, Tommaso-Melacarne-compiti-scuola, anthropics, bluerange-io, canonical, catchwise, exgen-code, feldera, imgbot, krpc-rs, mend, mway-io, mway-io @relution-io @bluerange-io, n/a, relution-io"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#contributors"}}]},"last_synced_at":"2026-05-04T05:26:30.692Z","repository_id":37309914,"created_at":"2026-05-04T05:26:30.692Z","updated_at":"2026-05-04T05:26:30.692Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38338287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-18T02:00:06.448Z","response_time":63,"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":["artificial-intelligence","cipher","cpp","cryptography","ctf","ctf-tools","cyberchef-magic","decryption","deep-neural-network","encodings","encryptions","hacking","hacktoberfest","hashes","natural-language-processing","pentesting","python"],"created_at":"2025-03-08T07:28:00.215Z","updated_at":"2026-10-18T21:08:04.827Z","avatar_url":"https://github.com/bee-san.png","language":"Rust","funding_links":["https://github.com/sponsors/bee-san"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/ciphey-tui-promo.mp4\"\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/preview.gif\" alt=\"Ciphey in a terminal: four layers of Base64 go in, Ciphey asks whether 'Ciphey peels back every layer of encoding' is the plaintext, then prints it with the path Base64 → Base64 → Base64 → Base64. Click to watch the one-minute tour.\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eCiphey\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003ePaste in text that's been encoded or encrypted. Ciphey works out how and hands you the plaintext.\u003c/b\u003e\u003cbr\u003e\n  No key, no cipher name, no hints. Base64, hex, Caesar/ROT13, Vigenère, Morse code and 19 more, several layers deep.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://crates.io/crates/ciphey\"\u003e\u003cimg alt=\"crates.io\" src=\"https://img.shields.io/crates/v/ciphey\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://docs.rs/ciphey\"\u003e\u003cimg alt=\"docs.rs\" src=\"https://img.shields.io/docsrs/ciphey\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"MIT license\" src=\"https://img.shields.io/badge/license-MIT-blue\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#install\"\u003eInstall\u003c/a\u003e ·\n  \u003ca href=\"#quick-start\"\u003eQuick start\u003c/a\u003e ·\n  \u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e ·\n  \u003ca href=\"#use-it-as-a-library\"\u003eLibrary\u003c/a\u003e ·\n  \u003ca href=\"#mcp-server-ai-assistants\"\u003eMCP\u003c/a\u003e ·\n  \u003ca href=\"#documentation\"\u003eDocs\u003c/a\u003e ·\n  \u003ca href=\"http://discord.skerritt.blog\"\u003eDiscord\u003c/a\u003e\n  \u003cbr\u003e\u003csub\u003e▶ \u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/ciphey-tui-promo.mp4\"\u003eWatch the one-minute tour\u003c/a\u003e (MP4, 61 s)\u003c/sub\u003e\n\u003c/p\u003e\n\n## Install\n\n```bash\ncargo install ciphey\n```\n\nPrebuilt binaries for Linux (x86_64), macOS (Intel and Apple silicon) and Windows (x86_64) are on the [releases page](https://github.com/bee-san/Ciphey/releases/latest), each with a `.sha256` checksum.\n\nTo build from source, you need a Rust toolchain:\n\n```bash\ngit clone https://github.com/bee-san/Ciphey\ncd Ciphey\ncargo build --release    # the binary is target/release/ciphey\n```\n\nOr skip installing: join the [Discord server](http://discord.skerritt.blog), go to `#bots` and type `$ciphey \u003cyour text\u003e` (`$help` lists the commands).\n\n## Quick start\n\n```console\n$ ciphey -t 'aGVsbG8gdGhlcmUgZ2VuZXJhbA=='\n🕵️ I think the plaintext is Words.\nPossible plaintext: 'hello there general' (y/N):\ny\n\n🥳 ciphey has decoded 64 times.\n\nThe plaintext is:\nhello there general\nthe decoder used is Base64\n```\n\nThe first time you run it, a short setup asks for a colour theme, how you want results shown and whether to use a wordlist, and saves your answers to `~/.ciphey/config.toml`.\n\n```bash\nciphey -t 'NTA3NjYzNzU3MjZjMjA3NjY2MjA2OTcyNjU2YzIwNzM2ZTY2Njc='   # ROT13 → hex → Base64, nothing else needed\nciphey -f secret.txt                    # read the input from a file\nciphey -d -t '...'                      # no y/N prompt: take the first plaintext found (handy in scripts)\nciphey -c 15 -t '...'                   # keep searching for up to 15 seconds (the default is 5)\nciphey -r 'flag\\{' -t '...'             # only accept plaintext that matches a regex (a crib)\nciphey --wordlist words.txt -t '...'    # also accept any exact match from a wordlist\n```\n\n`ciphey --help` lists every option.\n\n## Features\n\n### ⚡ Fast\n\n\u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/fast.mp4\"\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/fast.gif\" alt=\"A terminal runs time ciphey -d on a Base64 string. Ciphey prints 'Ciphey is very fast' and the path Base64 → Hexadecimal → caesar, and bash reports real 0m0.157s. A chart then compares Ciphey's 0.19 s (the median of 10 runs) with no answer after 60 s for Python Ciphey 5.14.0 on the same input.\"\u003e\u003c/a\u003e\n\n\u003csub\u003e▶ \u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/fast.mp4\"\u003eWatch the clip\u003c/a\u003e (16 s)\u003c/sub\u003e\n\nThree layers (ROT13, then hex, then Base64) come off in 0.16 s, measured by bash's `time` in a real recording. Here is the same comparison for more inputs, against Python Ciphey 5.14, the version Ciphey replaces:\n\n| Input | Ciphey | Python Ciphey 5.14 |\n| --- | --- | --- |\n| Base64 | 0.11 s | 0.92 s |\n| Hex → Base64 | 0.14 s | 1.02 s |\n| ROT13 → Hex → Base64 | 0.19 s | no answer within 60 s |\n| URL → Base64 → Hex | 0.24 s | 1.15 s |\n| Base64 ×4 | 0.41 s | 0.78 s |\n| Hex → Base32 → Base64 → Hex | 0.54 s | 0.72 s, wrong answer |\n| ROT13 → Hex → Base64 → Base32 | 1.15 s | no answer within 60 s |\n\n\u003csub\u003eWall-clock median of 10 runs per input (Python Ciphey: 3) on a shared 16-CPU Linux machine, Ciphey at 47bd16d6 with the y/N prompt off and a fresh \u003ccode\u003e$HOME\u003c/code\u003e per run so its cache can't help. Every run was capped at 60 s. The script and raw numbers are in \u003ca href=\"https://github.com/bee-san/Ciphey/tree/media/readme-videos/media/tui-video/bench\"\u003e\u003ccode\u003emedia/tui-video/bench\u003c/code\u003e\u003c/a\u003e on the \u003ccode\u003emedia/readme-videos\u003c/code\u003e branch.\u003c/sub\u003e\n\nWhere both get the right answer, Ciphey is 1.9 to 8.6 times faster. Where does the speed come from?\n\n- It's Rust.\n- An A* search tries the most promising chains of decoders first.\n- Every decoder runs in parallel with [Rayon](https://github.com/rayon-rs/rayon), on up to 10 candidate texts at a time.\n- Answers are cached in `~/.ciphey/database.sqlite`, so the same input a second time comes back in milliseconds.\n\n### 🧅 Layer after layer, no key needed\n\nCiphey doesn't need to be told what it's looking at. It searches chains of decoders (Base64 inside hex inside ROT13, four layers of Base64, and so on) and stops at the first candidate that looks like plaintext. By default it shows you that candidate and asks before accepting it (`-d` turns this off). The clip at the top of this page shows a four-layer decode.\n\nThere is also a timer: if Ciphey hasn't found anything after 5 seconds, it stops and says so (`-c` changes the limit).\n\nIt knows 24 decoders and crackers:\n\n| Kind | Decoders |\n| --- | --- |\n| Base encodings | Base64 (standard and URL-safe), Base32, Base58 (Bitcoin, Flickr, Monero, Ripple), Base91, Base65536, Z85 |\n| Other encodings | Hexadecimal, binary, URL (percent-encoding), Morse code, Braille, A1Z26, Citrix CTX1 |\n| Ciphers | Caesar (including ROT13), ROT47, Atbash, Vigenère (it works out the key itself), rail fence, reversed text |\n| Oddities | Brainfuck (it runs the program), Morse or binary written with other symbols |\n\nMore are on the way: [#1030](https://github.com/bee-san/Ciphey/issues/1030) tracks 109 decoders that aren't in yet.\n\n### 🕵️ Knows what it found\n\n\u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/lemmeknow.mp4\"\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/lemmeknow.gif\" alt=\"Three Ciphey runs. Base64 decodes to 'mount -o username=bee,password=hunter2', identified as a Mount Command With Clear Credentials. Base64 decodes to an otpauth:// link, identified as a Time-Based One-Time Password (TOTP) URI. Hex decodes to 192.168.0.1, identified as an Internet Protocol (IP) Address Version 4.\"\u003e\u003c/a\u003e\n\n\u003csub\u003e▶ \u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/lemmeknow.mp4\"\u003eWatch the clip\u003c/a\u003e (21 s)\u003c/sub\u003e\n\nEvery candidate plaintext also goes through [LemmeKnow](https://github.com/swanandx/lemmeknow), the Rust port of [pyWhat](https://github.com/bee-san/pyWhat), which recognises more than 120 formats. So Ciphey doesn't just decode the string, it tells you what it is: a password in a `mount` or `sshpass` command, a TOTP secret, a GitHub token or Stripe key, an IP or MAC address, an email address or URL, a card number, a crypto wallet, an AWS ARN or a CTF flag.\n\n```console\n$ ciphey -t '3139322e3136382e302e31'\n🕵️ I think the plaintext is Internet Protocol (IP) Address Version 4.\nPossible plaintext: '192.168.0.1' (y/N):\n```\n\n### 🎯 Crib and regex mode\n\n\u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/crib.mp4\"\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/crib.gif\" alt=\"A terminal runs ciphey -t on a Base64 string with -r 'picoCTF\\{'. Ciphey reports 'Regex matched: picoCTF\\{', asks about 'picoCTF{b4s3_64_1s_fun}', and prints it as the plaintext, decoded with Base64.\"\u003e\u003c/a\u003e\n\n\u003csub\u003e▶ \u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/crib.mp4\"\u003eWatch the clip\u003c/a\u003e (14.5 s)\u003c/sub\u003e\n\nIf you know part of the answer (the flag format, a word that has to be in there, how it starts), give it to Ciphey as a regex with `-r`. The other checkers switch off and only text that matches is accepted. This finds plaintext the English detection would pass over: Base64-encoded `picoCTF{b4s3_64_1s_fun}` comes back as gibberish by default, but with `-r 'picoCTF\\{'` it's the first match.\n\n`--wordlist words.txt` works the same way for exact matches: a candidate that is a line in the file counts as plaintext.\n\n### 🎨 Made for your terminal\n\nThe first-run setup lets you pick a colour theme (Capptucin, Darcula, GirlyPop, the default, or your own RGB values) and choose between being asked about each plaintext or getting a list of candidates at the end. You can see it [in the tour](https://cdn.jsdelivr.net/gh/bee-san/Ciphey@d41d19946234477346fede14dadf8c351cc469e6/media/tui-video/out/ciphey-tui-promo.mp4) from 0:32. Everything is saved to `~/.ciphey/config.toml`, which you can edit later.\n\n### 📚 Library first\n\nThe `ciphey` binary is a thin wrapper around the `ciphey` crate. The [Discord bot](https://github.com/bee-san/discord-bot) uses it as well, and so can your code.\n\n## Use it as a library\n\n`perform_cracking` runs the whole search, as the `ciphey` binary does:\n\n```rust\nuse ciphey::config::Config;\nuse ciphey::{perform_cracking, CipheyError};\n\nfn main() {\n    let mut config = Config::default();\n    config.timeout = 5; // seconds\n    config.human_checker_on = false; // never prompt on stdin\n    config.api_mode = true; // don't print progress to stdout\n    // config.regex = Some(r\"flag\\{\".to_string()); // only accept plaintext matching a crib\n\n    match perform_cracking(\"aGVsbG8gdGhlcmUgZ2VuZXJhbA==\", config) {\n        Ok(Some(result)) =\u003e {\n            let path: Vec\u003c\u0026str\u003e = result.path.iter().map(|step| step.decoder).collect();\n            println!(\"{} (via {})\", result.text[0], path.join(\" → \"));\n        }\n        Ok(None) =\u003e println!(\"no plaintext found\"),\n        Err(CipheyError::Timeout { secs }) =\u003e println!(\"gave up after {secs}s\"),\n        Err(e) =\u003e eprintln!(\"error: {e}\"),\n    }\n}\n```\n\nThis prints `hello there general (via Base64)`.\n\n### One decoder\n\nIf you know what you're looking at, call that decoder. Each one is a function in `ciphey::decoders`: encodings come back decoded, ciphers are cracked, and the ones that take a key can decrypt with yours.\n\n```rust\nuse ciphey::decoders;\n\nlet decoded = decoders::base64(\"aGVsbG8gd29ybGQ=\");\nassert_eq!(decoded.candidates[0].text, \"hello world\");\n\n// No key: Ciphey tries every shift and marks the one its checks accept\nlet cracked = decoders::caesar(\"Uryyb jbeyq\");\nlet plaintext = cracked.plaintext().expect(\"a shift reads as English\");\nassert_eq!(plaintext.text, \"Hello world\");\nassert_eq!(plaintext.key.as_deref(), Some(\"13\"));\n\n// With the key\nlet decrypted = decoders::vigenere_with_key(\"Rijvs uyvjn\", \"KEY\")?;\nassert_eq!(decrypted.candidates[0].text, \"Hello world\");\n```\n\nTo choose the decoder at run time, `decode_with` takes its name or an alias, and `list_decoders` lists them all with their aliases, tags and the key they take:\n\n```rust\nuse ciphey::{decode_with, list_decoders, DecodeOptions};\n\nlet cracked = decode_with(\"rot13\", \"Uryyb jbeyq\", \u0026DecodeOptions::default())?;\nlet decrypted = decode_with(\"affine\", \"IHHWVC SWFRCP\", \u0026DecodeOptions::with_key(\"a=5, b=8\"))?;\n\nfor decoder in list_decoders() {\n    println!(\"{}: {}\", decoder.name, decoder.key_format.unwrap_or(\"no key\"));\n}\n```\n\nNothing is filtered out: you get what the decoder hands on to the search. The candidate Ciphey's plaintext checks accept comes first and carries a `detection`; if they accept none, you get the decodings unmarked, for you to judge (all 25 Caesar shifts, say, though crackers with many keys hand on only their best few).\n\n### Is it plaintext?\n\n`detect_plaintext` runs the checks the search uses (a regex crib, a wordlist, LemmeKnow, common passwords and English) and says which one accepted the text and what it took it for:\n\n```rust\nuse ciphey::detection::{detect_plaintext, CheckerKind, DetectOptions, Sensitivity};\n\nlet found = detect_plaintext(\"192.168.0.1\", \u0026DetectOptions::default()).unwrap();\nassert_eq!(found.checker, CheckerKind::LemmeKnow);\nassert_eq!(found.description, \"Internet Protocol (IP) Address Version 4\");\nassert_eq!(found.confidence, Some(0.7)); // the format's rarity in pyWhat\n\n// Pick the checkers and how strict the English checker is, or give a crib\nlet english_only = DetectOptions::new()\n    .checkers([CheckerKind::English])\n    .sensitivity(Sensitivity::Low);\nlet crib = DetectOptions::new().regex(r\"^flag\\{\")?;\n```\n\n`cargo run --example decode` tours all of this, and `cargo run --example decode -- list` lists the decoders.\n\n- `perform_cracking` returns `Result\u003cOption\u003cDecoderResult\u003e, CipheyError\u003e` on `master` ([#915](https://github.com/bee-san/Ciphey/pull/915)), and the single-decoder and detection functions are only on `master` so far. The last release on crates.io (0.12.0) still returns `Option\u003cDecoderResult\u003e`, so until the next release use the git version: `ciphey = { git = \"https://github.com/bee-san/Ciphey\" }`.\n- The config is global to the process. The first call's `Config` is used for every later call, and the single decoders follow it too (a `regex` crib, a wordlist). They never prompt.\n- The API is documented on [docs.rs](https://docs.rs/ciphey).\n\n## MCP server (AI assistants)\n\n\u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@5aa9760b2912611755d037c01b9d2ed14fd3bf81/media/mcp-video/out/ciphey-mcp.mp4\"\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@5aa9760b2912611755d037c01b9d2ed14fd3bf81/media/mcp-video/out/ciphey-mcp.gif\" alt=\"An AI assistant (Kiro CLI) is asked to decode a Base64 string from a CTF challenge. It calls ciphey's decode tool over MCP, which returns the plaintext flag{ciphey_speaks_mcp} and the decoders it used, Base64 → Hexadecimal → caesar with key 13. The assistant then answers with the flag. Click to watch the 30-second video.\"\u003e\u003c/a\u003e\n\n\u003csub\u003e▶ \u003ca href=\"https://cdn.jsdelivr.net/gh/bee-san/Ciphey@5aa9760b2912611755d037c01b9d2ed14fd3bf81/media/mcp-video/out/ciphey-mcp.mp4\"\u003eWatch the video\u003c/a\u003e (29.5 s). The chat replays a real Kiro CLI session with ciphey-mcp.\u003c/sub\u003e\n\n`ciphey-mcp` is a [Model Context Protocol](https://modelcontextprotocol.io) server, so AI assistants such as Claude Desktop and Kiro can decode text with Ciphey. It's behind the `mcp` feature, so the normal `ciphey` build doesn't include it:\n\n```sh\ncargo install ciphey --features mcp --bin ciphey-mcp\n# or, from a clone of this repository:\ncargo install --path . --features mcp --bin ciphey-mcp\n```\n\nThe `mcp` feature isn't in a crates.io release yet (0.12.0 is the latest), so until the next one, install from git: `cargo install --git https://github.com/bee-san/Ciphey ciphey --features mcp --bin ciphey-mcp`.\n\nIt provides four tools:\n\n- `decode` decodes `text` when you don't know how it was encoded, and returns the `plaintext` and the `path` of decoders used, with keys such as the Caesar shift. Optional arguments: `timeout_secs` (1 to 30, default 10) and `regex`, a crib the plaintext must match, such as `flag\\{`.\n- `decode_with` runs one decoder you choose on `text`: give it the `decoder`'s id, name or an alias (`base64`, `rot13`, `vigenere`, `xor_single_byte`, ...). Without a `key` it decodes the text, or cracks the cipher by trying every key; with one it decrypts, for ciphers that take a key (`13`, `LEMON`, `a=5, b=8`, `rails=3, offset=1`). It returns every candidate decoding and whether each passes Ciphey's plaintext check. `regex` works as for `decode`.\n- `detect_plaintext` checks whether `text` already is plaintext, without decoding it, and says which checker accepted it, what it took it for and, for LemmeKnow's formats, how sure it is. Optional arguments: `checkers` (any of `lemmeknow`, `password` and `english`, by default all three), `sensitivity` of the English checker (`low`, `medium` or `high`) and a `regex` crib.\n- `list_decoders` lists the encodings and ciphers Ciphey supports, with the ids and aliases `decode_with` takes and the key format of each cipher that takes one.\n\nA `decode` result looks like this. `status` is `decoded`, `not_found` or `timed_out`.\n\n```json\n{\n  \"status\": \"decoded\",\n  \"plaintext\": \"hello there general\",\n  \"path\": [{ \"decoder\": \"Base64\", \"key\": null }],\n  \"checker\": \"English Checker\",\n  \"timeout_secs\": 10\n}\n```\n\n`decode_with` with `{\"decoder\": \"rot13\", \"text\": \"Uryyb jbeyq\"}` gives the result below. `status` is `plaintext_found`, `no_plaintext` (none of the candidates passed the check, so judge them yourself) or `no_candidates` (the text isn't in that decoder's format). A result holds at most 100 candidates and 65,536 characters of their text; `total_candidates` says how many there were, and a candidate cut short has `truncated` set.\n\n```json\n{\n  \"decoder\": \"caesar\",\n  \"status\": \"plaintext_found\",\n  \"candidates\": [\n    {\n      \"text\": \"Hello world\",\n      \"truncated\": false,\n      \"key\": \"13\",\n      \"is_plaintext\": true,\n      \"detection\": { \"checker\": \"english\", \"description\": \"Words\", \"confidence\": null }\n    }\n  ],\n  \"total_candidates\": 1\n}\n```\n\n`detect_plaintext` with `{\"text\": \"192.168.0.1\"}` gives:\n\n```json\n{\n  \"is_plaintext\": true,\n  \"detection\": {\n    \"checker\": \"lemmeknow\",\n    \"description\": \"Internet Protocol (IP) Address Version 4\",\n    \"confidence\": 0.7\n  },\n  \"checkers\": [\"lemmeknow\", \"password\", \"english\"]\n}\n```\n\nEvery call except `list_decoders` runs in its own short-lived process. Input is limited to 65,536 characters (keys too) and regexes to 1,000. A `decode` searches for at most 30 seconds and may use 1 GiB of memory; a `decode_with` call may run for 30 seconds and a `detect_plaintext` call for 10, with 256 MiB each. At most two decodes and four other calls run at once. The server doesn't read or write `~/.ciphey`, so there's no config file and no cache.\n\n### Claude Desktop\n\nOpen Settings → Developer → Edit Config, add the server to `claude_desktop_config.json`, then restart Claude Desktop. Use the full path printed by `which ciphey-mcp` (`where ciphey-mcp` on Windows, for example `C:\\\\Users\\\\you\\\\.cargo\\\\bin\\\\ciphey-mcp.exe`), because Claude Desktop may not see your shell's `PATH`.\n\n```json\n{\n  \"mcpServers\": {\n    \"ciphey\": {\n      \"command\": \"/Users/you/.cargo/bin/ciphey-mcp\"\n    }\n  }\n}\n```\n\n### Kiro\n\n```sh\nkiro-cli mcp add --name ciphey --command ciphey-mcp\n```\n\nOr add the entry below to `~/.kiro/settings/mcp.json` (all projects) or `.kiro/settings/mcp.json` (one project).\n\n### Other clients\n\nMost MCP clients take the same `mcpServers` entry: a stdio server started by `ciphey-mcp` with no arguments.\n\n```json\n{\n  \"mcpServers\": {\n    \"ciphey\": {\n      \"command\": \"ciphey-mcp\",\n      \"args\": []\n    }\n  }\n}\n```\n\n## Good to know\n\n- Plaintext detection isn't perfect. Very short phrases, text that isn't English, JSON and unusual flag formats can be missed or mistaken for something else. [#1031](https://github.com/bee-san/Ciphey/issues/1031) has the details and the planned fixes. If you know anything about the answer, a crib (`-r`) or a wordlist helps a lot.\n- If a cached answer is wrong, delete `~/.ciphey/database.sqlite` to clear the cache.\n- If you're stuck, ask in `#coded-messages` on [Discord](http://discord.skerritt.blog).\n\n## Documentation\n\n- [API docs on docs.rs](https://docs.rs/ciphey)\n- [The `docs/` folder](docs/), including an [overview](docs/ares_overview.md), the [architecture](docs/ares_architecture.md), [how the A* search works](docs/astar.md) and [how plaintext is identified](docs/plaintext_identification.md)\n- [Ciphey 2 documentation](https://broadleaf-angora-7db.notion.site/Ciphey2-32d5eea5d38b40c5b95a9442b4425710) on Notion\n- [Introducing Ares](https://skerritt.blog/introducing-ares/), the blog post about the Rust rewrite (it was called Ares before it became Ciphey)\n\n## Contributing\n\nBug reports, ideas and pull requests are welcome in [issues](https://github.com/bee-san/Ciphey/issues). A new decoder is a good first contribution: pick one from [#1030](https://github.com/bee-san/Ciphey/issues/1030), and copy the shape of an existing one in [`src/decoders/`](src/decoders/). You can also [sponsor the project](https://github.com/sponsors/bee-san).\n\n\u003ca href=\"https://github.com/bee-san/Ciphey/graphs/contributors\"\u003e\u003cimg src=\"https://contrib.rocks/image?repo=bee-san/Ciphey\" alt=\"Avatars of the people who have contributed to Ciphey\"\u003e\u003c/a\u003e\n\n## Credits\n\n- [LemmeKnow](https://github.com/swanandx/lemmeknow) by [@swanandx](https://github.com/swanandx) identifies what Ciphey finds, and [gibberish-or-not](https://github.com/bee-san/gibberish-or-not) decides whether it's English.\n- [Rayon](https://github.com/rayon-rs/rayon) runs the decoders in parallel.\n- Ciphey started as a Python project; Python Ciphey 5.x is still on [PyPI](https://pypi.org/project/ciphey/). Thank you to everyone who worked on it.\n- The videos are made with [HyperFrames](https://hyperframes.heygen.com/) from real terminal recordings. The source, recordings and build script are in [`media/tui-video`](https://github.com/bee-san/Ciphey/tree/media/readme-videos/media/tui-video) on the `media/readme-videos` branch.\n\n## AI use\n\nWe use AI for 2 things:\n\n1. The TUI is entirely vibe coded.\n2. I made AI spend hours researching every single CTF challenge out there. It created a list of 15,071 CTFs. It then went through every single CTF and looked for writeups. In those writeups it looked for anything related to encoding / decoding. It then created tests out of those. This enabled us to increase our testing coverage and make sure all CTF encoding / decoding challenges are solvable with this tool.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbee-san%2Fciphey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbee-san%2Fciphey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbee-san%2Fciphey/lists"}