{"id":43164137,"url":"https://github.com/gtsh77/grpc-captcha","last_synced_at":"2026-02-01T01:41:55.890Z","repository":{"id":231561971,"uuid":"781604433","full_name":"gtsh77/grpc-captcha","owner":"gtsh77","description":"captcha code sequence generator, image render and verify code service incl. gRPC interfaces","archived":false,"fork":false,"pushed_at":"2024-04-12T21:03:52.000Z","size":35688,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-13T04:08:59.634Z","etag":null,"topics":["captcha","golang","grpc","redis","security"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gtsh77.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}},"created_at":"2024-04-03T17:42:28.000Z","updated_at":"2024-04-09T16:47:53.000Z","dependencies_parsed_at":"2024-04-12T21:59:27.899Z","dependency_job_id":null,"html_url":"https://github.com/gtsh77/grpc-captcha","commit_stats":null,"previous_names":["gtsh77/grpc-captcha"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/gtsh77/grpc-captcha","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtsh77%2Fgrpc-captcha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtsh77%2Fgrpc-captcha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtsh77%2Fgrpc-captcha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtsh77%2Fgrpc-captcha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gtsh77","download_url":"https://codeload.github.com/gtsh77/grpc-captcha/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gtsh77%2Fgrpc-captcha/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28963914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T01:25:30.373Z","status":"ssl_error","status_checked_at":"2026-02-01T01:25:29.809Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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":["captcha","golang","grpc","redis","security"],"created_at":"2026-02-01T01:41:55.219Z","updated_at":"2026-02-01T01:41:55.884Z","avatar_url":"https://github.com/gtsh77.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"### GRPC-CAPTCHA [v1.0.0] (12 Apr 2024)\n### INFO\n\n#### requirements\ngo v1.20+, redis v7.x, docker compose v2.x\n\n#### description\ncaptcha code sequence generator, image render and verify code service with gRPC interfaces\u003cbr\u003e\nbased on lite (render, random) version of https://github.com/dchest/captcha\n\n##### example\n[![image](https://i.postimg.cc/rshMqnnR/captcha4d.png)](https://i.postimg.cc/rshMqnnR/captcha4d.png)\n\u003e180x80px 4 digits png image\n\n#### ENV vars\n[ENV FILE](.deploy/env/local.env)\n\n#### gRPC service schema\n[PROTO](pkg/proto/grpc-captcha/grpc-captcha.proto)\n\n#### Multi platform binaries\n[LIST](bin)\n\n### SIMPLE USAGE (NON-TLS)\n\n#### start via docker image (specify own redis 7.x instance)\n```\ndocker run --rm -it -p 1111:1111 -p 2222:2222 --env-file=.deploy/env/local.env -e CAPTCHA_REDIS_HOST=0.0.0.0 -e CAPTCHA_REDIS_PORT=6379 -e CAPTCHA_REDIS_DB=0 -e CAPTCHA_REDIS_PASS=YQ3dvPx3fVzv gtsh77workshop/grpc-captcha:v1.0.0\n```\n\n#### OR start via docker compose with redis\n```\ndocker compose -f docker-compose.local.yml up\n```\n\n#### OR export env settings and use binaries depends on your platform\n```\nexport $(grep -v '^#' ./deploy/env/local.env | xargs)\n./bin/grpc-captcha_linux_amd64\n```\n\n#### grpc: generate new captcha image (insecure)\n```\ngrpcurl -H 'x-api-key: 1ace3bed-3aaf-4642-adb1-d63aef85895f' -plaintext -import-path pkg/proto/grpc-captcha -proto grpc-captcha.proto 0.0.0.0:2222 werkstatt.captcha.CaptchaService.Generate |jq\n{\n  \"id\": \"acf26399-0aa3-4fea-89ef-495476315998\",\n  \"data\": \"iVBORw0KGgoAAAANSUhEUgAAALQAAABQCAMAAACHxq+UAAAAP1BMVEUAAAA5QBDe5bWzuord5LSwt4fZ4LBzekq5wJDHzp7g57dzekp6gVEyOQlUWyuMk2NSWSmZoHDHzp6Ij1+xuIidZE4xAAAAAXRSTlMAQObYZgAAA29JREFUeJzsmt2yqyoMx5Npay9qp07f/2HPVBGSEL4R19ljerF3K4Qff0KIuuCyyy677LLLLrvsVMOzASoMERHwf4aOK/bfJ5+myf7f4h4Bbr293+9GV9MkqS3w+m8f21cQNuZWagWaKh2lfuThEikOgQbjOq60+fXxSFAzYB36+XxWUnvMbkwNxbZJMXNg64wz11HzgRIRARlRY1uyHaK26QKd3HsF+zMneXZSOk4U2J9oP17ThPVgTkpNlH6yTnSrZXnqafGxiNJWIwRtu41kjq/qekUojdJc26FKB7aPQWJXUPnAeKFZ7aExUx4hrvs2FBp47eFd0g4g5ZubyjIIO1DlIQGi85B5jk1sWZZxke2fIk56ssXkahBmE/3L0DjhSCTIvV95h31eoCXvUdAGlOhLlZablYS0euRk2dRGDUo20PRHQhrJ3ZnMUxs1OQJZjhBJjtAxfHvDUkjdxsyovmQe7CIQefdp2UNGS55Hm5Pr+/3an9TINfxKdh/MbAdFBK40okpt2opyb/jjCG8v2d3nItcGhGnKDs0TmH2lnJw8SvaL7tJ50DIDsLPSr+9MFy1ZVg3eAD3PM81hIn/4IaSf+lVjV/ecf8Y2HpA6lijOp4rYqnR+X3nbaqB5hgCub0jrltxR0lnZeEJpYPThEbAlSxdOmEchmpgGVen4GAOZ+Q0AWWT+nE/UFNp9pVuYGuii1MHuXOTuY0+xfUKFuUbu4iILQL4SkAOjWmWo5XUlN9ZlaOTjsVPObUa/i/jOFqto7Apmr4hTr/k9ZKnEe3Rhjnvx48J6DcY0qaA04XOwk+2SbnQPwewhg6qMJi/TpbJRwEUkT8d2XjK0Mw+jeBYNDrLJeLvd/Ed5YeYEtVmbrBAKNYy+llsX/vYzKS0J6ogMxOm7ghlsYKN/nx33sUL7FXVyk7AnxutbIwSXQ8vyIhXLHYkRH1Lp3NHIkYuIbzdUYW4mSttFTvv4Ca2+b8ka0hW1ez6oKlDc9ItnXWF6hVvrC0tuGNqtz1jYcD952b9q97MBKux+P5Y6+YcWVXY48yHUh9og6Lmrt2ro9djNtXnuTl3TbavKsq0vc60VQrdbj8UaDb09AGy18UJ33hcDTIM+5VVGkanMf57as0OgX70dCtugP119vl4DqOHz6Uzd1VvI2pj/CwAA//9L/w3JNJ6cGwAAAABJRU5ErkJggg==\"\n}\n```\n\n#### grpc: validate captcha (insecure)\n```\ngrpcurl -H 'x-api-key: 1ace3bed-3aaf-4642-adb1-d63aef85895f' -plaintext -import-path pkg/proto/grpc-captcha -proto grpc-captcha.proto -d '{\"id\":\"acf26399-0aa3-4fea-89ef-495476315998\", \"otp\": \"5485\"}' 0.0.0.0:2222 werkstatt.captcha.CaptchaService.Verify |jq\n{}\n```\n\n#### render png\npaste data field value into \nhttps://onlinepngtools.com/convert-base64-to-png\n\n#### redis client (opt)\n```\ndocker run -it --rm --network host redis:7.2-alpine redis-cli -p 6379 -a YQ3dvPx3fVzv\n```\n\n### SECURED USAGE (TLSv1.2/v1.3)\n\nFor most cases we recommend simple use local proxy (eg `nginx`) with TLS enabled which upstreams non-tls captcha service or even simpler you can use `k8s` which already have its own TLS proxy/balancer\n\nIf in some cases there is no possibility to have a local proxy **we prepared this full operable example for direct interaction with service's interfaces through TLS**\n\n1. load our test self-signed crt/keys data into env variables or use own (crt, key and ca crt) [using data instead of file path helps with k8s pod implementation, so you need to load them in advance]\n    ```\n    export CAPTCHA_HTTP_TLS_CRT_DATA=`cat .deploy/crt/secure.nd.crt` CAPTCHA_GRPC_TLS_CRT_DATA=`cat .deploy/crt/secure.nd.crt` CAPTCHA_REDIS_TLS_CRT_DATA=`cat .deploy/crt/secure.nd.crt` CAPTCHA_HTTP_TLS_KEY_DATA=`cat .deploy/crt/secure.nd.key` CAPTCHA_GRPC_TLS_KEY_DATA=`cat .deploy/crt/secure.nd.key` CAPTCHA_REDIS_TLS_KEY_DATA=`cat .deploy/crt/secure.nd.key` CAPTCHA_HTTP_TLS_CRT_CA_DATA=`cat .deploy/crt/ca.crt`  CAPTCHA_GRPC_TLS_CRT_CA_DATA=`cat .deploy/crt/ca.crt` CAPTCHA_REDIS_TLS_CRT_CA_DATA=`cat .deploy/crt/ca.crt`\n    ```\n\n2. start via docker compose (tls variant)\n    ```\n    docker compose -f docker-compose.tls.yml up\n    ```\n\n3. add crt to trusted (only if self-signed) to be able to interact with grpc interface via tls\n    ```\n      apt install ca-certificates\n      cp .deploy/crt/secure.nd.crt /usr/local/share/ca-certificates/.\n      update-ca-certificates\n    ```\n\n4. set local domain which corresponds to your crt's CN (opt) [below example for test self-signed crt/key provided within repo]\n    ```\n    vi /etc/hosts\n    captcha.secure.nd 127.0.0.1\n    ```\n\n#### grpc: generate new captcha image (secure)\n```\ngrpcurl -H 'x-api-key: 1ace3bed-3aaf-4642-adb1-d63aef85895f' -import-path pkg/proto/grpc-captcha -proto grpc-captcha.proto captcha.secure.nd:2222 werkstatt.captcha.CaptchaService.Generate |jq\n{\n  \"id\": \"acf26399-0aa3-4fea-89ef-495476315998\",\n  \"data\": \"iVBORw0KGgoAAAANSUhEUgAAALQAAABQCAMAAACHxq+UAAAAP1BMVEUAAAA5QBDe5bWzuord5LSwt4fZ4LBzekq5wJDHzp7g57dzekp6gVEyOQlUWyuMk2NSWSmZoHDHzp6Ij1+xuIidZE4xAAAAAXRSTlMAQObYZgAAA29JREFUeJzsmt2yqyoMx5Npay9qp07f/2HPVBGSEL4R19ljerF3K4Qff0KIuuCyyy677LLLLrvsVMOzASoMERHwf4aOK/bfJ5+myf7f4h4Bbr293+9GV9MkqS3w+m8f21cQNuZWagWaKh2lfuThEikOgQbjOq60+fXxSFAzYB36+XxWUnvMbkwNxbZJMXNg64wz11HzgRIRARlRY1uyHaK26QKd3HsF+zMneXZSOk4U2J9oP17ThPVgTkpNlH6yTnSrZXnqafGxiNJWIwRtu41kjq/qekUojdJc26FKB7aPQWJXUPnAeKFZ7aExUx4hrvs2FBp47eFd0g4g5ZubyjIIO1DlIQGi85B5jk1sWZZxke2fIk56ssXkahBmE/3L0DjhSCTIvV95h31eoCXvUdAGlOhLlZablYS0euRk2dRGDUo20PRHQhrJ3ZnMUxs1OQJZjhBJjtAxfHvDUkjdxsyovmQe7CIQefdp2UNGS55Hm5Pr+/3an9TINfxKdh/MbAdFBK40okpt2opyb/jjCG8v2d3nItcGhGnKDs0TmH2lnJw8SvaL7tJ50DIDsLPSr+9MFy1ZVg3eAD3PM81hIn/4IaSf+lVjV/ecf8Y2HpA6lijOp4rYqnR+X3nbaqB5hgCub0jrltxR0lnZeEJpYPThEbAlSxdOmEchmpgGVen4GAOZ+Q0AWWT+nE/UFNp9pVuYGuii1MHuXOTuY0+xfUKFuUbu4iILQL4SkAOjWmWo5XUlN9ZlaOTjsVPObUa/i/jOFqto7Apmr4hTr/k9ZKnEe3Rhjnvx48J6DcY0qaA04XOwk+2SbnQPwewhg6qMJi/TpbJRwEUkT8d2XjK0Mw+jeBYNDrLJeLvd/Ed5YeYEtVmbrBAKNYy+llsX/vYzKS0J6ogMxOm7ghlsYKN/nx33sUL7FXVyk7AnxutbIwSXQ8vyIhXLHYkRH1Lp3NHIkYuIbzdUYW4mSttFTvv4Ca2+b8ka0hW1ez6oKlDc9ItnXWF6hVvrC0tuGNqtz1jYcD952b9q97MBKux+P5Y6+YcWVXY48yHUh9og6Lmrt2ro9djNtXnuTl3TbavKsq0vc60VQrdbj8UaDb09AGy18UJ33hcDTIM+5VVGkanMf57as0OgX70dCtugP119vl4DqOHz6Uzd1VvI2pj/CwAA//9L/w3JNJ6cGwAAAABJRU5ErkJggg==\"\n}\n```\n\n#### grpc: validate captcha (secure)\n```\ngrpcurl -H 'x-api-key: 1ace3bed-3aaf-4642-adb1-d63aef85895f' -import-path pkg/proto/grpc-captcha -proto grpc-captcha.proto -d '{\"id\":\"acf26399-0aa3-4fea-89ef-495476315998\", \"code\": \"5485\"}' captcha.secure.nd:2222 werkstatt.captcha.CaptchaService.Verify |jq\n{}\n```\n\n#### common http routes (secure)\n```\nuse curl -k https://host... instead of curl host...\n```\n\n#### redis client with tls support (opt)\n```\ndocker run -it --rm --network host -v $(pwd)/.deploy/crt/ca.crt:/ca.crt -v $(pwd)/.deploy/crt/secure.nd.crt:/server.crt -v $(pwd)/.deploy/crt/secure.nd.key:/server.key redis:7.2-alpine redis-cli -p 6379 -a YQ3dvPx3fVzv --tls --cacert /ca.crt --cert /server.crt --key /server.key\n```\n\n#### render png\npaste data field value into \nhttps://onlinepngtools.com/convert-base64-to-png\n\n### DEV INFO\n\n#### design\n##### method CaptchaService.Generate(empty):\nGenerate new sequence code of [0-9] digits in quantity of `CAPTCHA_RENDER_DIG_CNT`, render png image `CAPTCHA_RENDER_WIDTH` x `CAPTCHA_RENDER_HEIGHT` px, store code sequence in redis db with TTL `CAPTCHA_RENDER_TTL` and return base64 encoding of image and uniqique captcha `id` to identify the sequence (`uuidv4`)\n\n##### method CaptchaService.Verify(id, code):\ncompare code sequences in payload and value stored in redis by provided key (`id`), if no such key ret `NotFound`, if values are not equal ret `FailedPrecondition`, if eq ret `OK` and remove key from redis\n\n#### compile and run on your host\n\n```\nmake \u0026\u0026 make run\n```\n\n#### install go-linter (linux, opt)\n```\ncurl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.1\n```\n\n#### run linter task (opt)\n```\nmake lint\n```\n\n#### run autotests (opt)\n```\nmake test\n```\n\n#### get full env vars list\n```\nmake env\n```\n\n#### health check router\n```\ncurl 0.0.0.0:1111/health/check\n```\n\n#### operable check router\n```\ncurl 0.0.0.0:1111/health/operable\n```\n\n#### prometheus metrics (runtime, http)\n```\ncurl 0.0.0.0:1111/metrics\n```\n\n\ndefine B = \ngo build -ldflags \"-s -w -X main.name=$(APP) -X main.version=$(RELEASE) -X main.compiledAt=$(BUILD_TIME)\" -o $(APP_OUT) $(APP_MAIN)\nendef","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgtsh77%2Fgrpc-captcha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgtsh77%2Fgrpc-captcha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgtsh77%2Fgrpc-captcha/lists"}