diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2016-04-29 10:07:03 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2016-05-04 20:37:44 +0300 |
commit | 057a5d5d435d53166d1b8751748a9ba0a317bee3 (patch) | |
tree | 6770b5ba1566c95e79ad73e845ac4a04c145cbec /bpkg | |
parent | d61e9338c8eda118c5f2afd93827be4a84bdc36a (diff) |
Add signature_manifest class
Diffstat (limited to 'bpkg')
-rw-r--r-- | bpkg/manifest | 33 | ||||
-rw-r--r-- | bpkg/manifest.cxx | 96 |
2 files changed, 128 insertions, 1 deletions
diff --git a/bpkg/manifest b/bpkg/manifest index d55e714..0c9362f 100644 --- a/bpkg/manifest +++ b/bpkg/manifest @@ -588,6 +588,39 @@ namespace bpkg void serialize (manifest_serializer&) const; }; + + class signature_manifest + { + public: + // Checksum of the corresponding package_manifests. + // + std::string sha256sum; + + // Signature of the corresponding package_manifests. Calculated by + // encrypting package_manifests checksum (stored in sha256sum) with the + // repository certificate private key. + // + std::vector<char> signature; + + public: + signature_manifest () = default; + signature_manifest (manifest_parser&, bool ignore_unknown = false); + + // Serialize sha256sum and base64-encoded representation of the signature. + // + void + serialize (manifest_serializer&) const; + + private: + // Used for delegating in public constructor. Strictly speaking is not + // required, as a signature_manifest currently never appears as a part of + // a manifest list, but kept for the consistency with other manifests + // implementations. + // + signature_manifest (manifest_parser&, + manifest_name_value start, + bool ignore_unknown); + }; } #endif // BPKG_MANIFEST diff --git a/bpkg/manifest.cxx b/bpkg/manifest.cxx index b94c2c6..ff1c88f 100644 --- a/bpkg/manifest.cxx +++ b/bpkg/manifest.cxx @@ -18,6 +18,7 @@ #include <stdexcept> // invalid_argument #include <butl/path> +#include <butl/base64> #include <bpkg/manifest-parser> #include <bpkg/manifest-serializer> @@ -1197,7 +1198,7 @@ namespace bpkg { // @@ Should we check that all non-optional values are specified ? // @@ Should we check that values are valid: name is not empty, version - // release is not empty, sha256sum is a proper string, ... + // release is not empty, sha256sum is a proper string, ...? // @@ Currently we don't know if we are serializing the individual package // manifest or the package list manifest, so can't ensure all values // allowed in the current context (location, sha256sum, *-file values). @@ -2072,4 +2073,97 @@ namespace bpkg s.next ("", ""); // End of stream. } + + // signature_manifest + // + signature_manifest:: + signature_manifest (parser& p, bool iu) + : signature_manifest (p, p.next (), iu) // Delegate + { + // Make sure this is the end. + // + name_value nv (p.next ()); + if (!nv.empty ()) + throw parsing (p.name (), nv.name_line, nv.name_column, + "single signature manifest expected"); + } + + signature_manifest:: + signature_manifest (parser& p, name_value nv, bool iu) + { + auto bad_name ([&p, &nv](const string& d) { + throw parsing (p.name (), nv.name_line, nv.name_column, d);}); + + auto bad_value ([&p, &nv](const string& d) { + throw parsing (p.name (), nv.value_line, nv.value_column, d);}); + + // Make sure this is the start and we support the version. + // + if (!nv.name.empty ()) + bad_name ("start of signature manifest expected"); + + if (nv.value != "1") + bad_value ("unsupported format version"); + + for (nv = p.next (); !nv.empty (); nv = p.next ()) + { + string& n (nv.name); + string& v (nv.value); + + if (n == "sha256sum") + { + if (!sha256sum.empty ()) + bad_name ("sha256sum redefinition"); + + if (v.empty ()) + bad_value ("empty sha256sum"); + + if (!valid_sha256 (v)) + bad_value ("invalid sha256sum"); + + sha256sum = move (v); + } + else if (n == "signature") + { + if (!signature.empty ()) + bad_name ("signature redefinition"); + + if (v.empty ()) + bad_value ("empty signature"); + + // Try to base64-decode as a sanity check. + // + try + { + signature = base64_decode (v); + } + catch (const invalid_argument&) + { + bad_value ("invalid signature"); + } + } + else if (!iu) + bad_name ("unknown name '" + n + "' in signature manifest"); + } + + // Verify all non-optional values were specified. + // + if (sha256sum.empty ()) + bad_value ("no sha256sum specified"); + else if (signature.empty ()) + bad_value ("no signature specified"); + } + + void signature_manifest:: + serialize (serializer& s) const + { + // @@ Should we check that values are valid ? + // + s.next ("", "1"); // Start of manifest. + + s.next ("sha256sum", sha256sum); + s.next ("signature", base64_encode (signature)); + + s.next ("", ""); // End of manifest. + } } |