{"id":35203084,"url":"https://github.com/idthings/idengine","last_synced_at":"2026-04-25T15:36:01.112Z","repository":{"id":55445021,"uuid":"315133676","full_name":"idthings/idengine","owner":"idthings","description":"Open sourced project for the core engine used in idThings.","archived":false,"fork":false,"pushed_at":"2020-12-30T13:12:23.000Z","size":225,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2026-01-01T09:33:05.050Z","etag":null,"topics":["arduino","arduino-nano","containers","iot","iot-device","microservices","security","things"],"latest_commit_sha":null,"homepage":"https://idthings.io","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idthings.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}},"created_at":"2020-11-22T21:16:16.000Z","updated_at":"2023-04-03T05:02:31.000Z","dependencies_parsed_at":"2022-08-15T00:30:28.247Z","dependency_job_id":null,"html_url":"https://github.com/idthings/idengine","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/idthings/idengine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idthings%2Fidengine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idthings%2Fidengine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idthings%2Fidengine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idthings%2Fidengine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idthings","download_url":"https://codeload.github.com/idthings/idengine/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idthings%2Fidengine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32267710,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T09:15:33.318Z","status":"ssl_error","status_checked_at":"2026-04-25T09:15:31.997Z","response_time":59,"last_error":"SSL_read: 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":["arduino","arduino-nano","containers","iot","iot-device","microservices","security","things"],"created_at":"2025-12-29T12:36:39.841Z","updated_at":"2026-04-25T15:36:01.080Z","avatar_url":"https://github.com/idthings.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"### idEngine\nThe idEngine came about when I was developing an IoT product, and needed an way to deploy millions of identities (user id, secret) to devices.\nPrototyping with the Arduino Nano 33 IoT, it was clear there are significant logical security challenges in deploying credentials.\n\nThere is almost nothing secret on an IoT device, so factory installed credentials seems like the wrong approach.\nThe common case where a device is reset also raises the question, of whether a secret can be rotated safely?\n\nIn addition, there are significant scaling challenges to running a credential service running into the millions of accounts.\nThe keywords here, from an old infrastructure guy, are: simplicity, robustness, automation.\n\nMy approach is to treat an IoT device, and to a lesser extent a mobile app install, as simple a receptacle that can hold a credential.\nHowever, until a credential is deployed that device has no identity.\nResetting the device turns it back into a mere receptacle.\n\nidEngine currently supports either Redis (default) or HashiCorp Vault backends.\n\n### Project Goals\n* simplify the path to deploy best-practice for managing credentials\n* an easy to deploy, secure credential store\n* encourage the use of dynamic credentials and high-frequency secret rotation\n\n### Audience\n* IoT hackers and makers, who need easy to test and deploy credentials\n* Developers in a micro-service environment, who need a simple, fast, secure credential store\n* People interested in improving on the legacy user/password key-pair approach\n\n---\n\n### Quick Start\nTo get up and running quickly, use docker-compose to deploy idengine, Redis and Vault containers.\nVault is used as the backend datastore in this setup.\n```\n$ git clone git@github.com:idthings/idengine.git\nCloning into 'idengine'...\nremote: Enumerating objects: 77, done.\nReceiving objects: 100% (547/547), 194.27 KiB | 612.00 KiB/s, done.\nResolving deltas: 100% (257/257), done.\n$ cd idengine\n$ docker-compose up -d\nCreating network \"idengine_default\" with the default driver\nCreating idengine_idengine_1 ... done\nCreating idengine_redis_1    ... done\nCreating idengine_vault_1    ... done\n$\n$ docker ps --format \"{{.ID}}:\\t{{.Image}}\\t{{.Status}}\"\n7e2880096d42:\tthisdougb/idengine:latest\tUp 1 second\n870b7c2bcde2:\tvault:latest\tUp 1 second\ndbdfbd615920:\tredis:alpine\tUp 1 second\n$\n```\nAnd quick test, get a new identity that can now be authenticated:\n```\n$ curl localhost:8000/identities/new/\n{\"id\":\"30381b07-0bf8-4a93-9c6f-8e658690d090\",\"secret\":\"5kO0%9HTJmX%7\u0026d)VrC7\"}\n```\n\nTo stop the idengine environment:\n```\n$ docker-compose down\nStopping idengine_redis_1 ... done\nStopping idengine_vault_1 ... done\nRemoving idengine_redis_1    ... done\nRemoving idengine_vault_1    ... done\nRemoving idengine_idengine_1 ... done\nRemoving network idengine_default\n$\n```\n\n---\n\n### API Summary\n#### Get an identity: /identities/new/\nYour remote device or mobile app can obtain an identity, like this:\n```\n$ curl https://api.idthings.io/identities/new/\n{be39aaa1-3ab2-4855-9b13-d1bae9410baf,03Yg@\u00268F0OJM*6*@MDO0}\n```\n#### Authenticate a request: /identities/\u0026lt;guid\u0026gt;\nWhen remote devices send requests to your own API, they include an auth header (password or digest).\nYour API simply proxies this header to the idengine service for authentication.\n\nHere are simple password authentication examples, using the idEngine service at idThings.io:\n```\n$ curl -I https://api.idthings.io/identities/be39aaa1-3ab2-4855-9b13-d1bae9410baf \\\n    -H \"X-idThings-Password: 03Yg@\u00268F0OJM*6*@MDO0\"\nHTTP/1.1 200 OK\n\n$ curl -I https://api.idthings.io/identities/be39aaa1-3ab2-4855-9b13-d1bae9410baf \\\n    -H \"X-idThings-Password: wrong-password\"\nHTTP/1.1 401 Unauthorized\n```\nFor sentient devices it's a very short step to using HMAC digests to sign http requests to your API.\nThis means the device secret isn't transmitted with every call.\n```\n$ curl -I https://api.idthings.io/identities/be39aaa1-3ab2-4855-9b13-d1bae9410baf \\\n    -H \"X-idThings-Digest: HMAC-SHA256,c7fc567324b236e...,1604573826351,my device data\"\nHTTP/1.1 200 OK\n```\n#### Rotate secrets: /identities/rotate/\u0026lt;guid\u0026gt;\nYour remote device can rotate its own password, receiving a fresh one with this request:\n```\n$ curl https://api.idthings.io/identities/rotate/be39aaa1-3ab2-4855-9b13-d1bae9410baf \\\n    -H \"X-idThings-Password: 03Yg@\u00268F0OJM*6*@MDO0\"\n{be39aaa1-3ab2-4855-9b13-d1bae9410baf,WEN*86I9t3OUq0#))D4T}\n```\n#### Output formatting\nThe default format is intended to be easy to consume on lower powered IoT devices, running C-type languages.\nTypically these languages are string-challenged, so we try to make it as easy as possible.\nSearch your response stream for curly braces, and that's your data.\n\nHowever, when requesting new identities or rotating secrets, you can also specify the response in JSON format.\nIf that's what's easiest for your code.\n```\ncurl \"https://api.idthings.io/identities/new/?format=json\"\n{\"id\":\"18896661-e861-47a2-b724-629a07a4c67d\",\"secret\":\"#*P3ZO9F941L4C\u0026L#s%C\"}\n\ncurl https://api.idthings.io/identities/rotate/18896661-e861-47a2-b724-629a07a4c67d?format=json \\\n    -H \"x-idthings-password: #*P3ZO9F941L4C\u0026L#s%C\"\n{\"id\":\"18896661-e861-47a2-b724-629a07a4c67d\",\"secret\":\"m3GH7X5KCC#)0i(\u0026CaIO\"}\n```\n\n---\n\n### Computing Digests\nDigests are calculated by the message sender and recipient, and then compared.\nIn this way, the shared secret is not sent in the request (as is the case with password authentication).\n\nThe digest header has the following format (type,digest,timestamp,data):\n```\n\"X-idThings-Digest\": \"HMAC-SHA256,f62100c007ec7630a6d65c0d7d745dae5a21da5d8474722e6aa065c15b6ca9c0,1604573826351,my data\"\n```\nIn idEngine digests are valid for five minutes, so will be rejected as '401 Digest Expired'.\n#### HMAC-SHA256\nTo calculate an HMAC-256 digest:\n```\ntimestamp := time.Now().UnixNano() / 1e6         // convert to milliseconds\ntimestampStr := strconv.FormatInt(timestamp, 10) // convert to string type\n\nstringToSign := fmt.Sprintf(\"HMAC-SHA256,%s,%s,%s\", id, timestampStr, \"my data\")\n\nsigningKey := GenerateDigest(secret, timestampStr)\ndigest := GenerateDigest(signingKey, stringToSign)\n\ndigestHeader := fmt.Sprintf(\"HMAC-SHA256,%s,%s,%s\", digest, timestampStr, \"my data\")\n```\nAnd the GenerateDigest method:\n```\nfunc GenerateDigest(secret string, message string) string {\n\n\th := hmac.New(sha256.New, []byte(secret))\n\th.Write([]byte(message))\n\treturn hex.EncodeToString(h.Sum(nil))\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidthings%2Fidengine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidthings%2Fidengine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidthings%2Fidengine/lists"}