{"id":17717297,"url":"https://github.com/bwesterb/go-atum","last_synced_at":"2025-07-08T04:35:27.564Z","repository":{"id":57492393,"uuid":"122643426","full_name":"bwesterb/go-atum","owner":"bwesterb","description":"Go client for the post-quantum Atum time-stamping service","archived":false,"fork":false,"pushed_at":"2023-12-18T22:44:55.000Z","size":63,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-06-19T05:53:44.221Z","etag":null,"topics":["ed25519","golang","post-quantum","trusted-timestamping","xmss","xmssmt"],"latest_commit_sha":null,"homepage":null,"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/bwesterb.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":"2018-02-23T16:11:41.000Z","updated_at":"2024-06-19T05:53:44.222Z","dependencies_parsed_at":"2024-10-25T17:12:27.405Z","dependency_job_id":"94031ff2-b6c6-4f38-b4ec-4891ddb22255","html_url":"https://github.com/bwesterb/go-atum","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bwesterb%2Fgo-atum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bwesterb%2Fgo-atum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bwesterb%2Fgo-atum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bwesterb%2Fgo-atum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bwesterb","download_url":"https://codeload.github.com/bwesterb/go-atum/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243511644,"owners_count":20302592,"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":["ed25519","golang","post-quantum","trusted-timestamping","xmss","xmssmt"],"created_at":"2024-10-25T14:19:44.668Z","updated_at":"2025-03-14T02:31:10.588Z","avatar_url":"https://github.com/bwesterb.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"go-atum\n=======\n\nGo client (and CLI tool) to the [Atum trusted timestamping server](\n    https://github.com/bwesterb/atumd).\nSo, why use Atum instead of [RFC 3161](https://tools.ietf.org/html/rfc3161)\n    or [ANSI ASC X9.95](https://en.wikipedia.org/wiki/ANSI_ASC_X9.95_Standard)?\n\n 1.  Atum timestamps use [XMSSMT hash-based signatures](\n     https://datatracker.ietf.org/doc/draft-irtf-cfrg-xmss-hash-based-signatures/)\n     by default, which are safe, even against an adversary with\n     a large quantum computer.\n 2.  Atum has a simple REST/json based API.  See below.\n\nGo example\n----------\nTo create a timestamp on some nonce, run\n\n```go\ntsBytes, err := atum.JsonStamp(\"https://some.atum/server\", someNonce)\n```\n\nThis returns a Json encoded version of the timestamp.\nTo check whether this timestamp is valid, run\n\n```go\nvalid, time, tsServer, _ := atum.Verify(tsBytes, nonce)\n```\n\nAs anyone can run their own Atum server, you should check whether you\nshould trust the Atum server that signed the timestamp (`tsServer` in the\nexample above).\n\nBy default, the Atum server issues XMSSMT signatures, which are somewhat large\nin size. To request an Ed25519 signature, which is smaller, but not safe\nagainst an attacker with a quantum computer, use\n\n```go\nalg := atum.Ed25519\nts, err := atum.SendRequest(\"https://some.atum/server\",\n                    atum.Request{\n                        Nonce: someNonce,\n                        PreferredSigAlg: \u0026alg\n                    })\n```\n\nThe `ts` is an `*atum.Timestamp`, which can be serialized using\n`ts.MarshalText()` or simply `json.Marshal(ts)`.\n\nFor further documentation, see [godoc](\n    https://godoc.org/github.com/bwesterb/go-atum).\n\n\nCommandline tool\n----------------\n\nTo create a timestamp on a file `some-document` (with a default Atum server),\nrun:\n\n```\natum stamp -f some-document\n```\n\nThis will create an `some-document.atum-timestamp` file.\n\nTo check the timestamp, run\n\n```\natum verify -f some-document\n```\n\nThis will tell whether the timestamp is valid and by which server it was set.\nLike before, anyone can set up an Atum server, so you should check whether\nyou trust the Atum server which set the timestamp.\n\nTo check for a specific server, run\n\n```\natum verify -f some-document -S https://some.atum/server\n```\n\nThis will fail if the document is not signed by that specific Atum server.\n\nSee `atum -h` for more options.\n\nServer\n------\n\nWant to run your own Atum server?  Check out [atumd](\n    https://github.com/bwesterb/atumd).\n\nProtocol\n--------\n\nAn Atum server is a webservice and is identified by the url it runs at.  An example of an Atum server is\n\n    https://keyshare.privacybydesign.foundation/atumd\n    \n### Request a timestamp\n\nTo request a timestamp for the nonce `example nonce`, simply POST\n\n```json\n{\"Nonce\": \"ZXhhbXBsZSB0b2tlbg==\"}\n```\n\nto the Atum server url.  If everything is fine, the server will respond with\n\n```\n{\n \"Error\": null,\n \"Stamp\": (the json encoded Atum timestamp),\n \"Info\": null\n}\n```\n\nIf there is a problem, the `Error` field will be one `missing nonce`,\n`nonce is too long`, `proof of work is missing`,\n`proof of work is invalid` or `too much lag`. Also, if helpful, the\n`Info` field will include the server information, see below.\n\n### Atum timestamp for a nonce\n\nAn example of a (json encoded) Atum timestamp (for the nonce `example nonce`) is\n\n```json\n{\n \"Time\": 1520078016,\n \"ServerUrl\": \"https://metrics.privacybydesign.foundation/atum\",\n \"Sig\": {\n  \"Alg\":\"ed25519\",\n  \"Data\":\"L6Pig67OOXI01YuY8798o3F8RA6ehVI2UFc+wa2X4uOu9f6SrfkATb6ZexUKj8HfrHYTn2fK9Xna9rGAFYyWDg==\",\n  \"PublicKey\":\"e/nMAJF7nwrvNZRpuJljNpRx+CsT7caaXyn9OX683R8=\"\n}\n```\n\n* `Time` contains the [unix time](https://en.wikipedia.org/wiki/Unix_time)\n   when the stamp was set.  In this case march 3rd, 2018 at 11:53:36 UTC.\n* `ServerUrl` contains the url of the server which set the timestamp.\n* `Alg` is the signature algorithm used.  Either `ed25519` or `xmssmt`.\n* `PublicKey` contains the base64 encoded public key of the private\n   key which was used to create the signature.\n* `Data` contains a base64 encoded [Ed25519](https://ed25519.cr.yp.to)\n   or [XMSSMT](https://datatracker.ietf.org/doc/draft-irtf-cfrg-xmss-hash-based-signatures/)\n   signature of the unix time (uint64, encoded big endian) concatenated\n   with the nonce.\n\nNote that the timestamp does not include the nonce itself.\nTo check a timestamp, one verifies the signature, but also should verify\nthat the public key belongs to the Atum server.  More on this later.\n\n### Server information\n\nA GET request to the url of the Atum server, will return a Json object like\n\n```json\n{\n \"MaxNonceSize\": 128,\n \"AcceptableLag\": 60,\n \"DefaultSigAlg\": \"xmssmt\",\n \"RequiredProofOfWork\": {\n   \"xmssmt\": \"sha2bday-16-T3oAQ2oV2VIdO5LqOLyrCsOEOr+86AhOyRnR37Vja8I\"\n }\n}\n```\n\n* `MaxNonceSize` is the maximum size of a nonce in bytes which the Atum\n  server will sign.\n* `AcceptableLag` is the largest difference in seconds the Atum server\n  will accept between the requested time for a timestamp and the actual time.\n* `DefaultSigAlg` is the default signature algorithm used.  See below.\n* `RequiredProofOfWork` is a map that lists for which signature algorithms\n  what [go-pow proof of work](https://github.com/bwesterb/go-pow)\n  the server requires (if any).\n\nThis is the same Json object that might appear in `Info` field\nin the response to a timestamp POST request.\n\n### Optional request fields\n\nA timestamp request (which is POSTed to the server url) may contain the\nfollowing optional fields.\n\n* `PreferredSigAlg` to specify which kind of signature is preferred.\n* `Time` to request the time on the timestamp.  This can't differ too much\n  from the actual local time (as dictated by `AcceptableLag`).\n\nFor instance, this requests an `ed25519` signature for the UNIX time 1520078016.\n\n```json\n{\n \"Nonce\": \"ZXhhbXBsZSB0b2tlbg==\",\n \"Time\": 1520078016,\n \"PreferredSigAlg\": \"ed25519\"\n}\n```\n\n### Proof of work\n\nThe server can be configured to require a proof of work before it will create\na timestamp with a certain signature scheme.  By default, `ed25519` does not\nrequire a proof of work, but `xmssmt` does.\n\nThe [go-pow proof of work](https://github.com/bwesterb/go-pow) request is\ncontained in the server information and changes, by default, daily.\nTo fulfil the proof of work, the message that is to be signed for the timestamp\n(uint64 unix time concatenated with the nonce) must be used as bound data.\nThis also means that `Time` should be specified in the request.\nThe resulting proof is put in the `ProofOfWork` field of the POSTed request.\n\nAn example for the PoW-request `sha2bday-16-T3oAQ2oV2VIdO5LqOLyrCsOEOr+86AhOyRnR37Vja8I` is\n\n```json\n{\n \"Nonce\":\"4ihcK00BmuSQloyRH1kTrJ1/dfmSN5VkNSlDwEl+S+Lyxa2sfzg+t3v7pW6XhYZ8OBsblWgR+byLujVlnVNhpA==\",\n \"ProofOfWork\":\"AAAAAAAAAWIAAAAAAAACmwAAAAAAAAZh\",\n \"Time\":1520081097\n}\n```\n\n### Atum timestamp of a file (or longer message)\n\nTo timestamp  a file (which is too long to be a nonce), a hash is used.\nAn example of an Atum timestamp on an [old versionof this README](\nhttps://github.com/bwesterb/go-atum/blob/55050e92e28492a76c8b29aff4c94dae4621721b/README.md)\nis\n\n```json\n{\n \"Time\": 1520081260,\n \"ServerUrl\": \"https://metrics.privacybydesign.foundation/atum\",\n \"Sig\": {\n   \"Alg\": \"ed25519\",\n   \"Data\": \"G/HCNLL/ZGkonGcDX4eIMysPw5Pw49vCsQ3wuFbo4dBd81HG8EGfwBsYBfPFCwyudrOW0jTxbNhcGvQG52VHDA==\",\n   \"PublicKey\":\"e/nMAJF7nwrvNZRpuJljNpRx+CsT7caaXyn9OX683R8=\"\n },\n \"Hashing\": {\n  \"Hash\": \"shake256\",\n  \"Prefix\": \"3hGOzeS3h/Wm9FKa8RbXvrdHNqk/N1ZzFKDdnSpdoqg=\"\n }\n}\n```\n\nThe nonce is computed by hashing the base64-decoded `Prefix` and then the file.\nCurrently only `shake256` is supported, which is\n[SHA3's SHAKE-256](https://en.wikipedia.org/wiki/SHA-3)\nwhere a 64-byte nonce is extracted.\n\n### Lookup a public key\n\nTo verify an Atum timestamp, a client must check whether the public key\nis valid for the given Atum server.  To do this, she sends a GET request\nwith query parameters `alg` for the algorithm and `pk` for the hex encoded\npublic key to `\u003cserver url\u003e/checkPublicKey`.  For example, a GET to\n\n    https://metrics.privacybydesign.foundation/atum/checkPublicKey?alg=ed25519\u0026pk=7bf9cc00917b9f0aef359469b89963369471f82b13edc69a5f29fd397ebcdd1f\n\nreturned\n\n```json\n{\n \"Trusted\": true,\n \"Expires\": \"2018-04-02T14:59:06.164300986+02:00\"\n}\n```\n\nbut\n\n    https://metrics.privacybydesign.foundation/atum/checkPublicKey?alg=ed25519\u0026pk=7b\n\nwould return\n\n```json\n{\n \"Trusted\": false,\n \"Expires\": \"2018-04-02T14:59:06.164300986+02:00\"\n}\n```\n\nThe `Expires` field contains the time after which the client should check back\nwith the server whether the public key is still trusted.\n\nOther remarks\n-------------\n\n1. **Trusted server.**\n   Anyone can run an Atum server, which might or might not be honest.\n   It is not sufficient to check that an Atum timestamp is valid: you should\n   ensture that you trust the Atum server by which it was set.\n2. **`xmssmt` or `ed25519`**\n   The `ed25519` signatures are significantly smaller (0.4kB versus 2kB\n   for `XMSSMT-SHA2_40/2_512`) and faster to create and verify.\n   `xmssmt` is still very fast, it takes approximately 5ms to create or\n   verify a signature for `XMSSMT-SHA2_40/2_512`.\n   The big difference is that `ed25519` is easily broken by someone in\n   possesion of a moderately sized quantum computer, which we are likely\n   to see within the next 50 years.  On the other hand, it seems very\n   unlikely that `XMSSMT-SHA2_40/2_512` will be broken in the forseeable\n   future.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbwesterb%2Fgo-atum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbwesterb%2Fgo-atum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbwesterb%2Fgo-atum/lists"}