| Crates.io | sigserlic |
| lib.rs | sigserlic |
| version | 0.2.0 |
| created_at | 2024-12-28 12:49:33.245905+00 |
| updated_at | 2025-04-30 19:55:21.934093+00 |
| description | Combine serde with signify |
| homepage | |
| repository | https://github.com/deadbaed/sigserlic |
| max_upload_size | |
| id | 1497446 |
| size | 117,987 |
The signify serde license system.
Rust library to combine serde with libsignify. Based on openbsd signify.
My goal is to have some kind of licensing system for a project I am working on.
I was always wondering how a licensing sytem was working, and from time to time I was reading some articles on the subject, but I never had the time and need to implement that, until now!
Having the prior experience of coding an auth service with JWTs I tried pasetors, a Rust implementation of paseto. It worked pretty well and I liked the format, but paseto is for signing short-lived access tokens, and I am not doing that. (in retrospect paseto can be used for long-lived tokens, and I could have used paseto for this licensing system)
I got a link (thanks Lara!) to this excellent blog post, it is a great read! It gave me some ideas for my licensing system.
I originally wanted to use minisign, but the Rust implementations did not suit me, even though I prefer minisign over signify.
After learning that minisign was compatible at some point with signify, I read the paper introducing signify, discovered the portable version of openbsd's signify, and finally landed on libsignify!
My only problem with signify is that it is too basic: you can only sign/verify files and that's it (which is actually good, less is more).
I want to sign some data programatically, and also access that data programatically, not just whole files.
Also, I am not a huge fan of have the signature and the signed data in two different places, why not combine them in a single place?
Once you have generated keys/signatures, use the power of serde to pass your data anywhere!
For simplicity, these samples will be serialized in json.
Comments and expiration are optional if you do not have a need for them.
{
"secret_key": "RWRCSwAAAADSJSpBLNHNIzTs0FMnX7paPcnmr795lupZeb8cfPFAOqtZeVxFArUaQirh3mbooWQkKXzG8pxBJ9Phf24z0b1QYYp6GWtCHbEYK7PUbXVsv6tU4lS3MH5sylrYLGdOcRs=",
"created_at": "2024-12-24T15:02:48.845298Z",
"expired_at": null,
"comment": "testing key, do not use"
}
{
"public_key": "RWRZeb8cfPFAOmGKehlrQh2xGCuz1G11bL+rVOJUtzB+bMpa2CxnTnEb",
"created_at": "2024-12-24T15:02:48.845298Z",
"expired_at": null,
"comment": "testing key, do not use"
}
{
"signed_artifact": {
"data": {
"string": "Toto mange du gateau",
"bytes": [
222,
173,
186,
237
],
"int": -1,
"boolean": true
},
"timestamp": "2024-12-27T14:59:30Z",
"expiration": "2024-12-28T14:59:30Z"
},
"signature": "RWRZeb8cfPFAOrlQsaAKcOTnSpCwkqzVsQRb2gZ4IAkvlwQwWBOts3bUbZ8+pNJHPuZXSEMuUPua+FuLkrpteTeh1DiGSoORUAg=",
"comment": "anybody can change me :)"
}
The struct holding data is this:
struct MyData {
string: String,
bytes: Vec<u8>,
int: i32,
boolean: bool,
}
When deserializing a signature, you need to use the same structure you used for the serialization, otherwise deserialization will fail.
My usage of this crate is in a setup like this:
"Signing authority"
┌───────────────────────────────────────────┐
│ │
│ - Key management: generation, rotation │
│ │
┌────┼─── Sign data: produce signatures │
│ │ │
Transfer │ └───────────────────────────────────────────┘
over the │
internet │ ┌──────────────────────────────────┐
│ │ │
└────► - Verify signatures + validity │
│ │
│ - Use data if authentic │
│ │
└──────────────────────────────────┘
"Signature consumer"
Both the authority and consumer are going to use the same crate, meaning there is no built-in versionning. But it should be easy to do it yourself.
Key rotation can be pretty simple to do: with an existing key a:
bab for verifying signaturesba for verifying signatures.When implementating a key rotation system, do not forget what should happen for existing signatures from signing key a:
b?MIT