20
20
#include " SignatureTST.h"
21
21
22
22
#include " ASiC_S.h"
23
+ #include " Conf.h"
23
24
#include " DataFile_p.h"
25
+ #include " XMLDocument.h"
24
26
#include " crypto/Digest.h"
25
27
#include " crypto/Signer.h"
26
28
#include " crypto/TS.h"
27
29
#include " crypto/X509Cert.h"
30
+ #include " util/algorithm.h"
28
31
#include " util/DateTime.h"
29
32
#include " util/File.h"
30
33
#include " util/log.h"
31
34
35
+ #include < functional>
36
+ #include < sstream>
37
+
32
38
using namespace digidoc ;
33
39
using namespace std ;
34
40
35
- constexpr std::string_view DSIG_NS { " http://www.w3.org/2000/09/xmldsig# " };
36
- constexpr XMLName DigestMethod { " DigestMethod " , DSIG_NS} ;
37
- constexpr XMLName DigestValue { " DigestValue " , DSIG_NS} ;
41
+ struct SignatureTST ::Data {
42
+ std::string name, mime, data ;
43
+ bool root = false ;
38
44
39
- SignatureTST::SignatureTST (const string &data, ASiC_S *asicSDoc)
40
- : asicSDoc(asicSDoc)
41
- , timestampToken(make_unique<TS>((const unsigned char *)data.data(), data.size()))
42
- {}
45
+ Digest digest (Digest digest = {}) const
46
+ {
47
+ digest.update ((const unsigned char *)data.data (), data.size ());
48
+ return digest;
49
+ }
50
+ };
43
51
44
- SignatureTST::SignatureTST (string current, XMLDocument &&xml, const string &data , ASiC_S *asicSDoc)
45
- : SignatureTST(data, asicSDoc)
52
+ SignatureTST::SignatureTST (bool manifest, const ZipSerialize &z , ASiC_S *asicSDoc)
53
+ : asicSDoc( asicSDoc)
46
54
{
47
- file = std::move (current);
48
- doc = std::move (xml);
55
+ auto data = z.extract <stringstream>(" META-INF/timestamp.tst" ).str ();
56
+ timestampToken = make_unique<TS>((const unsigned char *)data.data (), data.size ());
57
+ metadata.push_back ({" META-INF/timestamp.tst" , " application/vnd.etsi.timestamp-token" , std::move (data)});
58
+ if (!manifest)
59
+ return ;
60
+ XMLSchema schema (util::File::path (Conf::instance ()->xsdPath (), " en_31916201v010101.xsd" ));
61
+ function<void (const string &, string_view)> add = [this , &schema, &add, &z](const string &file, string_view mime) {
62
+ auto xml = z.extract <stringstream>(file);
63
+ XMLDocument doc = XMLDocument::openStream (xml, {" ASiCManifest" , ASiContainer::ASIC_NS});
64
+ schema.validate (doc);
65
+
66
+ for (auto ref = doc/" DataObjectReference" ; ref; ref++)
67
+ {
68
+ if (ref[" Rootfile" ] == " true" )
69
+ add (util::File::fromUriPath (ref[" URI" ]), ref[" MimeType" ]);
70
+ }
71
+
72
+ auto ref = doc/" SigReference" ;
73
+ string uri = util::File::fromUriPath (ref[" URI" ]);
74
+ string tst = z.extract <stringstream>(uri).str ();
75
+ metadata.push_back ({file, string (mime), xml.str ()});
76
+ metadata.push_back ({uri, string (ref[" MimeType" ]), std::move (tst)});
77
+ };
78
+ add (" META-INF/ASiCArchiveManifest.xml" , " text/xml" );
49
79
}
50
80
51
81
SignatureTST::SignatureTST (ASiC_S *asicSDoc, Signer *signer)
@@ -55,6 +85,8 @@ SignatureTST::SignatureTST(ASiC_S *asicSDoc, Signer *signer)
55
85
Digest digest;
56
86
dataFile->digest (digest);
57
87
timestampToken = make_unique<TS>(digest, signer->userAgent ());
88
+ vector<unsigned char > der = *timestampToken;
89
+ metadata.push_back ({" META-INF/timestamp.tst" , " application/vnd.etsi.timestamp-token" , {der.cbegin (), der.cend ()}});
58
90
}
59
91
60
92
SignatureTST::~SignatureTST () = default ;
@@ -106,28 +138,48 @@ void SignatureTST::validate() const
106
138
}
107
139
try
108
140
{
109
- timestampToken->verify (dataToSign ());
110
- if (auto digestMethod = signatureMethod ();
111
- !Exception::hasWarningIgnore (Exception::ReferenceDigestWeak) &&
141
+ auto digestMethod = signatureMethod ();
142
+ DataFile *file = asicSDoc->dataFiles ().front ();
143
+ timestampToken->verify (file->calcDigest (digestMethod));
144
+ if (!Exception::hasWarningIgnore (Exception::ReferenceDigestWeak) &&
112
145
Digest::isWeakDigest (digestMethod))
113
146
{
114
147
Exception e (EXCEPTION_PARAMS (" TimeStamp '%s' digest weak" , digestMethod.c_str ()));
115
148
e.setCode (Exception::ReferenceDigestWeak);
116
149
exception.addCause (e);
117
150
}
118
- if (doc)
151
+ vector<string> list {file->fileName ()};
152
+ for (const auto &manifest: metadata)
119
153
{
120
- DataFile *file = asicSDoc->dataFiles ().front ();
154
+ if (manifest.mime != " text/xml" )
155
+ continue ;
156
+ istringstream is (manifest.data );
157
+ XMLDocument doc = XMLDocument::openStream (is, {" ASiCManifest" , ASiContainer::ASIC_NS});
158
+ vector<string> add;
121
159
for (auto ref = doc/" DataObjectReference" ; ref; ref++)
122
160
{
123
161
string_view method = (ref/DigestMethod)[" Algorithm" ];
124
- auto uri = util::File::fromUriPath (ref[" URI" ]);
125
- vector<unsigned char > digest = file->fileName () == uri ?
126
- dynamic_cast <const DataFilePrivate*>(file)->calcDigest (string (method)) :
127
- asicSDoc->fileDigest (uri, method).result ();
162
+ const auto &uri = add.emplace_back (util::File::fromUriPath (ref[" URI" ]));
163
+ vector<unsigned char > digest;
164
+ if (file->fileName () == uri)
165
+ digest = file->calcDigest (string (method));
166
+ else
167
+ {
168
+ auto i = find_if (metadata.cbegin (), metadata.cend (), [&uri](const auto &d) { return d.name == uri; });
169
+ if (i == metadata.cend ())
170
+ THROW (" File not found '%s'." , uri.c_str ());
171
+ digest = i->digest (method).result ();
172
+ }
128
173
if (vector<unsigned char > digestValue = ref/DigestValue; digest != digestValue)
129
- THROW (" Reference %s digest does not match" , uri.c_str ());
174
+ THROW (" Reference '%s' digest does not match" , uri.c_str ());
175
+ }
176
+ // Check if all files in previous scope are present
177
+ for (const string &uri: list)
178
+ {
179
+ if (!contains (add, uri))
180
+ THROW (" Reference '%s' not found in manifest" , uri.c_str ());
130
181
}
182
+ list = std::move (add);
131
183
}
132
184
}
133
185
catch (const Exception& e)
@@ -141,8 +193,6 @@ void SignatureTST::validate() const
141
193
142
194
std::vector<unsigned char > SignatureTST::dataToSign () const
143
195
{
144
- if (!file.empty ())
145
- return asicSDoc->fileDigest (file, signatureMethod ()).result ();
146
196
return asicSDoc->dataFiles ().front ()->calcDigest (signatureMethod ());
147
197
}
148
198
@@ -162,7 +212,8 @@ string SignatureTST::profile() const
162
212
return string (ASiC_S::ASIC_TST_PROFILE);
163
213
}
164
214
165
- std::vector< unsigned char > SignatureTST::save () const
215
+ void SignatureTST::save (const ZipSerialize &z ) const
166
216
{
167
- return *timestampToken;
217
+ for (const auto &[name, mime, data, root]: metadata)
218
+ z.addFile (name, asicSDoc->zproperty (name))(data);
168
219
}
0 commit comments