diff --git a/cdoc/CDoc.h b/cdoc/CDoc.h index 960f4727..2249c79f 100644 --- a/cdoc/CDoc.h +++ b/cdoc/CDoc.h @@ -183,6 +183,41 @@ struct FileInfo { int64_t size; }; +#ifdef VERSION +#undef VERSION +#endif + +namespace CDoc2 { +namespace Label { + /** + * @brief Recipient types for machine-readable labels + * + */ + static constexpr std::string_view TYPE_PASSWORD = "pw"; + static constexpr std::string_view TYPE_SYMMETRIC = "secret"; + static constexpr std::string_view TYPE_PUBLIC_KEY = "pub_key"; + static constexpr std::string_view TYPE_CERTIFICATE = "cert"; + static constexpr std::string_view TYPE_UNKNOWN = "Unknown"; + static constexpr std::string_view TYPE_ID_CARD = "ID-card"; + static constexpr std::string_view TYPE_DIGI_ID = "Digi-ID"; + static constexpr std::string_view TYPE_DIGI_ID_E_RESIDENT = "Digi-ID E-RESIDENT"; + + /** + * @brief Recipient data for machine-readable labels + * + */ + static constexpr std::string_view VERSION = "v"; + static constexpr std::string_view TYPE = "type"; + static constexpr std::string_view FILE = "file"; + static constexpr std::string_view LABEL = "label"; + static constexpr std::string_view CN = "cn"; + static constexpr std::string_view SERIAL_NUMBER = "serial_number"; + static constexpr std::string_view LAST_NAME = "last_name"; + static constexpr std::string_view FIRST_NAME = "first_name"; + static constexpr std::string_view CERT_SHA1 = "cert_sha1"; +} +} + }; // namespace libcdoc #endif // CDOC_H diff --git a/cdoc/CDoc2.h b/cdoc/CDoc2.h index ce3813cc..009a61d9 100644 --- a/cdoc/CDoc2.h +++ b/cdoc/CDoc2.h @@ -19,6 +19,8 @@ #ifndef __CDOC2_H__ #define __CDOC2_H__ +#include "CDoc.h" + #include namespace libcdoc { @@ -57,10 +59,10 @@ constexpr std::string_view LABELBASE64IND{";base64,"}; * @brief EID type values for machine-readable label */ static constexpr std::string_view eid_strs[] = { - "Unknown", - "ID-card", - "Digi-ID", - "Digi-ID E-RESIDENT" + CDoc2::Label::TYPE_UNKNOWN, + CDoc2::Label::TYPE_ID_CARD, + CDoc2::Label::TYPE_DIGI_ID, + CDoc2::Label::TYPE_DIGI_ID_E_RESIDENT }; } // namespace CDoc2 diff --git a/cdoc/CDoc2Reader.cpp b/cdoc/CDoc2Reader.cpp index 478e51ab..4e9b1199 100644 --- a/cdoc/CDoc2Reader.cpp +++ b/cdoc/CDoc2Reader.cpp @@ -630,7 +630,6 @@ CDoc2Reader::CDoc2Reader(libcdoc::DataSource *src, bool take_ownership) LOG_ERROR("{}", last_error); return; } - //if (libcdoc::CDoc2::LABEL.compare(0, libcdoc::CDoc2::LABEL.size(), (const char *) in)) return; // Read 32-bit header length in big endian order uint8_t c[4]; diff --git a/cdoc/Recipient.cpp b/cdoc/Recipient.cpp index 3459f41d..1e70fa78 100644 --- a/cdoc/Recipient.cpp +++ b/cdoc/Recipient.cpp @@ -121,60 +121,44 @@ Recipient::isTheSameRecipient(const std::vector& public_key) const } static void -buildLabel(std::ostream& ofs, std::string_view type, std::initializer_list> components) +buildLabel(std::ostream& ofs, std::string_view type, const std::map lbl_parts, std::initializer_list> extra) { + auto parts = lbl_parts; + if (parts.contains("v")) + parts.erase("v"); + if (parts.contains("type")) + parts.erase("type"); + for (const auto& [key, value] : extra) { + if (!value.empty()) + parts[key] = value; + } ofs << CDoc2::LABELPREFIX; - ofs << "v" << '=' << std::to_string(CDoc2::KEYLABELVERSION) << '&' - << "type" << '=' << type; - for (const auto& [key, value] : components) { + ofs << CDoc2::Label::VERSION << '=' << std::to_string(CDoc2::KEYLABELVERSION) << '&' + << CDoc2::Label::TYPE << '=' << type; + for (const auto& [key, value] : parts) { if (!value.empty()) ofs << '&' << urlEncode(key) << '=' << urlEncode(value); } } static void -BuildLabelEID(std::ostream& ofs, Certificate::EIDType type, const Certificate& x509) -{ - buildLabel(ofs, CDoc2::eid_strs[type], { - {"cn", x509.getCommonName()}, - {"serial_number", x509.getSerialNumber()}, - {"last_name", x509.getSurname()}, - {"first_name", x509.getGivenName()}, - }); -} - -static void -BuildLabelCertificate(std::ostream &ofs, const std::string& file, const Certificate& x509) +BuildLabelEID(std::ostream& ofs, Certificate::EIDType type, const Certificate& x509, const std::map& lbl_parts) { - buildLabel(ofs, "cert", { - {"file", file}, - {"cn", x509.getCommonName()}, - {"cert_sha1", toHex(x509.getDigest())} + + buildLabel(ofs, CDoc2::eid_strs[type], lbl_parts, { + {CDoc2::Label::CN, x509.getCommonName()}, + {CDoc2::Label::SERIAL_NUMBER, x509.getSerialNumber()}, + {CDoc2::Label::LAST_NAME, x509.getSurname()}, + {CDoc2::Label::FIRST_NAME, x509.getGivenName()}, }); } static void -BuildLabelPublicKey(std::ostream &ofs, const std::string& file) +BuildLabelCertificate(std::ostream &ofs, const Certificate& x509, const std::map& lbl_parts) { - buildLabel(ofs, "pub_key", { - {"file", file} - }); -} - -static void -BuildLabelSymmetricKey(std::ostream &ofs, const std::string& label, const std::string& file) -{ - buildLabel(ofs, "secret", { - {"label", label}, - {"file", file} - }); -} - -static void -BuildLabelPassword(std::ostream &ofs, const std::string& label) -{ - buildLabel(ofs, "pw", { - {"label", label} + buildLabel(ofs, CDoc2::Label::TYPE_CERTIFICATE, lbl_parts, { + {CDoc2::Label::CN, x509.getCommonName()}, + {CDoc2::Label::CERT_SHA1, toHex(x509.getDigest())} }); } @@ -183,6 +167,15 @@ Recipient::getLabel(const std::vector parts; + for (const auto& [key, value] : lbl_parts) { + if (!value.empty()) + parts[key] = value; + } + for (const auto& [key, value] : extra) { + if (!value.empty()) + parts[key] = value; + } std::ostringstream ofs; switch(type) { case NONE: @@ -190,30 +183,26 @@ Recipient::getLabel(const std::vector 0) { - BuildLabelPassword(ofs, key_name); + buildLabel(ofs, CDoc2::Label::TYPE_PASSWORD, parts, {}); } else { - BuildLabelSymmetricKey(ofs, key_name, file_name); + buildLabel(ofs, CDoc2::Label::TYPE_SYMMETRIC, parts, {}); } break; case PUBLIC_KEY: if (!cert.empty()) { Certificate x509(cert); if (auto eid = x509.getEIDType(); eid != Certificate::Unknown) { - BuildLabelEID(ofs, eid, x509); + BuildLabelEID(ofs, eid, x509, parts); } else { - BuildLabelCertificate(ofs, file_name, x509); + BuildLabelCertificate(ofs, x509, parts); } } else { - BuildLabelPublicKey(ofs, file_name); + buildLabel(ofs, CDoc2::Label::TYPE_PUBLIC_KEY, parts, {}); } break; case KEYSHARE: break; } - for (const auto& [key, value] : extra) { - if (!value.empty()) - ofs << '&' << urlEncode(key) << '=' << urlEncode(value); - } LOG_DBG("Generated label: {}", ofs.str()); return ofs.str(); } diff --git a/cdoc/Recipient.h b/cdoc/Recipient.h index 50aac040..bc50d944 100644 --- a/cdoc/Recipient.h +++ b/cdoc/Recipient.h @@ -23,6 +23,7 @@ #include #include +#include #include namespace libcdoc { @@ -108,16 +109,6 @@ struct CDOC_EXPORT Recipient { * */ uint64_t expiry_ts = 0; - /** - * @brief key/certificate filename for machine-readable label - * - */ - std::string file_name; - /** - * @brief public key/password name for machine-readable label - * - */ - std::string key_name; /** * @brief test whether the Recipient structure is initialized @@ -234,9 +225,25 @@ struct CDOC_EXPORT Recipient { */ std::string getLabel(const std::vector> &extra) const; + /** + * @brief Set a property for automatic label generation + * + * @param key the property name + * @param value the property value + */ + void setLabelValue(std::string_view key, std::string_view value) { + if (!value.empty()) { + lbl_parts[std::string(key)] = value; + } else { + lbl_parts.erase(std::string(key)); + } + } + bool operator== (const Recipient& other) const = default; protected: Recipient(Type _type) : type(_type) {}; +private: + std::map lbl_parts; }; } // namespace libcdoc diff --git a/libcdoc.i b/libcdoc.i index b25531ac..b34b421a 100644 --- a/libcdoc.i +++ b/libcdoc.i @@ -51,6 +51,9 @@ %ignore libcdoc::FileListConsumer; %ignore libcdoc::FileListSource; +// Ignore until there is straightfoward string_view translation +%ignore libcdoc::CDoc2; + %ignore libcdoc::CDocWriter::createWriter(int version, DataConsumer *dst, bool take_ownership, Configuration *conf, CryptoBackend *crypto, NetworkBackend *network); %ignore libcdoc::CDocWriter::createWriter(int version, std::ostream& ofs, Configuration *conf, CryptoBackend *crypto, NetworkBackend *network); %ignore libcdoc::CDocWriter::encrypt(MultiDataSource& src, const std::vector& recipients);