Cipherpack v1.2.0-dirty
A Cryprographic Stream Processor
cipherpack.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2021 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef JAU_CIPHERPACK_HPP_
27#define JAU_CIPHERPACK_HPP_
28
29#include <string>
30#include <cstdint>
31#include <functional>
32
33#include <botan_all.h>
34
36
37#include <jau/basic_types.hpp>
38#include <jau/file_util.hpp>
39#include <jau/byte_stream.hpp>
40#include <jau/io_util.hpp>
41#include <jau/environment.hpp>
42#include <jau/java_uplink.hpp>
43
44namespace cipherpack {
45
46 /** @defgroup CipherpackAPI Cipherpack General User Level API
47 * General User level Cipherpack API types and functionality, see @ref cipherpack_overview "Cipherpack Overview".
48 *
49 * @anchor cipherpack_overview
50 * ### Cipherpack Overview
51 * *Cipherpack*, a secure stream processor utilizing public-key signatures to
52 * authenticate the sender and public-key encryption of a symmetric-key for multiple receiver
53 * ensuring their privacy and high-performance message encryption.
54 *
55 * *Cipherpack* securely streams messages through any media,
56 * via file using
57 * [ByteInStream_File](https://jausoft.com/projects/jaulib/build/documentation/cpp/html/classjau_1_1io_1_1ByteInStream__File.html)
58 * and via all [*libcurl* network protocols](https://curl.se/docs/url-syntax.html)
59 * using [ByteInStream_URL](https://jausoft.com/projects/jaulib/build/documentation/cpp/html/classjau_1_1io_1_1ByteInStream__URL.html)
60 * are *build-in* and supported. <br/>
61 * Note: *libcurl* must be enabled via `-DUSE_LIBCURL=ON` at build.
62 *
63 * A user may use the media agnostic
64 * [ByteInStream_Feed](https://jausoft.com/projects/jaulib/build/documentation/cpp/html/classjau_1_1io_1_1ByteInStream__Feed.html)
65 * to produce the input stream by injecting data off-thread and a CipherpackListener to receive the processed output stream.
66 *
67 * *Cipherpack* is implemented using C++17 and accessible via C++ and Java.
68 *
69 * ### Cipherpack Implementation
70 * #### Implementation Status
71 * READY TO USE
72 *
73 * #### Cipherpack Operations
74 * The following public-key signature and encryption, as well as symmetric-key message encryption operations are performed:
75 * - Writing a DER Header-1, containing the general message information and receiver count, see {@link PackHeader} details.
76 * - Writing a DER Header for each recevr, containing the fingerprint, encrypted symmetric-key and encrypted symmetric-nonce.
77 * - Writing a DER Header-2, containing the sender's signature over the whole header
78 * - Writing the symmetrically encrypted message, using the symmetric-key for encryption + MAC via AEAD `ChaCha20Poly1305`.
79 *
80 * Implementation performs all operation `in-place` without redundant copies, processing the stream.
81 *
82 * @anchor cipherpack_stream
83 * #### Cipherpack Data Stream
84 * The stream's header contains the sender's public-key fingerprint
85 * and its signature for authentication by the receiving parties.
86 *
87 * Further, the stream contains triples per receiver, its public-key fingerprint,
88 * the encrypted symmetric-key and the encrypted symmetric-nonce for each receiver,
89 * allowing a secure messaging between multiple parties:
90 * - Symmetric encryption of the plaintext message ensures high-performance processing.
91 * - Symmetric stream-key is unique for each message
92 *
93 * Implementation uses an Authenticated Encryption with Additional Data (AEAD) encryption+MAC cipher algo,
94 * i.e. {@link cipherpack::constants::aead_cipher_algo}.
95 *
96 * The random nonce, unique for one message and used for the symmetric encryption is not a secret and doesn't have to be confidential.
97 * However, since we already encrypt the symmetric-key for each receiver, we transmit the nonce with it, encrypted.
98 *
99 * The cipherpack stream will be produced as follows:
100 * ```
101 * DER Header 1 {
102 * ASN1_Type::OctetString stream_magic // simple stream identifier to be matched
103 * ASN1_Type::OctetString target_path // optional target path for the plaintext message, user application specific.
104 * ASN1_Type::Integer plaintext_size // size in bytes of plaintext message, zero if not determined at start of streaming
105 * ASN1_Type::Integer creation_timestamp_sec // message creation timestamp, second component
106 * ASN1_Type::Integer creation_timestamp_nsec // message creation timestamp, nanoseconds component
107 * ASN1_Type::OctetString subject // optional subject of message, user application specific.
108 * ASN1_Type::OctetString plaintext_version // version of this plaintext message, user application specific.
109 * ASN1_Type::OctetString plaintext_version_parent // version of this plaintext message's preceding message, user application specific.
110 * ASN1_Type::OctetString pk_type // public-key type. Default `RSA`.
111 * ASN1_Type::OctetString pk_fingerprt_hash_algo // public-key fingerprint hash. Default `SHA-256`.
112 * ASN1_Type::OctetString pk_enc_padding_algo // public-key encryption padding. Default `OAEP`.
113 * ASN1_Type::OctetString pk_enc_hash_algo // public-key encryption hash. Default `SHA-256`.
114 * ASN1_Type::OctetString pk_sign_algo // public-key signature algorithm. Default `EMSA1(SHA-256)`.
115 * ASN1_Type::ObjectId sym_enc_mac_oid // symmetric-key encryption+MAC algorithm. Default `ChaCha20Poly1305`.
116 * ASN1_Type::OctetString fingerprt_sender // fingerprint of public sender key used for header signature
117 * ASN1_Type::Integer receiver_count, // number of receiver triples { fingerprint, encrypted-symmetric-keys, encrypted-nonce }
118 * }
119 * DER Header recevr_1 {
120 * ASN1_Type::OctetString fingerprt_recevr_1, // fingerprint of receiver's public-key_1 used for encrypted_skey_recevr_1
121 * ASN1_Type::OctetString encrypted_skey_recevr_1, // encrypted symmetric-key with receiver's public-key_1
122 * ASN1_Type::OctetString encrypted_nonce_recevr_1, // encrypted symmetric-encryption nonce with receiver's public-key_1
123 * },
124 * DER Header recevr_2 {
125 * ASN1_Type::OctetString fingerprt_recevr_2, // fingerprint of receiver's public-key_1 used for encrypted_skey_recevr_2
126 * ASN1_Type::OctetString encrypted_skey_recevr_2, // encrypted symmetric-key with receiver's public-key_2
127 * ASN1_Type::OctetString encrypted_nonce_recevr_2, // encrypted symmetric-encryption nonce with receiver's public-key_2
128 * } ...
129 * DER Header 2 {
130 * ASN1_Type::OctetString sign_sender // sender's signature over whole header, matching fingerprt_sender
131 * },
132 * uint8_t encrypted_data[ciphertext_size] // the encrypted message, `ciphertext_size` bytes resulting to `plaintext_size` plaintext message
133 * ```
134 *
135 * @see encryptThenSign()
136 * @see checkSignThenDecrypt()
137 *
138 * @{
139 */
140
141 #define JAVA_MAIN_PACKAGE "org/cipherpack/"
142
144 private:
145 environment() noexcept;
146
147 public:
148 void print_info() noexcept;
149
150 static environment& get() noexcept {
151 /**
152 * Thread safe starting with C++11 6.7:
153 *
154 * If control enters the declaration concurrently while the variable is being initialized,
155 * the concurrent execution shall wait for completion of the initialization.
156 *
157 * (Magic Statics)
158 *
159 * Avoiding non-working double checked locking.
160 */
161 static environment e;
162 return e;
163 }
164 };
165
166 template<typename T> using secure_vector = std::vector<T, Botan::secure_allocator<T>>;
167
168 /**
169 * This class represents an abstract data source object.
170 */
171 class WrappingDataSource : public Botan::DataSource
172 {
173 public:
174 jau::io::ByteInStream& in;
175
176 WrappingDataSource(jau::io::ByteInStream& in_)
177 : in(in_) {}
178
179 [[nodiscard]] size_t read(uint8_t out[], size_t length) override
180 { return in.read(out, length); }
181
182 bool check_available(size_t n) override
183 { return in.available(n); }
184
185 [[nodiscard]] size_t peek(uint8_t out[], size_t length, size_t peek_offset) const override
186 { return in.peek(out, length, peek_offset); }
187
188 bool end_of_data() const override
189 { return !in.good(); }
190
191 std::string id() const override
192 { return in.id(); }
193
194 size_t get_bytes_read() const override
195 { return static_cast<size_t>( in.tellg() ); }
196 };
197
198 /**
199 * CryptoConfig, contains crypto algorithms settings given at encryption wired via the @ref cipherpack_stream "Cipherpack Data Stream",
200 * hence received and used at decryption if matching keys are available.
201 *
202 * @see @ref cipherpack_overview "Cipherpack Overview"
203 * @see @ref cipherpack_stream "Cipherpack Data Stream"
204 */
206 std::string pk_type;
209 std::string pk_enc_hash_algo;
210 std::string pk_sign_algo;
211 std::string sym_enc_algo;
213
214 /**
215 * Returns default CryptoConfig.
216 *
217 * - Public-Key type is {@code RSA}.
218 * - Public key fingerprint hash algorithm is {@code SHA-256}.
219 * - Public-Key padding algorithm is {@code OAEP}.
220 * - Public-Key hash algorithm is {@code SHA-256}.
221 * - Public-Key signature algorithm is {@code EMSA1(SHA-256)}.
222 * - Symmetric Authenticated Encryption with Additional Data (AEAD) encryption+MAC cipher algo is {@code ChaCha20Poly1305}.
223 * - Symmetric AEAD ChaCha Nonce size 96 bit for one message per symmetric-key. Sizes are usually: 64-bit classic, 96-bit IETF, 192-bit big.
224 */
225 static CryptoConfig getDefault() noexcept;
226
227 CryptoConfig() noexcept
228 : pk_type(),
232 pk_sign_algo(),
233 sym_enc_algo(),
235 { }
236
237 CryptoConfig(const std::string& pk_type_,
238 const std::string& pk_fingerprt_hash_algo_,
239 const std::string& pk_enc_padding_algo_,
240 const std::string& pk_enc_hash_algo_,
241 const std::string& pk_sign_algo_,
242 const std::string& sym_enc_algo_,
243 const size_t sym_enc_nonce_bytes_) noexcept
244 : pk_type(pk_type_),
245 pk_fingerprt_hash_algo(pk_fingerprt_hash_algo_),
246 pk_enc_padding_algo(pk_enc_padding_algo_),
247 pk_enc_hash_algo(pk_enc_hash_algo_),
248 pk_sign_algo(pk_sign_algo_),
249 sym_enc_algo(sym_enc_algo_),
250 sym_enc_nonce_bytes(sym_enc_nonce_bytes_)
251 { }
252
253 bool valid() const noexcept;
254
255 std::string to_string() const noexcept;
256 };
257
258 class Constants {
259 public:
260 /** Intermediate copy buffer size of {@code 16384 bytes}, usually the 4 x 4096 bytes page-size. */
261 constexpr static const size_t buffer_size = 16384;
262
263 /**
264 * Package magic {@code CIPHERPACK_0004}.
265 */
266 static const std::string package_magic;
267 };
268
269 /**
270 * Cipherpack header less encrypted keys or signatures as described in @ref cipherpack_stream "Cipherpack Data Stream"
271 *
272 * @see @ref cipherpack_overview "Cipherpack Overview"
273 * @see @ref cipherpack_stream "Cipherpack Data Stream"
274 */
276 private:
277 std::string target_path_;
278 uint64_t plaintext_size_;
279 jau::fraction_timespec ts_creation_;
280 std::string subject_;
281 std::string plaintext_version_;
282 std::string plaintext_version_parent_;
283 CryptoConfig crypto_cfg_;
284 std::vector<uint8_t> sender_fingerprint_;
285 std::vector<std::vector<uint8_t>> recevr_fingerprints_;
286 ssize_t used_recevr_key_idx_;
287 std::string plaintext_hash_algo_;
288 std::vector<uint8_t> plaintext_hash_;
289 bool valid_;
290
291 public:
292 /** default ctor, denoting an invalid package header. */
294 : target_path_("none"),
295 plaintext_size_(0),
296 ts_creation_( jau::getWallClockTime() ),
297 subject_("none"),
298 plaintext_version_(),
299 plaintext_version_parent_(),
300 crypto_cfg_(),
301 sender_fingerprint_(),
302 recevr_fingerprints_(),
303 used_recevr_key_idx_(-1),
304 plaintext_hash_algo_(),
305 plaintext_hash_(),
306 valid_(false)
307 { }
308
309 /** ctor, denoting an invalid package header. */
310 PackHeader(const jau::fraction_timespec& ts_creation)
311 : target_path_("none"),
312 plaintext_size_(0),
313 ts_creation_( ts_creation ),
314 subject_("none"),
315 plaintext_version_(),
316 plaintext_version_parent_(),
317 crypto_cfg_(),
318 sender_fingerprint_(),
319 recevr_fingerprints_(),
320 used_recevr_key_idx_(-1),
321 plaintext_hash_algo_(),
322 plaintext_hash_(),
323 valid_(false)
324 { }
325
326 /** Complete ctor, denoting a complete package header, see @ref cipherpack_stream "Cipherpack Data Stream". */
327 PackHeader(const std::string& _target_path,
328 const uint64_t& _plaintext_size,
329 const jau::fraction_timespec& _ts_creation,
330 const std::string& _subject,
331 const std::string& _pversion, const std::string& _pversion_parent,
332 const CryptoConfig& _crypto_cfg,
333 const std::vector<uint8_t>& _sender_fingerprint,
334 const std::vector<std::vector<uint8_t>>& _recevr_fingerprints,
335 const size_t _used_recevr_key_idx,
336 const bool _valid)
337 : target_path_(_target_path),
338 plaintext_size_(_plaintext_size),
339 ts_creation_(_ts_creation),
340 subject_(_subject),
341 plaintext_version_(_pversion), plaintext_version_parent_(_pversion_parent),
342 crypto_cfg_(_crypto_cfg),
343 sender_fingerprint_(_sender_fingerprint),
344 recevr_fingerprints_(_recevr_fingerprints),
345 used_recevr_key_idx_(_used_recevr_key_idx),
346 plaintext_hash_algo_(),
347 plaintext_hash_(),
348 valid_(_valid)
349 { }
350
351 /** Returns the designated target path for this plaintext message, see @ref cipherpack_stream "Cipherpack Data Stream". */
352 const std::string& target_path() const noexcept { return target_path_; }
353
354 /** Returns the plaintext message size in bytes, zero if not determined yet. See @ref cipherpack_stream "Cipherpack Data Stream". */
355 uint64_t plaintext_size() const noexcept { return plaintext_size_; }
356
357 void set_plaintext_size(const uint64_t v) noexcept { plaintext_size_=v; }
358
359 /** Returns the creation time since Unix epoch, see @ref cipherpack_stream "Cipherpack Data Stream". */
360 constexpr const jau::fraction_timespec& creation_time() const noexcept { return ts_creation_; }
361
362 /** Returns the designated subject of message, see @ref cipherpack_stream "Cipherpack Data Stream". */
363 constexpr const std::string& subject() const noexcept { return subject_; }
364
365 /** Returns version of this plaintext message, user semantic, see @ref cipherpack_stream "Cipherpack Data Stream". */
366 constexpr const std::string& plaintext_version() const noexcept { return plaintext_version_;}
367
368 /** Returns version of this plaintext message's preceding message, user semantic, see @ref cipherpack_stream "Cipherpack Data Stream". */
369 constexpr const std::string& plaintext_version_parent() const noexcept { return plaintext_version_parent_;}
370
371 constexpr const CryptoConfig& crypto_config() const noexcept { return crypto_cfg_; }
372
373 /**
374 * Return the sender's public-key fingerprint used to sign, see @ref cipherpack_stream "Cipherpack Data Stream".
375 */
376 const std::vector<uint8_t>& sender_fingerprint() const noexcept { return sender_fingerprint_; }
377
378 /**
379 * Return the list of receiver's public-keys fingerprints used to encrypt the symmetric-key, see @ref cipherpack_stream "Cipherpack Data Stream".
380 */
381 const std::vector<std::vector<uint8_t>>& receiver_fingerprints() const noexcept { return recevr_fingerprints_; }
382
383 /**
384 * Return the index of the matching receiver's public-key fingerprint used to decrypt the symmetric-key, see @ref cipherpack_stream "Cipherpack Data Stream".
385 *
386 * @return the receiver's key index of getReceiverFingerprints(), or -1 if not found or not decrypting.
387 */
388 ssize_t receiver_key_index() const noexcept { return used_recevr_key_idx_; }
389
390 /**
391 * Return optional hash algorithm for the plaintext message, produced for convenience and not wired.
392 *
393 * If not used, returned string is empty.
394 *
395 * @see getPlaintextHash()
396 * @see setPlaintextHash()
397 */
398 const std::string& plaintext_hash_algo() const noexcept { return plaintext_hash_algo_; }
399
400 /**
401 * Return optional hash value of the plaintext message, produced for convenience and not wired.
402 *
403 * If not used, i.e. getPlaintextHashAlgo() is empty, returned vector has zero size.
404 *
405 * @see getPlaintextHashAlgo()
406 * @see setPlaintextHash()
407 */
408 const std::vector<uint8_t>& plaintext_hash() const noexcept { return plaintext_hash_; }
409
410 /**
411 * Set optional hash-algo and -value of the plaintext messages, produced for convenience and not wired.
412 * @see getPlaintextHash()
413 * @see getPlaintextHashAlgo()
414 */
415 void set_plaintext_hash(const std::string& algo, const std::vector<uint8_t>& hash) noexcept {
416 plaintext_hash_algo_ = algo;
417 plaintext_hash_ = hash;
418 }
419
420 /**
421 * Return a string representation
422 * @param show_crypto_algos pass true if used crypto algos shall be shown, otherwise suppressed (default).
423 * @param force_all_fingerprints if true always show all getTermKeysFingerprint(), otherwise show only the getTermKeysFingerprint() if >= 0 (default).
424 * @return string representation
425 */
426 std::string to_string(const bool show_crypto_algos=false, const bool force_all_fingerprints=false) const noexcept;
427
428 void setValid(const bool v) { valid_ = v; }
429 bool isValid() const noexcept { return valid_; }
430 };
431 inline std::string to_string(const PackHeader& ph) noexcept { return ph.to_string(true, true); }
432
433 std::shared_ptr<Botan::Public_Key> load_public_key(const std::string& pubkey_fname);
434 std::shared_ptr<Botan::Private_Key> load_private_key(const std::string& privatekey_fname, const jau::io::secure_string& passphrase);
435
436 /**
437 * Listener for events occurring while processing a cipherpack message via encryptThenSign() and checkSignThenDecrypt().
438 *
439 * @see @ref cipherpack_overview "Cipherpack Overview"
440 * @see @ref cipherpack_stream "Cipherpack Data Stream"
441 */
442 class CipherpackListener : public jau::jni::JavaUplink {
443 public:
444 enum class content_type : uint8_t {
445 header = 0,
446 message = 1
447 };
448
449 /**
450 * User notification about an error via text message and preliminary PackHeader
451 *
452 * This message will be send without a subsequent notifyHeader() or notifyEnd() to indicate an error and hence aborts processing.
453 * @param decrypt_mode true if sender is decrypting, otherwise sender is encrypting
454 * @param header the preliminary PackHeader
455 * @param msg the error message
456 */
457 virtual void notifyError(const bool decrypt_mode, const PackHeader& header, const std::string& msg) noexcept {
458 (void)decrypt_mode;
459 (void)msg;
460 }
461
462 /**
463 * User notification of preliminary PackHeader w/o optional hash of the plaintext message
464 * @param decrypt_mode true if sender is decrypting, otherwise sender is encrypting
465 * @param header the preliminary PackHeader
466 * @return true to continue processing (default), false to abort.
467 */
468 virtual bool notifyHeader(const bool decrypt_mode, const PackHeader& header) noexcept {
469 (void)decrypt_mode;
470 (void)header;
471 return true;
472 }
473
474 /**
475 * User notification about content streaming progress.
476 *
477 * In case contentProcessed() gets called, notifyProgress() is called thereafter.
478 *
479 * @param decrypt_mode true if sender is decrypting, otherwise sender is encrypting
480 * @param plaintext_size the plaintext message size, zero if not determined yet
481 * @param bytes_processed the number of unencrypted bytes processed
482 * @return true to continue processing (default), false to abort.
483 * @see contentProcessed()
484 */
485 virtual bool notifyProgress(const bool decrypt_mode, const uint64_t plaintext_size, const uint64_t bytes_processed) noexcept {
486 (void)decrypt_mode;
487 (void)plaintext_size;
488 (void)bytes_processed;
489 return true;
490 }
491
492 /**
493 * User notification of successful completion.
494 * @param decrypt_mode true if sender is decrypting, otherwise sender is encrypting
495 * @param header the final PackHeader
496 */
497 virtual void notifyEnd(const bool decrypt_mode, const PackHeader& header) noexcept {
498 (void)decrypt_mode;
499 (void)header;
500 }
501
502 /**
503 * User provided information whether process shall send the processed content via contentProcessed() or not
504 * @param decrypt_mode true if sender is decrypting, otherwise sender is encrypting
505 * @return true if process shall call contentProcessed(), otherwise false (default)
506 * @see contentProcessed()
507 */
508 virtual bool getSendContent(const bool decrypt_mode) const noexcept {
509 (void)decrypt_mode;
510 return false;
511 }
512
513 /**
514 * User callback to receive the actual processed content, either the generated cipherpack or plaintext content depending on decrypt_mode.
515 *
516 * This callback is only enabled if getSendContent() returns true.
517 *
518 * In case contentProcessed() gets called, notifyProgress() is called thereafter.
519 *
520 * @param decrypt_mode true if sender is decrypting, otherwise sender is encrypting
521 * @param ctype content_type of passed data. Always content_type::message if decrypt_mode is true.
522 * @param data the processed content, either the generated cipherpack or plaintext content depending on decrypt_mode.
523 * @param is_final true if this is the last content call, otherwise false
524 * @return true to continue processing (default), false to abort.
525 * @see getSendContent()
526 */
527 virtual bool contentProcessed(const bool decrypt_mode, const content_type ctype, cipherpack::secure_vector<uint8_t>& data, const bool is_final) noexcept {
528 (void)decrypt_mode;
529 (void)ctype;
530 (void)data;
531 (void)is_final;
532 return true;
533 }
534
535 ~CipherpackListener() noexcept override {}
536
537 std::string toString() const noexcept override { return "CipherpackListener["+jau::to_hexstring(this)+"]"; }
538
539 std::string get_java_class() const noexcept override {
540 return java_class();
541 }
542 static std::string java_class() noexcept {
543 return std::string(JAVA_MAIN_PACKAGE "CipherpackListener");
544 }
545
546 /**
547 * Default comparison operator, merely testing for same memory reference.
548 * <p>
549 * Specializations may override.
550 * </p>
551 */
552 virtual bool operator==(const CipherpackListener& rhs) const noexcept
553 { return this == &rhs; }
554
555 bool operator!=(const CipherpackListener& rhs) const noexcept
556 { return !(*this == rhs); }
557
558 };
559 typedef std::shared_ptr<CipherpackListener> CipherpackListenerRef;
560
561 /**
562 * Name of default hash algo for the plaintext message,
563 * e.g. for encryptThenSign() and checkSignThenDecrypt().
564 *
565 * Value is `BLAKE2b(512)`.
566 *
567 * Note:
568 * - SHA-256 performs 64 rounds over 512 bits (blocks size) at a time.
569 * - Often better optimized and hardware implemented.
570 * - SHA-512 performs 80 rounds over 1024 bits (blocks size) at a time.
571 * - Requires double storage size than SHA-256, i.e. 512/256 bits.
572 * - 25% more rounds, i.e. calculations than SHA-256
573 * - Operating on 64-bit words instead of SHA-256's 32-bit words
574 * - Theoretically shall outperform SHA-256 by 2 / 1.25 = 1.6 on 64-bit architectures,
575 * however, SHA-256 is often better optimized and hardware implemented.
576 * - BLAKE2b(512) usually beats both, SHA-256 and SHA-512 on 64-bit machines.
577 * - It even matches their performance if using hardware accelerated implementations.
578 */
579 std::string_view default_hash_algo() noexcept;
580
581 /**
582 * Encrypt then sign the source producing a cipherpack stream passed to the CipherpackListener if opt-in and also optionally store into destination_fname.
583 *
584 * @param crypto_cfg Used CryptoConfig, consider using CryptoConfig::getDefault()
585 * @param enc_pub_keys Public keys of the receiver, used to encrypt the symmetric-key for multiple parties.
586 * @param sign_sec_key_fname Private key of the sender, used to sign the DER-Header-1 incl encrypted symmetric-key for authenticity.
587 * @param passphrase Passphrase for `sign_sec_key_fname`, may be an empty secure_string for no passphrase.
588 * @param source The source jau::io::ByteInStream of the plaintext message.
589 * @param target_path Optional target path for the message, user application specific.
590 * @param subject Optional subject of message, user application specific.
591 * @param plaintext_version Version of this plaintext message, user semantic
592 * @param plaintext_version_parent Version of this plaintext message's preceding message, user application specific
593 * @param listener CipherpackListener listener used for notifications and optionally
594 * to send the ciphertext destination bytes via CipherpackListener::contentProcessed()
595 * @param plaintext_hash_algo Optional hash algorithm for the plaintext message, produced for convenience and not wired. See default_hash_algo().
596 * Pass an empty string to disable.
597 * @param destination_fname Optional filename of the ciphertext destination file, not used if empty (default). If not empty and file already exists, file will be overwritten.
598 * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not.
599 *
600 * @see @ref cipherpack_overview "Cipherpack Overview"
601 * @see @ref cipherpack_stream "Cipherpack Data Stream"
602 * @see checkSignThenDecrypt()
603 * @see CipherpackListener
604 * @see [jau::io::ByteInStream](https://jausoft.com/projects/jaulib/build/documentation/cpp/html/classjau_1_1io_1_1ByteInStream.html#details)
605 */
606 PackHeader encryptThenSign(const CryptoConfig& crypto_cfg,
607 const std::vector<std::string>& enc_pub_keys,
608 const std::string& sign_sec_key_fname, const jau::io::secure_string& passphrase,
609 jau::io::ByteInStream& source,
610 const std::string& target_path, const std::string& subject,
611 const std::string& plaintext_version,
612 const std::string& plaintext_version_parent,
613 CipherpackListenerRef listener,
614 const std::string_view& plaintext_hash_algo,
615 const std::string destination_fname = "");
616
617 /**
618 * Verify signature then decrypt the source passing to the CipherpackListener if opt-in and also optionally store into destination file.
619 *
620 * @param sign_pub_keys Authorized sender public-keys to verify the sender's signature
621 * and hence the authenticity of the message incl. encrypted symmetric-key and ciphertext message.
622 * @param dec_sec_key_fname Private key of the receiver, used to decrypt the symmetric-key.
623 * It shall match one of the keys used to encrypt.
624 * @param passphrase The passphrase for `dec_sec_key_fname`, may be an empty secure_string for no passphrase.
625 * @param source The source jau::io::ByteInStream of the cipherpack containing the encrypted message.
626 * @param listener The CipherpackListener listener used for notifications and optionally
627 * to send the plaintext destination bytes via CipherpackListener::contentProcessed()
628 * @param plaintext_hash_algo Optional hash algorithm for the plaintext message, produced for convenience and not wired. See default_hash_algo().
629 * Pass an empty string to disable.
630 * @param destination_fname Optional filename of the plaintext destination file, not used if empty (default). If not empty and file already exists, file will be overwritten.
631 * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not.
632 *
633 * @see @ref cipherpack_overview "Cipherpack Overview"
634 * @see @ref cipherpack_stream "Cipherpack Data Stream"
635 * @see encryptThenSign()
636 * @see CipherpackListener
637 * @see [jau::io::ByteInStream](https://jausoft.com/projects/jaulib/build/documentation/cpp/html/classjau_1_1io_1_1ByteInStream.html#details)
638 */
639 PackHeader checkSignThenDecrypt(const std::vector<std::string>& sign_pub_keys,
640 const std::string& dec_sec_key_fname, const jau::io::secure_string& passphrase,
641 jau::io::ByteInStream& source,
642 CipherpackListenerRef listener,
643 const std::string_view& plaintext_hash_algo,
644 const std::string destination_fname = "");
645
646 /**
647 * Hash utility functions to produce a hash file compatible to `sha256sum`
648 * as well as to produce the hash value itself for validation.
649 */
650 namespace hash_util {
651 /** Return a lower-case file suffix used to store a `sha256sum` compatible hash signature w/o dot and w/o dashes. */
652 std::string file_suffix(const std::string& algo) noexcept;
653
654 /**
655 * Append the hash signature to the text file out_file
656 *
657 * The hash signature is composed as follows
658 * - hash algo name
659 * - space
660 * - hash value
661 * - space
662 * - `*` to denote binary processing
663 * - hashed file name
664 *
665 * The hash signature is similar to `sha256sum` output, but the added hash algo name upfront.
666 *
667 * @param out_file the text file to append hash signature of hashed_file.
668 * @param hashed_file the file of the hash signature
669 * @param hash_algo the hash algo name used
670 * @param hash_value the hash value of hashed_file
671 * @return true if successful, otherwise false
672 */
673 bool append_to_file(const std::string& out_file, const std::string& hashed_file, const std::string_view& hash_algo, const std::vector<uint8_t>& hash_value) noexcept;
674
675 /**
676 * Return the calculated hash value using given algo name and byte input stream.
677 * @param algo the hash algo name
678 * @param source the byte input stream
679 * @return the calculated hash value or nullptr in case of error
680 */
681 std::unique_ptr<std::vector<uint8_t>> calc(const std::string_view& algo, jau::io::ByteInStream& source) noexcept;
682
683 /**
684 * Return the calculated hash value using given algo name and the bytes of a single file or all files if denoting a directory.
685 * @param algo the hash algo name
686 * @param path_or_uri given path or uri, either a URI denoting a single file, a single file path or directory path for which all files (not symbolic links) are considered
687 * @param bytes_hashed returns overall bytes hashed
688 * @param timeout in case `path_or_uri` refers to an URI, timeout is being used as maximum duration to wait for next bytes. Defaults to 20_s.
689 * @return the calculated hash value or nullptr in case of error
690 */
691 std::unique_ptr<std::vector<uint8_t>> calc(const std::string_view& algo, const std::string& path_or_uri, uint64_t& bytes_hashed, jau::fraction_i64 timeout=20_s) noexcept;
692 }
693
694 /**@}*/
695
696} // namespace cipherpack
697
698/** \example commandline.cpp
699 * cipherpack command line tool.
700 *
701 * Examples:
702 * - File based operation
703 * - `cipherpack pack -epk test_keys/terminal_rsa1.pub.pem -ssk test_keys/host_rsa1 -out a.enc plaintext.bin`
704 * - `cipherpack unpack -spk test_keys/host_rsa1.pub.pem -dsk test_keys/terminal_rsa1 -out a.dec a.enc`
705 * - `cipherpack hash -out a.hash jaulib/test_data`
706 * - Pipe based operation
707 * - `cat plaintext.bin | cipherpack pack -epk test_keys/terminal_rsa1.pub.pem -ssk test_keys/host_rsa1 > a.enc`
708 * - `cat a.enc | cipherpack unpack -spk test_keys/host_rsa1.pub.pem -dsk test_keys/terminal_rsa1 > a.dec`
709 * - `cat a.dec | cipherpack hash jaulib/test_data`
710 * - Pipe based full streaming
711 * - `cat plaintext.bin | cipherpack pack -epk test_keys/terminal_rsa1.pub.pem -ssk test_keys/host_rsa1 | cipherpack unpack -spk test_keys/host_rsa1.pub.pem -dsk test_keys/terminal_rsa1 > a.dec`
712 *
713 */
714
715/** \example test_01_cipherpack.cpp
716 * Unit test, testing encrypting to and decrypting from a cipherpack stream using different sources.
717 *
718 * Unit test also covers error cases.
719 */
720
721#endif /* JAU_CIPHERPACK_HPP_ */
Listener for events occurring while processing a cipherpack message via encryptThenSign() and checkSi...
Definition: cipherpack.hpp:442
static std::string java_class() noexcept
Definition: cipherpack.hpp:542
virtual bool contentProcessed(const bool decrypt_mode, const content_type ctype, cipherpack::secure_vector< uint8_t > &data, const bool is_final) noexcept
User callback to receive the actual processed content, either the generated cipherpack or plaintext c...
Definition: cipherpack.hpp:527
virtual bool notifyProgress(const bool decrypt_mode, const uint64_t plaintext_size, const uint64_t bytes_processed) noexcept
User notification about content streaming progress.
Definition: cipherpack.hpp:485
std::string toString() const noexcept override
Definition: cipherpack.hpp:537
bool operator!=(const CipherpackListener &rhs) const noexcept
Definition: cipherpack.hpp:555
std::string get_java_class() const noexcept override
Definition: cipherpack.hpp:539
virtual bool getSendContent(const bool decrypt_mode) const noexcept
User provided information whether process shall send the processed content via contentProcessed() or ...
Definition: cipherpack.hpp:508
virtual void notifyEnd(const bool decrypt_mode, const PackHeader &header) noexcept
User notification of successful completion.
Definition: cipherpack.hpp:497
~CipherpackListener() noexcept override
Definition: cipherpack.hpp:535
virtual bool operator==(const CipherpackListener &rhs) const noexcept
Default comparison operator, merely testing for same memory reference.
Definition: cipherpack.hpp:552
virtual void notifyError(const bool decrypt_mode, const PackHeader &header, const std::string &msg) noexcept
User notification about an error via text message and preliminary PackHeader.
Definition: cipherpack.hpp:457
virtual bool notifyHeader(const bool decrypt_mode, const PackHeader &header) noexcept
User notification of preliminary PackHeader w/o optional hash of the plaintext message.
Definition: cipherpack.hpp:468
static const std::string package_magic
Package magic CIPHERPACK_0004.
Definition: cipherpack.hpp:266
Cipherpack header less encrypted keys or signatures as described in Cipherpack Data Stream.
Definition: cipherpack.hpp:275
const std::vector< uint8_t > & sender_fingerprint() const noexcept
Return the sender's public-key fingerprint used to sign, see Cipherpack Data Stream.
Definition: cipherpack.hpp:376
PackHeader(const std::string &_target_path, const uint64_t &_plaintext_size, const jau::fraction_timespec &_ts_creation, const std::string &_subject, const std::string &_pversion, const std::string &_pversion_parent, const CryptoConfig &_crypto_cfg, const std::vector< uint8_t > &_sender_fingerprint, const std::vector< std::vector< uint8_t > > &_recevr_fingerprints, const size_t _used_recevr_key_idx, const bool _valid)
Complete ctor, denoting a complete package header, see Cipherpack Data Stream.
Definition: cipherpack.hpp:327
constexpr const std::string & plaintext_version() const noexcept
Returns version of this plaintext message, user semantic, see Cipherpack Data Stream.
Definition: cipherpack.hpp:366
void set_plaintext_size(const uint64_t v) noexcept
Definition: cipherpack.hpp:357
void set_plaintext_hash(const std::string &algo, const std::vector< uint8_t > &hash) noexcept
Set optional hash-algo and -value of the plaintext messages, produced for convenience and not wired.
Definition: cipherpack.hpp:415
const std::vector< uint8_t > & plaintext_hash() const noexcept
Return optional hash value of the plaintext message, produced for convenience and not wired.
Definition: cipherpack.hpp:408
const std::string & plaintext_hash_algo() const noexcept
Return optional hash algorithm for the plaintext message, produced for convenience and not wired.
Definition: cipherpack.hpp:398
constexpr const CryptoConfig & crypto_config() const noexcept
Definition: cipherpack.hpp:371
uint64_t plaintext_size() const noexcept
Returns the plaintext message size in bytes, zero if not determined yet.
Definition: cipherpack.hpp:355
constexpr const std::string & subject() const noexcept
Returns the designated subject of message, see Cipherpack Data Stream.
Definition: cipherpack.hpp:363
constexpr const std::string & plaintext_version_parent() const noexcept
Returns version of this plaintext message's preceding message, user semantic, see Cipherpack Data Str...
Definition: cipherpack.hpp:369
const std::vector< std::vector< uint8_t > > & receiver_fingerprints() const noexcept
Return the list of receiver's public-keys fingerprints used to encrypt the symmetric-key,...
Definition: cipherpack.hpp:381
PackHeader()
default ctor, denoting an invalid package header.
Definition: cipherpack.hpp:293
bool isValid() const noexcept
Definition: cipherpack.hpp:429
PackHeader(const jau::fraction_timespec &ts_creation)
ctor, denoting an invalid package header.
Definition: cipherpack.hpp:310
ssize_t receiver_key_index() const noexcept
Return the index of the matching receiver's public-key fingerprint used to decrypt the symmetric-key,...
Definition: cipherpack.hpp:388
const std::string & target_path() const noexcept
Returns the designated target path for this plaintext message, see Cipherpack Data Stream.
Definition: cipherpack.hpp:352
constexpr const jau::fraction_timespec & creation_time() const noexcept
Returns the creation time since Unix epoch, see Cipherpack Data Stream.
Definition: cipherpack.hpp:360
This class represents an abstract data source object.
Definition: cipherpack.hpp:172
std::string id() const override
Definition: cipherpack.hpp:191
bool end_of_data() const override
Definition: cipherpack.hpp:188
size_t peek(uint8_t out[], size_t length, size_t peek_offset) const override
Definition: cipherpack.hpp:185
WrappingDataSource(jau::io::ByteInStream &in_)
Definition: cipherpack.hpp:176
size_t read(uint8_t out[], size_t length) override
Definition: cipherpack.hpp:179
jau::io::ByteInStream & in
Definition: cipherpack.hpp:174
bool check_available(size_t n) override
Definition: cipherpack.hpp:182
size_t get_bytes_read() const override
Definition: cipherpack.hpp:194
void print_info() noexcept
Definition: crypto0.cpp:87
static environment & get() noexcept
Definition: cipherpack.hpp:150
std::shared_ptr< Botan::Public_Key > load_public_key(const std::string &pubkey_fname)
Definition: crypto0.cpp:181
std::shared_ptr< CipherpackListener > CipherpackListenerRef
Definition: cipherpack.hpp:559
std::shared_ptr< Botan::Private_Key > load_private_key(const std::string &privatekey_fname, const jau::io::secure_string &passphrase)
Definition: crypto0.cpp:310
std::vector< T, Botan::secure_allocator< T > > secure_vector
Definition: cipherpack.hpp:166
PackHeader encryptThenSign(const CryptoConfig &crypto_cfg, const std::vector< std::string > &enc_pub_keys, const std::string &sign_sec_key_fname, const jau::io::secure_string &passphrase, jau::io::ByteInStream &source, const std::string &target_path, const std::string &subject, const std::string &plaintext_version, const std::string &plaintext_version_parent, CipherpackListenerRef listener, const std::string_view &plaintext_hash_algo, const std::string destination_fname="")
Encrypt then sign the source producing a cipherpack stream passed to the CipherpackListener if opt-in...
Definition: crypto1.cpp:518
std::string_view default_hash_algo() noexcept
Name of default hash algo for the plaintext message, e.g.
Definition: crypto0.cpp:110
PackHeader checkSignThenDecrypt(const std::vector< std::string > &sign_pub_keys, const std::string &dec_sec_key_fname, const jau::io::secure_string &passphrase, jau::io::ByteInStream &source, CipherpackListenerRef listener, const std::string_view &plaintext_hash_algo, const std::string destination_fname="")
Verify signature then decrypt the source passing to the CipherpackListener if opt-in and also optiona...
Definition: crypto1.cpp:1134
#define JAVA_MAIN_PACKAGE
Definition: cipherpack.hpp:141
std::unique_ptr< std::vector< uint8_t > > calc(const std::string_view &algo, const std::string &path_or_uri, uint64_t &bytes_hashed, jau::fraction_i64 timeout=20_s) noexcept
Return the calculated hash value using given algo name and the bytes of a single file or all files if...
Definition: crypto0.cpp:411
std::string file_suffix(const std::string &algo) noexcept
Return a lower-case file suffix used to store a sha256sum compatible hash signature w/o dot and w/o d...
Definition: crypto0.cpp:348
bool append_to_file(const std::string &out_file, const std::string &hashed_file, const std::string_view &hash_algo, const std::vector< uint8_t > &hash_value) noexcept
Append the hash signature to the text file out_file.
Definition: crypto0.cpp:358
CryptoConfig, contains crypto algorithms settings given at encryption wired via the Cipherpack Data S...
Definition: cipherpack.hpp:205
bool valid() const noexcept
Definition: crypto0.cpp:131
CryptoConfig(const std::string &pk_type_, const std::string &pk_fingerprt_hash_algo_, const std::string &pk_enc_padding_algo_, const std::string &pk_enc_hash_algo_, const std::string &pk_sign_algo_, const std::string &sym_enc_algo_, const size_t sym_enc_nonce_bytes_) noexcept
Definition: cipherpack.hpp:237
static CryptoConfig getDefault() noexcept
Returns default CryptoConfig.
Definition: crypto0.cpp:123
std::string pk_enc_padding_algo
Definition: cipherpack.hpp:208
std::string pk_fingerprt_hash_algo
Definition: cipherpack.hpp:207
std::string pk_enc_hash_algo
Definition: cipherpack.hpp:209
std::string to_string() const noexcept
Definition: crypto0.cpp:141