{"id":21038861,"url":"https://github.com/revelaction/privage","last_synced_at":"2026-01-05T01:21:51.996Z","repository":{"id":61625654,"uuid":"444220104","full_name":"revelaction/privage","owner":"revelaction","description":"privage is a terminal based password manager and general file encryption tool","archived":false,"fork":false,"pushed_at":"2024-09-14T01:06:15.000Z","size":153,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-09-14T14:43:30.283Z","etag":null,"topics":["age","age-encryption","encryption","golang","password-manager","piv","yubikey"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/revelaction/privage","language":"Go","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/revelaction.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":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-03T22:45:49.000Z","updated_at":"2024-09-14T01:06:18.000Z","dependencies_parsed_at":"2023-10-21T11:21:47.466Z","dependency_job_id":"7afd4d3d-472d-4ae3-aa8e-770b3300f830","html_url":"https://github.com/revelaction/privage","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revelaction%2Fprivage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revelaction%2Fprivage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revelaction%2Fprivage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revelaction%2Fprivage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/revelaction","download_url":"https://codeload.github.com/revelaction/privage/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225362090,"owners_count":17462363,"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","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":["age","age-encryption","encryption","golang","password-manager","piv","yubikey"],"created_at":"2024-11-19T13:36:42.625Z","updated_at":"2026-01-02T21:15:32.196Z","avatar_url":"https://github.com/revelaction.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg alt=\"kind\" src=\"./logo.png\"/\u003e\u003c/p\u003e\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/revelaction/privage)](https://pkg.go.dev/github.com/revelaction/privage)\n[![Test](https://github.com/revelaction/privage/actions/workflows/test.yml/badge.svg)](https://github.com/revelaction/privage/actions/workflows/test.yml)\n[![golangci-lint](https://github.com/revelaction/privage/actions/workflows/golangci-lint.yml/badge.svg)](https://github.com/revelaction/privage/actions/workflows/golangci-lint.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/revelaction/privage)](https://goreportcard.com/report/github.com/revelaction/privage)\n[![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/revelaction/privage/main/.github/badges/coverage.json)](https://github.com/revelaction/privage/actions/workflows/test.yml)\n[![sloc](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/revelaction/privage/main/.github/badges/sloc.json)](https://github.com/revelaction/privage/actions/workflows/sloc.yml)\n[![deps](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/revelaction/privage/master/.github/badges/deps.json)](https://github.com/revelaction/privage/actions/workflows/dependencies.yml)\n[![GitHub Release](https://img.shields.io/github/v/release/revelaction/privage?style=flat)]() \n[![GitHub Release](https://img.shields.io/badge/built_with-Go-00ADD8.svg?style=flat)]()\n\n`privage` is a terminal based password manager and general file encryption tool that\nrelies on [age](https://age-encryption.org/v1) for encryption. Optionally it uses a \n[yubikey](https://developers.yubico.com/PIV/) for encryption of the age key.\n\nThe main goal of privage is to have your secrets (credentials and other\nfiles) securely backed up in untrusted 3-party repositories whitout revealing\nany secret information (not even the file name) to those 3-party repositories.\n\n\n**WARNING: The author is not a cryptographer, and the code has not been reviewed. Use at your own risk.**\n\nYou may want to use privage if:\n\n- You want to have your encrypted credentials and other secrets files in a revision control system repository (ex: git)\n- You want to have backups of this repository in untrusted 3 party services (github, gitlab, bitbucket)\n- You do not want to leak any information (not even the name of the files) in\n  case of a breach of those 3 party services, which you otherwise should always assume.\n  privage guarantees not leaking information because it also encrypts the metadata of the files. \n- You want to have one encrypted file per credential or secret file.\n- You trust the computer running privage. `privage` uses unencrypted `age`\n  keys, following the reasoning\n  [here](https://github.com/FiloSottile/age#passphrase-protected-key-files).\n  privage supports yubikeys to encrypt the age secret key.  \n\n\n# Features\n\n- `privage` uses the golang [age API](https://github.com/FiloSottile/age/blob/main/age.go) for encryption of files.\n- privage can use a yubikey (PIV smart card) to encrypt the age secret key. See [Yubikey](#markdown-header-yubikey)   \n- privage uses `categories` to allow classification of the encrypted files. \n- Encrypted files do not reveal any metadata. `privage` encrypted files names are hashes of the file name and the category. See [design](#design)   \n- privage encrypts any kind of file, not only credentials/passwords.\n- privage can easily (with one command) change the secret key and reencode all the files with the new key. See [rotate](#rotate)   \n- privage tries to be simple: it does not wrap `git` or your editor: Use git to control your\n  repository and use your preferred editor to edit credentials files.\n- Powerful command completion. All commands have completion. See [Bash Completion](#bash-completion)   \n\n# Installation\n\nOn Linux you can use the [pre-built binaries](https://github.com/revelaction/privage/releases/)\n\nIf your system has a supported version of Go, you can build from source\n\n## Dependencies\n\n```console\nsudo apt-get -y install pkg-config libpcsclite-dev libpcsclite1 pcscd pcsc-tools build-essential pkg-config\n```\n\n## privage\n\n```console\n go install github.com/revelaction/privage/cmd...@v0.9.1-beta\n```\n\n# Usage\n\n## Initialize a repository for your credentials and other encrypted files\n\nCreate a repository to contain your encrypted credentials and other secret\nfiles. This repository can be pushed to untrusted 3-party services.\n\n```console\nmkdir /home/user/mysecrets\ncd /home/user/mysecrets\ngit init\n```\n\nNow run `privage init`:  \n\n```console\nprivage init\n🔑 Generated age key file `/home/user/mysecrets/privage-key.txt` ✔️\n📒 Generated `/home/user/mysecrets/.gitignore` file ✔️\n📑 Generated config file .privage.conf ✔️\n```\n    \nThe `init` command does three things:\n\n1. it creates a secret key file named `privage-key.txt` (if no one is found in\n   the system). The key is a standard unencrypted `age` key or a [Yubikey](#markdown-header-yubikey)  \n   encrypted age key.\n2. it creates a `.gitignore` file to make sure that only encrypted (.age) files\n   are commited in the repository. The file content is:\n\n        # Ignore everything\n        *\n\n        # But not these files...\n        !.gitignore\n        !*.age\n\n3. it creates a `.privage.conf` file in your home directory. The config file\n   contains references to the secret key and the repository path. These\n   references allows `privage` to be used in any directory of your computer.\n\nTo create a encrypted age secret key with a\n[yubikey](#markdown-header-yubikey), add the flag `--piv-slot`, `-p` with the\nyubikey slot that will be used to encrypt/decrypt the age key.\n\n```console\nprivage init -p 86\n🔑 Generated encrypted age key file `/home/user/src/privage/privage-key.txt` with PIV slot 86 ✔️\n📒 Generated `/home/user/src/privage/.gitignore` file ✔️\n📑 Generated config file .privage.conf ✔️\n```\n\n## Create a credentials file\n\nIn `privage`, credentials are structured text (`.toml` files), that can contain not only passwords, but any other\ndata associated with a website, like API keys, 2-factor backup codes, etc. \n\nTo add a barebone credentials file (that you can later edit), use the command\n`add`, specifying a `category` (for credential files it should always be\n`credential`) and a `label` (any string that good describes the website, f.ex.\n`somewebsite.com@loginname`).\n\n```console\nprivage add credential somewebsite.com@loginname\nAn encrypted file was saved for 📖 somewebsite.com@loginname  🔖credential\n```\n\n`privage` will generate a random password, put the password (among other\nfields) in a `.toml` file and encrypt that file under the `category`\n'credential'.\n\nIt is recommended to use some naming convention for the credentials label, like\n`\u003curl\u003e@loginname`\n\nYou can now list the encrypted file with: \n\n```console\nls -al\n\ndrwxrwxr-x  3 user user 4096 Sep 26 18:27 .\ndrwxr-xr-x 29 user user 4096 Sep 25 21:43 ..\n-rw-rw-r--  1 user user  347 Sep 26 18:27 66ceb74807d0fd997566360b22ecbda1590ec35fbd3dd0ce88e15311a4e53faf.age\ndrwxrwxr-x  7 user user 4096 Sep 26 18:16 .git\n-rw-------  1 user user    0 Sep 26 18:21 .gitignore\n-rw-------  1 user user  189 Sep 26 18:21 privage-key.txt\n```\n\nThat long `age` file is the encrypted credential file.  The label\n(somewebsite.com@loginname) and the category (credential) were encrypted along\nwith the credential information.\n\n## Encrypt any file\n\n`privage` can encrypt any file. You can use any category and label. \n\nFor example, to encrypt the file `secret-plan.doc` under the category\n`work`:\n\n```console\nprivage add work secret-plan.doc\n```\n\n## List the encrypted files\n\nTo list the encrypted files, use `list`:\n\n```console\nprivage list\nFound 2 total encrypted tracked files.\n\n        📖 somewebsite.com@loginname  🔖credential\n        💼 secret-plan.doc 🔖work\n```\n\n\nTo list only encrypted files corresponding to the category `credential`:\n\n```console\nprivage list credential\nFound 1 files matching your category 'credential' of a total of 2 tracked files.\n\n        📖 somewebsite.com@loginname  🔖credential\n```\n\nThe `list` command accepts a string for matching the labels and categories:\n\n```console\nprivage list somew\nFound 1 files with name matching 'somew':\n\n    📖 somewebsite.com@loginname  🔖credential\n```\n\n\n## Copy the password to the clipboard \n\nThe command `clipboard` copies the credential password to the clipboard \n\n```console\nprivage clipboard somewebsite.com@loginname \nThe password for `somewebsite.com@loginname` is in the clipboard\n```\n\nUse the flag `-d` (`--delete`) to empty the clipboard.\n\n```console\nprivage clipboard -d \n```\n\n## Show the contents of a credentials file\n\nThe command `show` presents in the terminal the login and the password of a credential file:\n\n```console\nprivage show somewebsite.com@loginname\n\n    Login:👤 loginname\n    Password:🔑 ad81h4b54*)(y73\n```\n\nIf the file is not a credential file, `privage` will ask you to use `cat`.\n\n## Show a specific field of a credentials file\n\nYou can provide a second argument to `show` to print only the value of a specific TOML field. This is particularly useful for automation and shell scripts (e.g., to retrieve an API key).\n\n```console\nprivage show somewebsite.com@loginname api_key\n```\n\nSupported field names (like `login`, `password`, `api_key`, `url`, etc.) can be autocompleted by pressing `[TAB]`.\n\n## Cat the contents of an encrypted file\n\nThe command `cat` prints the decrypted contents of an encrypted file to the terminal (standard output). This is useful for piping to other commands or viewing the raw content of a file (including the full content of credential files).\n\n```console\nprivage cat somewebsite.com@loginname\n#\nlogin = \"loginname\"\npassword = \"ad8Q1hD4b54*)(y73\"\n\nemail = \"\"\nurl = \"somewebsite.com\"\n...\n```\n\nOr for regular files:\n\n```console\nprivage cat secret-plan.doc\n```\n\n\n## Decrypt a file for manual edition\n\nUse `decrypt` to decrypt the contents of a file:\n    \n```console\nprivage decrypt somewebsite.com@loginname\nThe file somewebsite.com@loginname was decrypted in the directory /home/user/mysecrets.\n\n(Use \"privage reencrypt --force\" to reencrypt all decrypted files)\n(Use \"privage reencrypt --clean\" to reencrypt all decrypted files and after that delete them)\n```\n\n`decrypt` will write a decrypted file in the repository directory. In the case\nof credentials files, the decrypted file is a `.toml` file. You can use now\nyour favorite editor to change the password, user, email\nand other predefined fields.\n\n```console\nvim somewebsite.com@loginname\n```\n\nAfter manually changing the file, you have to reencrypt the file...\n\n## Reencrypt edited files\n\nUse the `reencrypt` command to reencrypt `all` files that were decrypted and are present in\nthe repository directory:\n\n```console\n⤷ privage reencrypt\nFound the following files to be reencrypted:\n\n📖 somewebsite.com@me  🔖credential\n\n(Use \"privage reencrypt --force\" to reencrypt all files)\n(Use \"privage reencrypt --clean\" to reencrypt and also delete the decrypted files)\n```\n\nWithout flags, `reencrypt` will only show (dry-run) the files that will be reencrypted.\nUse the flag `-f` or `-c` to force the reencryption. \n\n## Delete a encrypted file \n\nthe command `delete` deletes a encryted file:\n\n```console\nprivage delete somewebsite.com@loginname\n```\n\n## Get information about the configuration\n\n```console\n⤷ privage status\n\n🔑 Found age key file privage-key.txt in /home/user/mysecrets/privage-key.txt ✔️\n📂 The directory of the encripted files is /home/user/mysecrets ✔️\n📑 Found config file .privage.conf in /home/user/.privage.conf ✔️\n\n     The configuration file /home/user/.privage.conf is up to date\n\n🔐  Found 13 encrypted files for the age key /home/user/mysecrets/privage-key.txt\n```\n\n\n## Rotate \n\nThe `rotate` command will create a new `age` secret key and reencrypt all files with this new key.\nWith the flag `--clean`, it will also delete the encrypted files with the old key, and will rename both old and new keys. \n\nTo generate a new age key and reencrypt all the files:\n\n```console\nprivage rotate\n```\n\nYou can add the flag `--clean` to delete the old key encrypted files, and swap the secret key file names.\n\n\n```console\nprivate rotate --clean\n```\n\nTo generate a yubikey encrypted age secret key, use the flag `--piv-slot`,\n`-p`, to provide the yubikey slot that holds the key. See [possible\nvalues](https://developers.yubico.com/PIV/Introduction/Certificate_slots.html). \n\n\n```console\n# f. ex: use the 0x86 slot of the yubikey 5 \nprivate rotate -p 86 --clean\n```\n\n# Design\n\nThe content of a `privage` encrypted file is the byte concatenation of two\n`age` encrypted payloads:\n\nThe first encrypted payload (the header) contains the file name and a category\n(plus a version of the header). This encrypted payload is padded to 512 bytes.\n\n\nThe second encrypted payload contains the file contents.\n\nWhen listing the encrypted files, `privage` scans all encrypted files, retrieves the\nencrypted header payload and decrypts it, presenting the header.\n\nWhen writing the encrypted file, `privage` hashes the header and the public age\nkey, and uses the hash as name of the encrypted file. Encrypted\n`privage` file names look like this:\n\n```console\n425020f87e753ebe4dba67a872de04b7ce7350a63af9f74c1b7c4d633b41573c.age\n5e107b8e3b57411d5661d05e54f755408dd12c831a6b63e8033885c211da1317.age\n```\n\n\n# Bash Completion\n\n`privage` has builtin bash autocompletion. You can enable completion commands by putting the following bash\nsnippet in your `.bashrc` file:\n\n```console\nif command -v privage \u003e/dev/null; then\n    source \u003c(privage bash)\nfi\n```\n\n# Command line options\n\n```console\n⤷ privage help\nNAME:\nprivage - password manager/encryption tool based on age\n\nUSAGE:\nprivage [global options] command [command options] [arguments...]\n\nCOMMANDS:\ninit       Add a .gitignore, age/yubikey key file to the current directory. Add a config file in the home directory.\nkey        Decrypt the age private key with the PIV key defined in the .privage.conf file.\nstatus     Provide information about the current configuration.\nadd        Add a new encrypted file.\ndelete     Delete an encrypted file.\nlist       list metadata of all/some encrypted files.\nshow       Show the contents the an encripted file.\ncat        Print the decrypted contents of an encrypted file to stdout.\nclipboard  Copy the credential password to the clipboard\n    decrypt    Decrypt a file and write its content in a file named after the label\nreencrypt  Reencrypt all decrypted files that are already encrypted. (default is dry-run)\n    rotate     Create a new age key and reencrypt every file with the new key\n    bash       Dump bash complete script.\n    help, h    Shows a list of commands or help for one command\n\n    GLOBAL OPTIONS:\n    --conf value, -c value        Use file as privage configuration file\n    --key value, -k value         Use file path for private key\n    --piv-slot value, -p value    The PIV slot for decryption of the age key\n    --repository value, -r value  Use file path as path for the repository\n    --help, -h                    show help\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frevelaction%2Fprivage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frevelaction%2Fprivage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frevelaction%2Fprivage/lists"}