{"id":37124751,"url":"https://github.com/soyart/gfc","last_synced_at":"2026-01-14T14:25:13.888Z","repository":{"id":49346228,"uuid":"349819682","full_name":"soyart/gfc","owner":"soyart","description":"stable branch of gfc, a small go file encryption utility using AES 256 and PBKDF2","archived":false,"fork":false,"pushed_at":"2024-10-06T14:17:32.000Z","size":845,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"stable","last_synced_at":"2025-08-17T00:33:20.665Z","etag":null,"topics":["aes","crypto","cryptography","encryption","rsa"],"latest_commit_sha":null,"homepage":"","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/soyart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2021-03-20T19:40:25.000Z","updated_at":"2022-07-24T18:55:07.000Z","dependencies_parsed_at":"2023-11-27T17:47:52.199Z","dependency_job_id":"779977e1-8ec9-4b4e-8c8c-37d2bc4ab959","html_url":"https://github.com/soyart/gfc","commit_stats":null,"previous_names":["soyart/gfc","artnoi43/gfc"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/soyart/gfc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soyart%2Fgfc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soyart%2Fgfc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soyart%2Fgfc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soyart%2Fgfc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soyart","download_url":"https://codeload.github.com/soyart/gfc/tar.gz/refs/heads/stable","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soyart%2Fgfc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28422944,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["aes","crypto","cryptography","encryption","rsa"],"created_at":"2026-01-14T14:25:12.738Z","updated_at":"2026-01-14T14:25:13.873Z","avatar_url":"https://github.com/soyart.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gfc (go file crypt)\n\n\u003e gfc is my first programming project, written the first day I learned Go.\n\ngfc is a minimal encryption CLI tool designed to be versatile and easy to use. This package provides [an executable](./cmd/gfc.go), and [a library](./pkg/gfc) providing high-level wrapper for AES256-GCM, AES256-CTR, RSA256-OEAP, ChaCha20-Poly1305, XChaCha20-Poly1305 primitives.\n\ngfc can encrypt any files which the user has read access to (except for RSA, which has limited message length), as well as stdin.\n\n## Features\n\n- AES256-GCM and AES256-CTR encryption\n\n- XChaCha20-Poly1305, and ChaCha20-Poly1305 encryption\n\n- RSA-OEAP SHA512 encryption\n\n- PBKDF2 passphrase hash derivation for symmetric cryptography\n\n- ZSTD compression\n\n- Hexadecimal or Base64 output\n\n- Reads from files or stdin, and writes to files or stdout\n\nThe AES part of the code was first copied from [this source](https://levelup.gitconnected.com/a-short-guide-to-encryption-using-go-da97c928259f) for AES CTR, and [this source](https://gist.github.com/enyachoke/5c60f5eebed693d9b4bacddcad693b47) for AES GCM, although both files have changed so much since.\n\n\u003e ALERT: gfc stable just merged with commits that changed how final file layout is written, so if you have files encrypted with previous build of `gfc`, decrypt it with older versions, and re-encrypt plaintext with the current version.\n\n## Using gfc as a Go library\n\nPackage [`github.com/soyart/gfc/pkg/gfc`](./pkg/gfc/) provides public functions for encrypting/decrypting and encoding/decoding.\n\n\u003e The data parameter to these cryptography functions is [`gfc.Buffer`](./pkg/gfc/buffer.go), which is quite constrained.\n\u003e In the [main program](./internal/cli/cli.go), `bytes.Buffer` is used as the standard way to pass data bytes around.\n\u003e This may be changed and the functions might just take `[]byte`.\n\n## Using gfc as a program:\n\n### Building gfc\n\nBuild `gfc` executable from source with `go build`:\n\n```bash\ngo build cmd/gfc;  # compile gfc\ncp gfc ~/bin/.;    # copy gfc to $PATH, for example $HOME/bin\n```\n\n### Generating gfc encryption keys\n\n#### Generating symmetric key for AES or ChaCha20 encryption\n\nTo generate a new AES key, I usually use `dd(1)` write 32 bytes of random character to a file:\n\n```bash\ndd if=/dev/random of=assets/files/aes.key bs=32 count=1;\n```\n\nI'm too lazy to add deterministic keyfile hasher, so gfc will assume that the key is well randomized and can be used right away without PBKDF2 or SHA256 hash.\n\n\u003e In any cases, users should replace the test file `gfc/files/aes.key` included in this repository.\n\n#### Generating RSA keypair for gfc with OpenSSL\n\nFirst, you create a private key. In this case, it will be 4096-byte long with name `pri.pem`:\n\n```bash\nopenssl genrsa -out pri.pem 4096;\n```\n\nThen, derive a public key `pub.pem` from your private key `pri.pem`:\n\n```bash\nopenssl rsa -in pri.pem -outform PEM -pubout -out pub.pem;\n```\n\n## PBKDF2 key derivation function\n\nPassphrases will be securely hashed using PBKDF2, which added random number _salt_ to the passphrase before SHA256 hashing is performed to ensure that the derived key will always be unique, even if the same passphrase is reused.\n\nTo decrypt files encrypted with key derived from a passphrase, that same _salt_ is needed in order to convert input passphrase into the key used to encrypt it in the first place.\n\nKey and salt handling is in `pkg/gfc/pbkdf2.go`.\n\n## Usage\n\n### Defaults\n\nDefault infile: stdin\n\nDefault outfile: stdout\n\nDefault encryption mode:\n\n- AES: AES256-GCM\n\n- ChaCha20: XChaCha20-Poly1305\n\n- RSA: RSA256-OEAP (only one is supported)\n\nDefault encoding: None\n\nDefault compression: None\n\nDefault key source (symmetric key cryptography only): Passphrase\n\n### Help\n\ngfc has 2 subcommands - `aes` for AES encryption, and `rsa` for RSA encryption. To see help for each subcommand, just run:\n\n```bash\ngfc aes -h; # See help for gfc-aes\ngfc rsa -h; # See help for gfc-rsa\ngfc cc20 -h; # See help for gfc-cc20\n```\n\n### General arguments/flags\n\n#### Input and output\n\n`-i \u003cINFILE\u003e`, `--infile \u003cINFILE\u003e`, `-o \u003cOUTFILE\u003e`, and `--outfile \u003cOUTFILE\u003e` can be used to specify infile/outfile. If nothing is specified, stdin is used by default for input file, and stdout is used for output file.\n\n```bash\n# Encrypt foo.txt with AES256-GCM to out.bin\ngfc aes -i foo.txt -o out.bin;\n\n# Encrypt foo.txt with AES256-GCM to stdout\ngfc aes -i foo.txt;\n```\n\nThere're 2 ways to use stdin input - piping and by entering text manually.\n\n```bash\n # gfc gets its input from pipe, and encrypts it with AES256-GCM\n curl https://artnoi.com | gfc aes -o artnoi.com.bin;\n\n # User types text input into stdin. The input ends with \"\\n\".\n # The output is written to ./text.bin\n gfc aes --text -o text.bin;\n```\n\n#### Pre-encryption and post-encryption\n\n\u003e For more info on gfc pre-processing and post-processing, see [CLI page](/internal/cli/)\n\n##### Encoding\nWe can also apply some encoding to our output (encryption) or input (decryption) with `-e \u003cENCODING\u003e` or `--encoding \u003cENCODING\u003e`:\n\n```bash\n# The first execution spits hex-encoded output to the other execution, which expects it\ngfc aes -i plain.txt -k mykey --encoding hex | gfc aes -d -k mykey --encoding hex;\n```\n\n##### Compression\n\nSimilar to encoding, we can enable ZSTD compression with flag `-c` or `--compress`. The example below combines ZSTD compression with hex encoding:\n\n```bash\ngfc aes --compress -i plain.txt -k mykey -e hex | gfc aes --compress -d -k mykey -e hex;\n```\n\n#### Encryption key\n\n##### AES and XChaCha20\nIn `gfc-aes` and `gfc-cc20`, we can specify key filename to use with `-k \u003cKEYFILE\u003e` or `--key \u003cKEYFILE\u003e`. The key must be 256-bit, i.e. 32-byte long. If the key argument is omitted, a user-supplied passphrase will be used to derive an encryption key using PDKDF2.\n\n```bash\n# gfc will read key from ~/.secret/mykey and uses it to encrypt plain.txt to out.bin;\ngfc aes -k ~/.secret/mykey -i plain.txt -o out.bin;\n# The same as above, but XChaCha20-Poly1305 is used\ngfc cc20 -k ~/.secret/mykey -i plain.txt -o out.bin;\n```\n\n##### RSA\n\nIt's quite tricky to specify RSA key in the command line, since the keypairs are usually long and multi-lined. As a result, we should leverage the power of UNIX shell to read keyfiles for us. The syntax for this is `\"$(\u003c FILENAME)\"`, where the shell reads the file for us and gives us the content string.\n\nRSA keyfiles can be specified in 2 ways - with environment variable or as a full flag:\n\n```bash\n# The shell reads the content of file my_pub.pem to variable PUB\nexport PUB=\"$(\u003c my_pub.pem)\";\n\n# gfc uses the public key from ENV variable 'PUB' and uses it to encrypt plain.txt\ngfc rsa -i plain.txt -o out.bin;\n# The exact same thing as above, but key is given as argument instead\ngfc rsa -i plain.txt -o out.bin --public-key=\"$(\u003c my_pub.pem)\";\n# The shell reads the content of file my_pri.pem to variable PRI\nexport PRI=\"$(\u003c my_pri.pem)\";\n\n# gfc uses the public key from ENV variable 'PRI' and uses it to decrypt out.bin\ngfc rsa -d -i out.bin;\n# The exact same thing as above, but key is given as argument instead\ngfc rsa -d -i out.bin --private-key=\"$(\u003c my_pri.pem)\";\n```\n\n### Command examples\n\n## Encrypting a directory\n\n\u003e Bash script `rgfc.sh` can be used to perform this task. Usage is simple; `$ rgfc.sh \u003cdir\u003e \u003coutfile\u003e` will first create temporary tarball from `\u003cdir\u003e`, and encrpyts the tarball. If the encryption is successful, the unencrypted tarball is removed.\n\ngfc does not recursively encrypt/decrypt files - that would add needless complexity. If you are encrypting a directory (folder), use `tar(1)` to archive (and optionally compress) the directory, and use gfc to encrypt that tarball.\n\nFor example, to create Zstd compressed archive of directory _before encryption_ `foo`:\n\n```bash\ntar --zstd -cf foo.zstd foo;\n```\n\nAnd extract it after decryption with:\n\n```bash\ntar --zstd -xf foo.zstd;\n```\n\nOr with xz compression:\n\n```bash\ntar -cJf foo.txz foo;\ntar -xJf foo.txz;\n```\n\n## Testing gfc\n\nIn addition to Go unit tests, Bash scripts `gfc_test.sh` is shipped with gfc and can be use to test a combination of commands.\n\n## Repositories\n\nThere are 2 repositories for gfc, one on GitHub.com and one on GitLab.com\n\nThe main (stable) branch of gfc is hosted on [Github](https://github.com/soyart/gfc).\n\n## Depedencies\n\nI try my best to keep [dependencies](go.mod) low and aviod using external libraries.\n\nimported for ZSTD compression\n\n## License\n\nThis software is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoyart%2Fgfc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoyart%2Fgfc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoyart%2Fgfc/lists"}