namespace fedem::sign {
struct ManifestData;
struct ManifestResult;
class Manifest;
}
Defined in <sign/Manifest.hh>. Link plugin-sign (needs OpenSSL).
A signed DSO carries two extra ELF sections:
| Section | Content |
|---|---|
.dso_manifest | UTF-8 JSON — the fields below |
.dso_sig | 64 raw bytes — the Ed25519 signature over the manifest JSON bytes |
Both are noload,readonly and added by dso-sign via objcopy.
ManifestData
struct ManifestData {
std::string name; // addon identifier
std::string version; // "1.2.0"
std::string author; // "Name <email>"
std::string sha256; // hex — SHA-256 of the DSO BEFORE the sections were added
std::string publicKeyId; // hex — SHA-256 of the signer's DER public key
int abiMajor = 0; // host-defined
int abiMinor = 0; // host-defined
std::string timestamp; // ISO-8601, e.g. "2026-09-08T12:00:00Z"
};
sha256 is computed over the file before signing. Verifier strips the two sections to a temp file, hashes that, and compares — so re-signing does not change the hash.
ManifestResult
struct ManifestResult {
bool hasManifest = false;
bool hasSig = false;
std::string manifestJson; // raw JSON
std::array<uint8_t,64> sig{}; // raw signature
ManifestData data; // parsed
std::string error; // non-empty on failure
};
Manifest — static functions
static ManifestResult read( std::string const& soPath );
static std::string toJson( ManifestData const& d );
static bool fromJson( std::string const& json,
ManifestData& out,
std::string& error );
read— memory-mapssoPath, walks the ELF section table by hand (no libelf), and returns the JSON, the raw signature, and the parsed fields.hasManifest/hasSigsay what was found;erroris set on I/O or parse failure.toJson— serialisesManifestDatato canonical JSON with a fixed key order.dso-signsigns the output of this, so verification must hash the same bytes.fromJson— parses JSON intoManifestData; returnsfalseand setserroron malformed input.
Reading a manifest without verifying
auto m = fedem::sign::Manifest::read( "libCircle.so" );
if( m.hasManifest ) {
std::cout << m.data.name << ' ' << m.data.version
<< " by " << m.data.author << '\n';
std::cout << "abi " << m.data.abiMajor << '.' << m.data.abiMinor << '\n';
}
This tells you what the DSO claims. It does not check the signature — use Verifier::verify for that.
Notes
- The section reader is ELF-only. That is the platform limit on the signing half of the toolkit (the loader itself is portable
dlopen). - Canonical JSON (fixed insertion order, from
toJson) is what makes the signature reproducible — do not hand-edit.dso_manifest.

