diff --git a/src/ASiC_S.cpp b/src/ASiC_S.cpp index ac64f9be3..95ddfa93e 100644 --- a/src/ASiC_S.cpp +++ b/src/ASiC_S.cpp @@ -21,10 +21,11 @@ #include "SignatureTST.h" #include "SignatureXAdES_LTA.h" +#include "crypto/Signer.h" +#include "util/algorithm.h" #include "util/File.h" #include "util/log.h" -#include #include using namespace digidoc; @@ -45,10 +46,6 @@ ASiC_S::ASiC_S(const string &path) : ASiContainer(MIMETYPE_ASIC_S) { auto z = load(path, false, {mediaType()}); - auto starts_with = [](string_view str, string_view needle) constexpr { - return str.size() >= needle.size() && str.compare(0, needle.size(), needle) == 0; - }; - for(const string &file: z.list()) { if(file == "mimetype") @@ -87,9 +84,21 @@ ASiC_S::ASiC_S(const string &path) THROW("ASiC-S container does not contain any signatures."); } -unique_ptr ASiC_S::createInternal(const string & /*path*/) +void ASiC_S::addDataFileChecks(const string &fileName, const string &mediaType) +{ + ASiContainer::addDataFileChecks(fileName, mediaType); + if(!dataFiles().empty()) + THROW("Can not add document to ASiC-S container which already contains a document."); +} + +unique_ptr ASiC_S::createInternal(const string &path) { - return {}; + if(!util::File::fileExtension(path, {"asics", "scs"})) + return {}; + DEBUG("ASiC_S::createInternal(%s)", path.c_str()); + auto doc = unique_ptr(new ASiC_S()); + doc->zpath(path); + return doc; } void ASiC_S::addAdESSignature(istream & /*signature*/) @@ -124,9 +133,13 @@ void ASiC_S::save(const ZipSerialize &s) s.addFile("META-INF/timestamp.tst", zproperty("META-INF/timestamp.tst"))(static_cast(list.front())->save()); } -Signature *ASiC_S::sign(Signer * /*signer*/) +Signature *ASiC_S::sign(Signer *signer) { - THROW("Not implemented."); + if(signer->profile() != ASIC_TST_PROFILE) + THROW("ASiC-S container supports only TimeStampToken signing."); + if(!signatures().empty()) + THROW("ASiC-S container supports only one TimeStampToken signature."); + return addSignature(make_unique(this, signer)); } /** diff --git a/src/ASiC_S.h b/src/ASiC_S.h index f6eba5a20..af32d5673 100644 --- a/src/ASiC_S.h +++ b/src/ASiC_S.h @@ -45,6 +45,7 @@ namespace digidoc ASiC_S(const std::string &path); DISABLE_COPY(ASiC_S); + void addDataFileChecks(const std::string &path, const std::string &mediaType) override; void canSave() final; void save(const ZipSerialize &s) final; diff --git a/src/SignatureTST.cpp b/src/SignatureTST.cpp index 75299a426..105ce8259 100644 --- a/src/SignatureTST.cpp +++ b/src/SignatureTST.cpp @@ -22,6 +22,7 @@ #include "ASiC_S.h" #include "DataFile_p.h" #include "crypto/Digest.h" +#include "crypto/Signer.h" #include "crypto/TS.h" #include "crypto/X509Cert.h" #include "util/DateTime.h" @@ -35,6 +36,15 @@ SignatureTST::SignatureTST(const string &data, ASiC_S *asicSDoc) , timestampToken(make_unique((const unsigned char*)data.data(), data.size())) {} +SignatureTST::SignatureTST(ASiC_S *asicSDoc, Signer *signer) + : asicSDoc(asicSDoc) +{ + auto *dataFile = static_cast(asicSDoc->dataFiles().front()); + Digest digest; + dataFile->digest(digest); + timestampToken = make_unique(digest, signer->userAgent()); +} + SignatureTST::~SignatureTST() = default; X509Cert SignatureTST::TimeStampCertificate() const diff --git a/src/SignatureTST.h b/src/SignatureTST.h index b70940207..a3cea7f49 100644 --- a/src/SignatureTST.h +++ b/src/SignatureTST.h @@ -32,6 +32,7 @@ class SignatureTST final: public Signature { public: SignatureTST(const std::string &data, ASiC_S *asicSDoc); + SignatureTST(ASiC_S *asicSDoc, Signer *signer); ~SignatureTST(); std::vector messageImprint() const override; diff --git a/src/crypto/Signer.cpp b/src/crypto/Signer.cpp index c95974ccf..b36a0e4c5 100644 --- a/src/crypto/Signer.cpp +++ b/src/crypto/Signer.cpp @@ -20,6 +20,7 @@ #include "Signer.h" #include "ASiC_E.h" +#include "ASiC_S.h" #include "Conf.h" #include "crypto/Digest.h" #include "crypto/X509Cert.h" @@ -38,7 +39,7 @@ class Signer::Private { public: optional method; - string profile = "time-stamp"; + string profile{ASiC_E::ASIC_TS_PROFILE}; string userAgent; string city, streetAddress, stateOrProvince, postalCode, countryName; vector signerRoles; @@ -181,9 +182,10 @@ void Signer::setProfile(const string &profile) {"TSA", ASiC_E::ASIC_TSA_PROFILE}, {ASiC_E::ASIC_TS_PROFILE, ASiC_E::ASIC_TS_PROFILE}, {ASiC_E::ASIC_TSA_PROFILE, ASiC_E::ASIC_TSA_PROFILE}, + {ASiC_S::ASIC_TST_PROFILE, ASiC_S::ASIC_TST_PROFILE}, + {"time-stamp-token", ASiC_S::ASIC_TST_PROFILE} }; - if(auto it = std::find_if(profiles.cbegin(), profiles.cend(), [&profile](const auto &elem) { return elem.first == profile; }); - it != profiles.cend()) + if(auto it = profiles.find(profile); it != profiles.cend()) d->profile = it->second; else THROW("Unsupported profile: %s", profile.c_str()); diff --git a/src/digidoc-tool.1.cmake b/src/digidoc-tool.1.cmake index 94c9356fe..edd974c84 100644 --- a/src/digidoc-tool.1.cmake +++ b/src/digidoc-tool.1.cmake @@ -49,7 +49,7 @@ Command websign: Command sign: Example: digidoc-tool sign demo-container.asice Available options: - --profile= - signature profile, TS, TSA, time-stamp, time-stamp-archive + --profile= - signature profile, TS, TSA, time-stamp, time-stamp-archive, TimeStampToken, time-stamp-token --XAdESEN - use XAdES EN profile --city= - city of production place --street= - streetAddress of production place in XAdES EN profile diff --git a/src/digidoc-tool.cpp b/src/digidoc-tool.cpp index 16f05b6e0..0b01151f4 100644 --- a/src/digidoc-tool.cpp +++ b/src/digidoc-tool.cpp @@ -350,7 +350,7 @@ static int printUsage(const char *executable) << " Command sign:" << endl << " Example: " << executable << " sign demo-container.asice" << endl << " Available options:" << endl - << " --profile= - signature profile, TS, TSA, time-stamp, time-stamp-archive" << endl + << " --profile= - signature profile, TS, TSA, time-stamp, time-stamp-archive, TimeStampToken, time-stamp-token" << endl << " --XAdESEN - use XAdES EN profile" << endl << " --city= - city of production place" << endl << " --street= - streetAddress of production place in XAdES EN profile" << endl