aboutsummaryrefslogtreecommitdiff
path: root/bpkg
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2016-04-29 10:07:03 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2016-05-04 20:37:44 +0300
commit057a5d5d435d53166d1b8751748a9ba0a317bee3 (patch)
tree6770b5ba1566c95e79ad73e845ac4a04c145cbec /bpkg
parentd61e9338c8eda118c5f2afd93827be4a84bdc36a (diff)
Add signature_manifest class
Diffstat (limited to 'bpkg')
-rw-r--r--bpkg/manifest33
-rw-r--r--bpkg/manifest.cxx96
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.
+ }
}