@@ -45,58 +45,54 @@ struct FileEntry {
4545 * @brief CDoc1Writer is used for encrypt data.
4646 */
4747
48- class CDoc1Writer ::Private
48+ struct CDoc1Writer ::Private: public XMLWriter
4949{
50- public:
51- std::unique_ptr<XMLWriter> _xml;
52- std::vector<FileEntry> files;
53- std::vector<libcdoc::Recipient> rcpts;
50+ static const XMLWriter::NS DENC, DS, XENC11, DSIG11;
5451
55- static const XMLWriter::NS DENC, DS, XENC11, DSIG11;
56- std::string method, documentFormat = " ENCDOC-XML|1.1" , lastError;
52+ using XMLWriter::XMLWriter;
5753
58- uint64_t writeEncryptionProperties (bool use_ddoc);
59- uint64_t writeKeyInfo (bool use_ddoc, const libcdoc::Crypto::Key& transportKey);
60- uint64_t writeRecipient (const std::vector<uint8_t > &recipient, const libcdoc::Crypto::Key& transportKey);
54+ std::string method = " http://www.w3.org/2009/xmlenc11#aes256-gcm" ;
55+ std::string documentFormat = " ENCDOC-XML|1.1" , lastError;
56+ std::vector<FileEntry> files;
57+ std::vector<libcdoc::Recipient> rcpts;
58+
59+ int64_t writeEncryptionProperties (bool use_ddoc);
60+ int64_t writeKeyInfo (bool use_ddoc, const libcdoc::Crypto::Key& transportKey);
61+ int64_t writeRecipient (const std::vector<uint8_t > &recipient, const libcdoc::Crypto::Key& transportKey);
6162};
6263
6364const XMLWriter::NS CDoc1Writer::Private::DENC{ " denc" , " http://www.w3.org/2001/04/xmlenc#" };
6465const XMLWriter::NS CDoc1Writer::Private::DS{ " ds" , " http://www.w3.org/2000/09/xmldsig#" };
6566const XMLWriter::NS CDoc1Writer::Private::XENC11{ " xenc11" , " http://www.w3.org/2009/xmlenc11#" };
6667const XMLWriter::NS CDoc1Writer::Private::DSIG11{ " dsig11" , " http://www.w3.org/2009/xmldsig11#" };
6768
68- CDoc1Writer::CDoc1Writer (libcdoc::DataConsumer *dst, bool take_ownership, const std::string &method)
69- : CDocWriter(1 , dst, take_ownership), d(new Private())
70- {
71- d->method = method;
72- }
69+ CDoc1Writer::CDoc1Writer (libcdoc::DataConsumer *dst, bool take_ownership)
70+ : CDocWriter(1 , dst, take_ownership)
71+ {}
7372
74- CDoc1Writer::~CDoc1Writer ()
75- {
76- delete d;
77- }
73+ CDoc1Writer::~CDoc1Writer () noexcept = default ;
7874
79- uint64_t CDoc1Writer::Private::writeEncryptionProperties (bool use_ddoc)
75+ int64_t CDoc1Writer::Private::writeEncryptionProperties (bool use_ddoc)
8076{
81- RET_ERROR (_xml-> writeElement (DENC, " EncryptionProperties" , [&]() -> uint64_t {
82- RET_ERROR (_xml-> writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " LibraryVersion" }}, " cdoc|0.0.1" ));
83- RET_ERROR (_xml-> writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " DocumentFormat" }}, documentFormat));
84- RET_ERROR (_xml-> writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " Filename" }}, use_ddoc ? " tmp.ddoc" : files.at (0 ).name ));
77+ RET_ERROR (writeElement (DENC, " EncryptionProperties" , [&]() -> int64_t {
78+ RET_ERROR (writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " LibraryVersion" }}, " cdoc|0.0.1" ));
79+ RET_ERROR (writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " DocumentFormat" }}, documentFormat));
80+ RET_ERROR (writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " Filename" }}, use_ddoc ? " tmp.ddoc" : files.at (0 ).name ));
8581 for (const FileEntry &file: files)
8682 {
87- RET_ERROR (_xml-> writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " orig_file" }},
83+ RET_ERROR (writeTextElement (Private::DENC, " EncryptionProperty" , {{" Name" , " orig_file" }},
8884 file.name + " |" + std::to_string (file.size ) + " |" + " application/octet-stream" + " |D0" ));
8985 }
9086 return OK;
9187 }));
92- return _xml-> writeEndElement (Private::DENC); // EncryptedData
88+ return writeEndElement (Private::DENC); // EncryptedData
9389}
9490
95- uint64_t CDoc1Writer::Private::writeKeyInfo (bool use_ddoc, const libcdoc::Crypto::Key& transportKey)
91+ int64_t CDoc1Writer::Private::writeKeyInfo (bool use_ddoc, const libcdoc::Crypto::Key& transportKey)
9692{
97- RET_ERROR (_xml-> writeStartElement (Private::DENC, " EncryptedData" , {{" MimeType" , use_ddoc ? " http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" : " application/octet-stream" }}));
98- RET_ERROR (_xml-> writeElement (Private::DENC, " EncryptionMethod" , {{" Algorithm" , method}}));
99- return _xml-> writeElement (Private::DS, " KeyInfo" , {}, [&]() -> uint64_t {
93+ RET_ERROR (writeStartElement (Private::DENC, " EncryptedData" , {{" MimeType" , use_ddoc ? " http://www.sk.ee/DigiDoc/v1.3.0/digidoc.xsd" : " application/octet-stream" }}));
94+ RET_ERROR (writeElement (Private::DENC, " EncryptionMethod" , {{" Algorithm" , method}}));
95+ return writeElement (Private::DS, " KeyInfo" , {}, [&]() -> int64_t {
10096 for (const libcdoc::Recipient& key : rcpts) {
10197 if (!key.isCertificate ()) {
10298 lastError = " Invalid recipient type" ;
@@ -113,7 +109,7 @@ uint64_t CDoc1Writer::Private::writeKeyInfo(bool use_ddoc, const libcdoc::Crypto
113109 });
114110}
115111
116- uint64_t CDoc1Writer::Private::writeRecipient (const std::vector<uint8_t > &recipient, const libcdoc::Crypto::Key& transportKey)
112+ int64_t CDoc1Writer::Private::writeRecipient (const std::vector<uint8_t > &recipient, const libcdoc::Crypto::Key& transportKey)
117113{
118114 auto peerCert = libcdoc::Crypto::toX509 (recipient);
119115 if (!peerCert)
@@ -136,7 +132,7 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
136132 OPENSSL_free (data);
137133 return cn;
138134 }();
139- return _xml-> writeElement (Private::DENC, " EncryptedKey" , {{" Recipient" , cn}}, [&]() -> uint64_t {
135+ return writeElement (Private::DENC, " EncryptedKey" , {{" Recipient" , cn}}, [&]() -> int64_t {
140136 std::vector<uint8_t > encryptedData;
141137 auto *peerPKey = X509_get0_pubkey (peerCert.get ());
142138 switch (EVP_PKEY_base_id (peerPKey))
@@ -147,10 +143,10 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
147143 encryptedData.resize (size_t (RSA_size (rsa.get ())));
148144 RSA_public_encrypt (int (transportKey.key .size ()), transportKey.key .data (),
149145 encryptedData.data (), rsa.get (), RSA_PKCS1_PADDING);
150- RET_ERROR (_xml-> writeElement (Private::DENC, " EncryptionMethod" , {{" Algorithm" , libcdoc::Crypto::RSA_MTH}}));
151- RET_ERROR (_xml-> writeElement (Private::DS, " KeyInfo" , [&]{
152- return _xml-> writeElement (Private::DS, " X509Data" , [&]{
153- return _xml-> writeBase64Element (Private::DS, " X509Certificate" , recipient);
146+ RET_ERROR (writeElement (Private::DENC, " EncryptionMethod" , {{" Algorithm" , libcdoc::Crypto::RSA_MTH}}));
147+ RET_ERROR (writeElement (Private::DS, " KeyInfo" , [&] {
148+ return writeElement (Private::DS, " X509Data" , [&] {
149+ return writeBase64Element (Private::DS, " X509Certificate" , recipient);
154150 });
155151 }));
156152 break ;
@@ -188,28 +184,28 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
188184 LOG_TRACE_KEY (" iv {}" , transportKey.iv );
189185 LOG_TRACE_KEY (" transport {}" , transportKey.key );
190186
191- RET_ERROR (_xml-> writeElement (Private::DENC, " EncryptionMethod" , {{" Algorithm" , encryptionMethod}}));
192- RET_ERROR (_xml-> writeElement (Private::DS, " KeyInfo" , [&]{
193- return _xml-> writeElement (Private::DENC, " AgreementMethod" , {{" Algorithm" , libcdoc::Crypto::AGREEMENT_MTH}}, [&]{
194- RET_ERROR (_xml-> writeElement (Private::XENC11, " KeyDerivationMethod" , {{" Algorithm" , libcdoc::Crypto::CONCATKDF_MTH}}, [&]{
195- return _xml-> writeElement (Private::XENC11, " ConcatKDFParams" , {
187+ RET_ERROR (writeElement (Private::DENC, " EncryptionMethod" , {{" Algorithm" , encryptionMethod}}));
188+ RET_ERROR (writeElement (Private::DS, " KeyInfo" , [&] {
189+ return writeElement (Private::DENC, " AgreementMethod" , {{" Algorithm" , libcdoc::Crypto::AGREEMENT_MTH}}, [&] {
190+ RET_ERROR (writeElement (Private::XENC11, " KeyDerivationMethod" , {{" Algorithm" , libcdoc::Crypto::CONCATKDF_MTH}}, [&] {
191+ return writeElement (Private::XENC11, " ConcatKDFParams" , {
196192 {" AlgorithmID" , " 00" + libcdoc::toHex (AlgorithmID)},
197193 {" PartyUInfo" , " 00" + libcdoc::toHex (SsDer)},
198- {" PartyVInfo" , " 00" + libcdoc::toHex (recipient)}}, [&]{
199- return _xml-> writeElement (Private::DS, " DigestMethod" , {{" Algorithm" , concatDigest}});
194+ {" PartyVInfo" , " 00" + libcdoc::toHex (recipient)}}, [&] {
195+ return writeElement (Private::DS, " DigestMethod" , {{" Algorithm" , concatDigest}});
200196 });
201197 }));
202- RET_ERROR (_xml-> writeElement (Private::DENC, " OriginatorKeyInfo" , [&]{
203- return _xml-> writeElement (Private::DS, " KeyValue" , [&]{
204- return _xml-> writeElement (Private::DSIG11, " ECKeyValue" , [&]{
205- RET_ERROR (_xml-> writeElement (Private::DSIG11, " NamedCurve" , {{" URI" , " urn:oid:" + oid}}));
206- return _xml-> writeBase64Element (Private::DSIG11, " PublicKey" , SsDer);
198+ RET_ERROR (writeElement (Private::DENC, " OriginatorKeyInfo" , [&] {
199+ return writeElement (Private::DS, " KeyValue" , [&] {
200+ return writeElement (Private::DSIG11, " ECKeyValue" , [&] {
201+ RET_ERROR (writeElement (Private::DSIG11, " NamedCurve" , {{" URI" , " urn:oid:" + oid}}));
202+ return writeBase64Element (Private::DSIG11, " PublicKey" , SsDer);
207203 });
208204 });
209205 }));
210- return _xml-> writeElement (Private::DENC, " RecipientKeyInfo" , [&]{
211- return _xml-> writeElement (Private::DS, " X509Data" , [&]{
212- return _xml-> writeBase64Element (Private::DS, " X509Certificate" , recipient);
206+ return writeElement (Private::DENC, " RecipientKeyInfo" , [&] {
207+ return writeElement (Private::DS, " X509Data" , [&] {
208+ return writeBase64Element (Private::DS, " X509Certificate" , recipient);
213209 });
214210 });
215211 });
@@ -222,8 +218,8 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
222218
223219 if (encryptedData.empty ())
224220 return UNSPECIFIED_ERROR;
225- return _xml-> writeElement (Private::DENC, " CipherData" , [&]{
226- return _xml-> writeBase64Element (Private::DENC, " CipherValue" , encryptedData);
221+ return writeElement (Private::DENC, " CipherData" , [&] {
222+ return writeBase64Element (Private::DENC, " CipherValue" , encryptedData);
227223 });
228224 });
229225}
@@ -234,14 +230,14 @@ uint64_t CDoc1Writer::Private::writeRecipient(const std::vector<uint8_t> &recipi
234230libcdoc::result_t
235231CDoc1Writer::encrypt (libcdoc::MultiDataSource& src, const std::vector<libcdoc::Recipient>& keys)
236232{
233+ d = std::make_unique<Private>(dst);
234+ d->rcpts = keys;
237235 libcdoc::Crypto::Key transportKey = libcdoc::Crypto::generateKey (d->method );
238236 int n_components = src.getNumComponents ();
239237 bool use_ddoc = (n_components > 1 ) || (n_components == libcdoc::NOT_IMPLEMENTED);
240- d->rcpts = keys;
241238
242- d->_xml = std::make_unique<XMLWriter>(dst);
243239 RET_ERROR (d->writeKeyInfo (use_ddoc, transportKey));
244- RET_ERROR (d->_xml -> writeElement (Private::DENC, " CipherData" , [&]() -> uint64_t {
240+ RET_ERROR (d->writeElement (Private::DENC, " CipherData" , [&]() -> int64_t {
245241 std::vector<uint8_t > data;
246242 if (use_ddoc) {
247243 data.reserve (16384 );
@@ -268,18 +264,18 @@ CDoc1Writer::encrypt(libcdoc::MultiDataSource& src, const std::vector<libcdoc::R
268264 return IO_ERROR;
269265 d->files .push_back ({std::move (name), (size_t ) result});
270266 }
271- return d->_xml -> writeBase64Element (Private::DENC, " CipherValue" , libcdoc::Crypto::encrypt (d->method , transportKey, data));
267+ return d->writeBase64Element (Private::DENC, " CipherValue" , libcdoc::Crypto::encrypt (d->method , transportKey, data));
272268 }));
273269 RET_ERROR (d->writeEncryptionProperties (use_ddoc));
274- d-> _xml .reset ();
270+ d .reset ();
275271 if (owned) return dst->close ();
276272 return OK;
277273}
278274
279275libcdoc::result_t
280276CDoc1Writer::beginEncryption ()
281277{
282- d-> _xml = std::make_unique<XMLWriter >(dst);
278+ d = std::make_unique<Private >(dst);
283279 return libcdoc::OK;
284280}
285281
@@ -308,25 +304,25 @@ CDoc1Writer::writeData(const uint8_t *src, size_t size)
308304libcdoc::result_t
309305CDoc1Writer::finishEncryption ()
310306{
311- if (!d-> _xml ) return libcdoc::WORKFLOW_ERROR;
307+ if (!d) return libcdoc::WORKFLOW_ERROR;
312308 if (d->rcpts .empty ()) return libcdoc::WORKFLOW_ERROR;
313309 if (d->files .empty ()) return libcdoc::WORKFLOW_ERROR;
314310 bool use_ddoc = d->files .size () > 1 ;
315311 libcdoc::Crypto::Key transportKey = libcdoc::Crypto::generateKey (d->method );
316312
317313 RET_ERROR (d->writeKeyInfo (use_ddoc, transportKey));
318- RET_ERROR (d->_xml -> writeElement (Private::DENC, " CipherData" , [&]{
314+ RET_ERROR (d->writeElement (Private::DENC, " CipherData" , [&] {
319315 if (!use_ddoc)
320- return d->_xml -> writeBase64Element (Private::DENC, " CipherValue" , libcdoc::Crypto::encrypt (d->method , transportKey, d->files .back ().data ));
316+ return d->writeBase64Element (Private::DENC, " CipherValue" , libcdoc::Crypto::encrypt (d->method , transportKey, d->files .back ().data ));
321317 std::vector<uint8_t > data;
322318 data.reserve (4096 );
323319 for (DDOCWriter ddoc (data); const FileEntry& file : d->files ) {
324320 ddoc.addFile (file.name , " application/octet-stream" , file.data );
325321 }
326- return d->_xml -> writeBase64Element (Private::DENC, " CipherValue" , libcdoc::Crypto::encrypt (d->method , transportKey, data));
322+ return d->writeBase64Element (Private::DENC, " CipherValue" , libcdoc::Crypto::encrypt (d->method , transportKey, data));
327323 }));
328324 RET_ERROR (d->writeEncryptionProperties (use_ddoc));
329- d-> _xml .reset ();
325+ d .reset ();
330326 if (owned) return dst->close ();
331327 return libcdoc::OK;
332328}
0 commit comments