diff options
author | Sven Gothel <[email protected]> | 2022-06-03 06:40:50 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2022-06-03 06:40:50 +0200 |
commit | d09593b0a8ec180b8a6b1d925fcd53d3848f14fe (patch) | |
tree | 7c30c538da1a0fa0629a83d0b1beaae506439799 | |
parent | d826f8c14fbb2a4f072ffd681728df4e0ad04c82 (diff) |
Simplify *encrypt* and *decrypt* API, use destination_fname as an optional file sink, resuding Java API mapping; Working 1st Java unit test
-rw-r--r-- | examples/cipherpack/commandline.cpp | 10 | ||||
-rw-r--r-- | examples/java/Cipherpack.java | 17 | ||||
-rw-r--r-- | include/cipherpack/cipherpack.hpp | 65 | ||||
-rw-r--r-- | java/jni/cipherpack/Cipherpack.cxx | 147 | ||||
-rw-r--r-- | java/org/cipherpack/Cipherpack.java | 122 | ||||
-rw-r--r-- | java/org/cipherpack/PackHeader.java | 11 | ||||
-rw-r--r-- | src/cipherpack/crypto0.cpp | 2 | ||||
-rw-r--r-- | src/cipherpack/crypto1.cpp | 74 | ||||
-rw-r--r-- | test/cipherpack/data_test.hpp | 1 | ||||
-rw-r--r-- | test/cipherpack/test_01_cipherpack.cpp | 101 | ||||
-rw-r--r-- | test/java/test/org/cipherpack/Test01Cipherpack.java | 161 | ||||
-rw-r--r-- | test/java/test/org/cipherpack/data_test.java | 61 |
12 files changed, 455 insertions, 317 deletions
diff --git a/examples/cipherpack/commandline.cpp b/examples/cipherpack/commandline.cpp index 4ea4bc1..aa8a739 100644 --- a/examples/cipherpack/commandline.cpp +++ b/examples/cipherpack/commandline.cpp @@ -37,7 +37,6 @@ int main(int argc, char *argv[]) print_usage(argv[0]); return -1; } - const bool overwrite = true; const std::string command = argv[++argi]; if( command == "pack") { @@ -93,8 +92,8 @@ int main(int argc, char *argv[]) enc_pub_keys, sign_sec_key_fname, sign_sec_key_passphrase, *source, target_path, intention, payload_version, payload_version_parent, - fname_output, overwrite, - std::make_shared<cipherpack::CipherpackListener>()); + std::make_shared<cipherpack::CipherpackListener>(), + fname_output); jau::PLAIN_PRINT(true, "Pack: Encrypted %s to %s\n", source_name.c_str(), fname_output.c_str()); jau::PLAIN_PRINT(true, "Pack: %s\n", ph.toString(true, true).c_str()); return ph.isValid() ? 0 : -1; @@ -136,8 +135,9 @@ int main(int argc, char *argv[]) source = std::make_unique<jau::io::ByteInStream_File>(source_name, true /* use_binary */); } cipherpack::PackHeader ph = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key_fname, dec_sec_key_passphrase, - *source, fname_output, overwrite, - std::make_shared<cipherpack::CipherpackListener>()); + *source, + std::make_shared<cipherpack::CipherpackListener>(), + fname_output); // dec_sec_key_passphrase.resize(0); jau::PLAIN_PRINT(true, "Unpack: Decypted %s to %s\n", source_name.c_str(), fname_output.c_str()); jau::PLAIN_PRINT(true, "Unpack: %s\n", ph.toString(true, true).c_str()); diff --git a/examples/java/Cipherpack.java b/examples/java/Cipherpack.java index 7c2a901..9fd82a4 100644 --- a/examples/java/Cipherpack.java +++ b/examples/java/Cipherpack.java @@ -51,9 +51,9 @@ public class Cipherpack { } CPFactory.checkInitialized(); - CPUtils.println(System.err, "Direct-BT BluetoothManager initialized!"); - CPUtils.println(System.err, "Direct-BT Native Version "+CPFactory.getNativeVersion()+" (API "+CPFactory.getNativeAPIVersion()+")"); - CPUtils.println(System.err, "Direct-BT Java Version "+CPFactory.getImplVersion()+" (API "+CPFactory.getAPIVersion()+")"); + CPUtils.println(System.err, "Cipherpack initialized!"); + CPUtils.println(System.err, "Cipherpack Native Version "+CPFactory.getNativeVersion()+" (API "+CPFactory.getNativeAPIVersion()+")"); + CPUtils.println(System.err, "Cipherpack Java Version "+CPFactory.getImplVersion()+" (API "+CPFactory.getAPIVersion()+")"); CPUtils.fprintf_td(System.err, "Called with %d arguments: ", argc); for(int i=0; i<argc; i++) { @@ -66,8 +66,8 @@ public class Cipherpack { print_usage(); return; } - final boolean overwrite = true; final String command = args[++argi]; + final long source_timeout_ms = 10000; if( command.equals( "pack" ) ) { final List<String> enc_pub_keys = new ArrayList<String>(); @@ -116,9 +116,10 @@ public class Cipherpack { final PackHeader ph = org.cipherpack.Cipherpack.encryptThenSign( CryptoConfig.getDefault(), enc_pub_keys, sign_sec_key_fname, sign_sec_key_passphrase, - source_loc, target_path, intention, + source_loc, source_timeout_ms, + target_path, intention, payload_version, payload_version_parent, - fname_output, overwrite, new CipherpackListener()); + new CipherpackListener(), fname_output); CPUtils.fprintf_td(System.err, "Pack: Encrypted %s to %s\n", source_loc, fname_output); CPUtils.fprintf_td(System.err, "Pack: %s\n", ph.toString(true, true)); @@ -157,8 +158,8 @@ public class Cipherpack { final PackHeader ph = org.cipherpack.Cipherpack.checkSignThenDecrypt( sign_pub_keys, dec_sec_key_fname, dec_sec_key_passphrase, - source_loc, fname_output, overwrite, - new CipherpackListener()); + source_loc, source_timeout_ms, + new CipherpackListener(), fname_output); // dec_sec_key_passphrase.resize(0); CPUtils.fprintf_td(System.err, "Unpack: Decypted %s to %s\n", source_loc, fname_output); diff --git a/include/cipherpack/cipherpack.hpp b/include/cipherpack/cipherpack.hpp index db813c4..5bdd9b0 100644 --- a/include/cipherpack/cipherpack.hpp +++ b/include/cipherpack/cipherpack.hpp @@ -171,7 +171,7 @@ namespace cipherpack { constexpr static const size_t buffer_size = 4096; /** - * Package magic {@code CIPHERPACK_0001}. + * Package magic {@code CIPHERPACK_0002}. */ static const std::string package_magic; }; @@ -416,33 +416,6 @@ namespace cipherpack { typedef std::shared_ptr<CipherpackListener> CipherpackListenerRef; /** - * Encrypt then sign the source producing a cipherpack stream passed to the destination_fn consumer. - * - * @param crypto_cfg The used CryptoConfig, consider using CryptoConfig::getDefault() - * @param enc_pub_keys The public keys of the receiver (terminal device), used to encrypt the file-key for multiple parties. - * @param sign_sec_key_fname The private key of the host (pack provider), used to sign the DER-Header-1 incl encrypted file-key for authenticity. - * @param passphrase The passphrase for `sign_sec_key_fname`, may be an empty string for no passphrase. - * @param source The source jau::io::ByteInStream of the plaintext payload. - * @param target_path The designated target_path for the decrypted file as written in the DER-Header-1 - * @param payload_version The version of this payload - * @param payload_version_parent The version of this payload's parent - * @param listener The CipherpackListener listener used for notifications and optionally - * to send the ciphertext destination bytes via CipherpackListener::contentProcessed() - * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not. - * - * @see @ref cipherpack_stream "Cipherpack Data Stream" - * @see checkSignThenDecrypt() - */ - PackHeader encryptThenSign(const CryptoConfig& crypto_cfg, - const std::vector<std::string>& enc_pub_keys, - const std::string& sign_sec_key_fname, const std::string& passphrase, - jau::io::ByteInStream& source, - const std::string& target_path, const std::string& intention, - const std::string& payload_version, - const std::string& payload_version_parent, - CipherpackListenerRef listener); - - /** * Encrypt then sign the source producing a cipherpack destination file. * * @param crypto_cfg The used CryptoConfig, consider using CryptoConfig::getDefault() @@ -453,10 +426,9 @@ namespace cipherpack { * @param designated_fname The designated filename for the decrypted file as written in the DER-Header-1 * @param payload_version The version of this payload * @param payload_version_parent The version of this payload's parent - * @param destination_fname The filename of the ciphertext destination file. - * @param overwrite If true, overwrite a potentially existing `outfilename`. * @param listener The CipherpackListener listener used for notifications and optionally * to send the ciphertext destination bytes via CipherpackListener::contentProcessed() + * @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. * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not. * * @see @ref cipherpack_stream "Cipherpack Data Stream" @@ -469,30 +441,8 @@ namespace cipherpack { const std::string& target_path, const std::string& intention, const std::string& payload_version, const std::string& payload_version_parent, - const std::string& destination_fname, const bool overwrite, - CipherpackListenerRef listener); - - /** - * Check cipherpack signature of the source then pass decrypted payload to the destination_fn consumer. - * - * @param sign_pub_keys The potential public keys used by the host (pack provider) to verify the DER-Header-1 signature - * and hence the authenticity of the encrypted file-key. Proves authenticity of the file. - * @param dec_sec_key_fname The private key of the receiver (terminal device), used to decrypt the file-key. - * It shall match one of the keys used to encrypt. - * @param passphrase The passphrase for `dec_sec_key_fname`, may be an empty string for no passphrase. - * @param source The source jau::io::ByteInStream of the cipherpack containing the encrypted payload. - * @param listener The CipherpackListener listener used for notifications and optionally - * to send the plaintext destination bytes via CipherpackListener::contentProcessed() - * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not. - * - * @see @ref cipherpack_stream "Cipherpack Data Stream" - * @see encryptThenSign() - * - */ - PackHeader checkSignThenDecrypt(const std::vector<std::string>& sign_pub_keys, - const std::string &dec_sec_key_fname, const std::string &passphrase, - jau::io::ByteInStream &source, - CipherpackListenerRef listener); + CipherpackListenerRef listener, + const std::string destination_fname = ""); /** * Check cipherpack signature of the source then decrypt into the plaintext destination file. @@ -503,10 +453,9 @@ namespace cipherpack { * It shall match one of the keys used to encrypt. * @param passphrase The passphrase for `dec_sec_key_fname`, may be an empty string for no passphrase. * @param source The source jau::io::ByteInStream of the cipherpack containing the encrypted payload. - * @param destination_fname The filename of the plaintext destination file. - * @param overwrite If true, overwrite a potentially existing `destination_fname`. * @param listener The CipherpackListener listener used for notifications and optionally * to send the plaintext destination bytes via CipherpackListener::contentProcessed() + * @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. * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not. * * @see @ref cipherpack_stream "Cipherpack Data Stream" @@ -516,8 +465,8 @@ namespace cipherpack { PackHeader checkSignThenDecrypt(const std::vector<std::string>& sign_pub_keys, const std::string &dec_sec_key_fname, const std::string &passphrase, jau::io::ByteInStream &source, - const std::string &destination_fname, const bool overwrite, - CipherpackListenerRef listener); + CipherpackListenerRef listener, + const std::string destination_fname = ""); } // namespace cipherpack diff --git a/java/jni/cipherpack/Cipherpack.cxx b/java/jni/cipherpack/Cipherpack.cxx index ce5c3af..87c7684 100644 --- a/java/jni/cipherpack/Cipherpack.cxx +++ b/java/jni/cipherpack/Cipherpack.cxx @@ -34,57 +34,32 @@ using namespace cipherpack; using namespace jau::fractions_i64_literals; -/** - private native PackHeader encryptThenSignImpl1(final CryptoConfig crypto_cfg, - final String[] enc_pub_keys, - final String sign_sec_key_fname, final String passphrase, - final ByteInStream_Feed source, - final String target_path, final String intention, - final String payload_version, - final String payload_version_parent, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener); - */ jobject Java_org_cipherpack_Cipherpack_encryptThenSignImpl1(JNIEnv *env, jclass jclazz, - jobject jccfg, jobjectArray jenc_pub_keys, + jobject jccfg, jobject jenc_pub_keys, jstring jsign_sec_key_fname, jstring jpassphrase, jobject jsource_feed, jstring jtarget_path, jstring jintention, jstring jpayload_version, jstring jpayload_version_parent, - jstring jdestination_fname, jboolean joverwrite, - jobject cpListener) + jobject cpListener, jstring jdestination_fname) { try { jau::shared_ptr_ref<jau::io::ByteInStream_Feed> refFeed(env, jsource_feed); // hold until done jau::shared_ptr_ref<cipherpack::CipherpackListener> refListener(env, cpListener); // hold until done - CryptoConfig ccfg = jcipherpack::to_CryptoConfig(env, jccfg); - - const size_t enc_pub_keys_size = env->GetArrayLength(jenc_pub_keys); - if( 0 >= enc_pub_keys_size ) { - throw jau::IllegalArgumentException("enc_pub_keys array size "+std::to_string(enc_pub_keys_size)+" <= 0", E_FILE_LINE); - } - jau::JNICriticalArray<jobject, jobjectArray> criticalArray(env); // RAII - release - jobject * enc_pub_keys_ptr = criticalArray.get(jenc_pub_keys, criticalArray.Mode::NO_UPDATE_AND_RELEASE); - if( NULL == enc_pub_keys_ptr ) { - throw jau::InternalError("GetPrimitiveArrayCritical(address enc_pub_keys array) is null", E_FILE_LINE); - } - std::vector<std::string> enc_pub_keys; - for(size_t i=0; i<enc_pub_keys_size; ++i) { - std::string enc_pub_key = jau::from_jstring_to_string(env, (jstring)enc_pub_keys_ptr[i]); - enc_pub_keys.push_back(enc_pub_key); - } + CryptoConfig ccfg = jcipherpack::to_CryptoConfig(env, jccfg); + std::vector<std::string> enc_pub_keys = jau::convert_jlist_string_to_vector(env, jenc_pub_keys); std::string sign_sec_key_fname = jau::from_jstring_to_string(env, jsign_sec_key_fname); std::string passphrase = jau::from_jstring_to_string(env, jpassphrase); std::string target_path = jau::from_jstring_to_string(env, jtarget_path); std::string intention = jau::from_jstring_to_string(env, jintention); std::string payload_version = jau::from_jstring_to_string(env, jpayload_version); std::string payload_version_parent = jau::from_jstring_to_string(env, jpayload_version_parent); - std::string destination_fname = jau::from_jstring_to_string(env, jdestination_fname); + std::string destination_fname = nullptr != jdestination_fname ? jau::from_jstring_to_string(env, jdestination_fname) : ""; PackHeader ph = encryptThenSign(ccfg, enc_pub_keys, sign_sec_key_fname, passphrase, *refFeed, - target_path, intention, payload_version, payload_version_parent, refListener.shared_ptr()); + target_path, intention, payload_version, payload_version_parent, + refListener.shared_ptr(), destination_fname); jobject jph = jcipherpack::to_jPackHeader(env, ph); @@ -95,66 +70,67 @@ jobject Java_org_cipherpack_Cipherpack_encryptThenSignImpl1(JNIEnv *env, jclass return nullptr; } -/** - private native PackHeader encryptThenSignImpl1(final CryptoConfig crypto_cfg, - final String[] enc_pub_keys, - final String sign_sec_key_fname, final String passphrase, - final String source_loc, - final String target_path, final String intention, - final String payload_version, - final String payload_version_parent, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener); - */ -jobject Java_org_cipherpack_Cipherpack_encryptThenSignImpl1(JNIEnv *env, jclass jclazz, - jobject jccfg, jobjectArray jenc_pub_keys, +jobject Java_org_cipherpack_Cipherpack_encryptThenSignImpl2(JNIEnv *env, jclass jclazz, + jobject jccfg, jobject jenc_pub_keys, jstring jsign_sec_key_fname, jstring jpassphrase, - jstring jsource_loc, + jstring jsource_loc, jlong jsource_timeout_ms, jstring jtarget_path, jstring jintention, jstring jpayload_version, jstring jpayload_version_parent, - jstring jdestination_fname, jboolean joverwrite, - jobject cpListener) + jobject cpListener, jstring jdestination_fname) { try { jau::shared_ptr_ref<cipherpack::CipherpackListener> refListener(env, cpListener); // hold until done - CryptoConfig ccfg = jcipherpack::to_CryptoConfig(env, jccfg); - - const size_t enc_pub_keys_size = env->GetArrayLength(jenc_pub_keys); - if( 0 >= enc_pub_keys_size ) { - throw jau::IllegalArgumentException("enc_pub_keys array size "+std::to_string(enc_pub_keys_size)+" <= 0", E_FILE_LINE); - } - jau::JNICriticalArray<jobject, jobjectArray> criticalArray(env); // RAII - release - jobject * enc_pub_keys_ptr = criticalArray.get(jenc_pub_keys, criticalArray.Mode::NO_UPDATE_AND_RELEASE); - if( NULL == enc_pub_keys_ptr ) { - throw jau::InternalError("GetPrimitiveArrayCritical(address enc_pub_keys array) is null", E_FILE_LINE); - } - std::vector<std::string> enc_pub_keys; - for(size_t i=0; i<enc_pub_keys_size; ++i) { - std::string enc_pub_key = jau::from_jstring_to_string(env, (jstring)enc_pub_keys_ptr[i]); - enc_pub_keys.push_back(enc_pub_key); - } + CryptoConfig ccfg = jcipherpack::to_CryptoConfig(env, jccfg); + std::vector<std::string> enc_pub_keys = jau::convert_jlist_string_to_vector(env, jenc_pub_keys); std::string sign_sec_key_fname = jau::from_jstring_to_string(env, jsign_sec_key_fname); std::string passphrase = jau::from_jstring_to_string(env, jpassphrase); - std::string source_loc = jau::from_jstring_to_string(env, jsource_loc); std::unique_ptr<jau::io::ByteInStream> source; const std::string proto = source_loc.substr(0, 5); if( proto == "http:" ) { - source = std::make_unique<jau::io::ByteInStream_URL>(source_loc, 10_s); + source = std::make_unique<jau::io::ByteInStream_URL>(source_loc, (int64_t)jsource_timeout_ms * 1_ms); } else { source = std::make_unique<jau::io::ByteInStream_File>(source_loc, true /* use_binary */); } - std::string target_path = jau::from_jstring_to_string(env, jtarget_path); std::string intention = jau::from_jstring_to_string(env, jintention); std::string payload_version = jau::from_jstring_to_string(env, jpayload_version); std::string payload_version_parent = jau::from_jstring_to_string(env, jpayload_version_parent); - std::string destination_fname = jau::from_jstring_to_string(env, jdestination_fname); + std::string destination_fname = nullptr != jdestination_fname ? jau::from_jstring_to_string(env, jdestination_fname) : ""; PackHeader ph = encryptThenSign(ccfg, enc_pub_keys, sign_sec_key_fname, passphrase, *source, - target_path, intention, payload_version, payload_version_parent, refListener.shared_ptr()); + target_path, intention, payload_version, payload_version_parent, + refListener.shared_ptr(), destination_fname); + + jobject jph = jcipherpack::to_jPackHeader(env, ph); + + return jph; + } catch(...) { + rethrow_and_raise_java_exception(env); + } + return nullptr; +} + + +jobject Java_org_cipherpack_Cipherpack_checkSignThenDecrypt1(JNIEnv *env, jclass jclazz, + jobject jsign_pub_keys, + jstring jdec_sec_key_fname, jstring jpassphrase, + jobject jsource_feed, + jobject cpListener, jstring jdestination_fname) +{ + try { + jau::shared_ptr_ref<jau::io::ByteInStream_Feed> refFeed(env, jsource_feed); // hold until done + jau::shared_ptr_ref<cipherpack::CipherpackListener> refListener(env, cpListener); // hold until done + + std::vector<std::string> sign_pub_keys = jau::convert_jlist_string_to_vector(env, jsign_pub_keys); + std::string dec_sec_key_fname = jau::from_jstring_to_string(env, jdec_sec_key_fname); + std::string passphrase = jau::from_jstring_to_string(env, jpassphrase); + std::string destination_fname = nullptr != jdestination_fname ? jau::from_jstring_to_string(env, jdestination_fname) : ""; + + PackHeader ph = checkSignThenDecrypt(sign_pub_keys, dec_sec_key_fname, passphrase, *refFeed, + refListener.shared_ptr(), destination_fname); jobject jph = jcipherpack::to_jPackHeader(env, ph); @@ -165,4 +141,37 @@ jobject Java_org_cipherpack_Cipherpack_encryptThenSignImpl1(JNIEnv *env, jclass return nullptr; } +jobject Java_org_cipherpack_Cipherpack_checkSignThenDecrypt2(JNIEnv *env, jclass jclazz, + jobject jsign_pub_keys, + jstring jdec_sec_key_fname, jstring jpassphrase, + jstring jsource_loc, jlong jsource_timeout_ms, + jobject cpListener, jstring jdestination_fname) +{ + try { + jau::shared_ptr_ref<cipherpack::CipherpackListener> refListener(env, cpListener); // hold until done + + std::vector<std::string> sign_pub_keys = jau::convert_jlist_string_to_vector(env, jsign_pub_keys); + std::string dec_sec_key_fname = jau::from_jstring_to_string(env, jdec_sec_key_fname); + std::string passphrase = jau::from_jstring_to_string(env, jpassphrase); + std::string source_loc = jau::from_jstring_to_string(env, jsource_loc); + std::unique_ptr<jau::io::ByteInStream> source; + const std::string proto = source_loc.substr(0, 5); + if( proto == "http:" ) { + source = std::make_unique<jau::io::ByteInStream_URL>(source_loc, (int64_t)jsource_timeout_ms * 1_ms); + } else { + source = std::make_unique<jau::io::ByteInStream_File>(source_loc, true /* use_binary */); + } + std::string destination_fname = nullptr != jdestination_fname ? jau::from_jstring_to_string(env, jdestination_fname) : ""; + + PackHeader ph = checkSignThenDecrypt(sign_pub_keys, dec_sec_key_fname, passphrase, *source, + refListener.shared_ptr(), destination_fname); + + jobject jph = jcipherpack::to_jPackHeader(env, ph); + + return jph; + } catch(...) { + rethrow_and_raise_java_exception(env); + } + return nullptr; +} diff --git a/java/org/cipherpack/Cipherpack.java b/java/org/cipherpack/Cipherpack.java index fd16f0d..5482874 100644 --- a/java/org/cipherpack/Cipherpack.java +++ b/java/org/cipherpack/Cipherpack.java @@ -99,10 +99,9 @@ public final class Cipherpack { * @param target_path The designated target_path for the decrypted file as written in the DER-Header-1 * @param payload_version The version of this payload * @param payload_version_parent The version of this payload's parent - * @param destination_fname The filename of the plaintext destination file. - * @param overwrite If true, overwrite a potentially existing `destination_fname`. * @param listener The CipherpackListener listener used for notifications and optionally * to send the ciphertext destination bytes via CipherpackListener::contentProcessed() + * @param destination_fname Optional filename of the plaintext destination file, not used if null or empty (default). If not empty and file already exists, file will be overwritten. * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not. * * @see @ref cipherpack_stream "Cipherpack Data Stream" @@ -115,27 +114,24 @@ public final class Cipherpack { final String target_path, final String intention, final String payload_version, final String payload_version_parent, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener) { - return encryptThenSignImpl(crypto_cfg, - (String[])enc_pub_keys.toArray(), - sign_sec_key_fname, passphrase, - source_feed, - target_path, intention, - payload_version, - payload_version_parent, - destination_fname, overwrite, - listener); + final CipherpackListener listener, final String destination_fname) { + return encryptThenSignImpl1(crypto_cfg, + enc_pub_keys, + sign_sec_key_fname, passphrase, + source_feed, + target_path, intention, + payload_version, + payload_version_parent, + listener, destination_fname); } - private static native PackHeader encryptThenSignImpl(final CryptoConfig crypto_cfg, - final String[] enc_pub_keys, - final String sign_sec_key_fname, final String passphrase, - final ByteInStream_Feed source_feed, - final String target_path, final String intention, - final String payload_version, - final String payload_version_parent, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener); + private static native PackHeader encryptThenSignImpl1(final CryptoConfig crypto_cfg, + final List<String> enc_pub_keys, + final String sign_sec_key_fname, final String passphrase, + final ByteInStream_Feed source_feed, + final String target_path, final String intention, + final String payload_version, + final String payload_version_parent, + final CipherpackListener listener, final String destination_fname); /** * Encrypt then sign the source producing a cipherpack stream passed to the destination_fn consumer. @@ -145,13 +141,13 @@ public final class Cipherpack { * @param sign_sec_key_fname The private key of the host (pack provider), used to sign the DER-Header-1 incl encrypted file-key for authenticity. * @param passphrase The passphrase for `sign_sec_key_fname`, may be an empty string for no passphrase. * @param source_loc The source location of the cipherpack containing the encrypted payload, either a filename or a URL. + * @param source_timeout_ms The timeout in milliseconds for waiting on new bytes from source, e.g. if location is a URL * @param target_path The designated target_path for the decrypted file as written in the DER-Header-1 * @param payload_version The version of this payload * @param payload_version_parent The version of this payload's parent - * @param destination_fname The filename of the plaintext destination file. - * @param overwrite If true, overwrite a potentially existing `destination_fname`. * @param listener The CipherpackListener listener used for notifications and optionally * to send the ciphertext destination bytes via CipherpackListener::contentProcessed() + * @param destination_fname Optional filename of the plaintext destination file, not used if null or empty (default). If not empty and file already exists, file will be overwritten. * @return PackHeader, where true == PackHeader::isValid() if successful, otherwise not. * * @see @ref cipherpack_stream "Cipherpack Data Stream" @@ -160,31 +156,28 @@ public final class Cipherpack { public static PackHeader encryptThenSign(final CryptoConfig crypto_cfg, final List<String> enc_pub_keys, final String sign_sec_key_fname, final String passphrase, - final String source_loc, + final String source_loc, final long source_timeout_ms, final String target_path, final String intention, final String payload_version, final String payload_version_parent, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener) { - return encryptThenSignImpl(crypto_cfg, - (String[])enc_pub_keys.toArray(), - sign_sec_key_fname, passphrase, - source_loc, - target_path, intention, - payload_version, - payload_version_parent, - destination_fname, overwrite, - listener); + final CipherpackListener listener, final String destination_fname) { + return encryptThenSignImpl2(crypto_cfg, + enc_pub_keys, + sign_sec_key_fname, passphrase, + source_loc, source_timeout_ms, + target_path, intention, + payload_version, + payload_version_parent, + listener, destination_fname); } - private static native PackHeader encryptThenSignImpl(final CryptoConfig crypto_cfg, - final String[] enc_pub_keys, - final String sign_sec_key_fname, final String passphrase, - final String source_loc, - final String target_path, final String intention, - final String payload_version, - final String payload_version_parent, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener); + private static native PackHeader encryptThenSignImpl2(final CryptoConfig crypto_cfg, + final List<String> enc_pub_keys, + final String sign_sec_key_fname, final String passphrase, + final String source_loc, final long source_timeout_ms, + final String target_path, final String intention, + final String payload_version, + final String payload_version_parent, + final CipherpackListener listener, final String destination_fname); /** * Check cipherpack signature of the source then decrypt into the plaintext destination file. @@ -194,11 +187,10 @@ public final class Cipherpack { * @param dec_sec_key_fname The private key of the receiver (terminal device), used to decrypt the file-key. * It shall match one of the keys used to encrypt. * @param passphrase The passphrase for `dec_sec_key_fname`, may be an empty string for no passphrase. - * @param source The source ByteInStream_Feed of the cipherpack containing the encrypted payload. - * @param destination_fname The filename of the plaintext destination file. - * @param overwrite If true, overwrite a potentially existing `destination_fname`. + * @param source_feed The source ByteInStream_Feed of the cipherpack containing the encrypted payload. * @param listener The CipherpackListener listener used for notifications and optionally * to send the plaintext destination bytes via CipherpackListener::contentProcessed() + * @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. * @return PackInfo, which is PackInfo::isValid() if successful, otherwise not. * * @see @ref cipherpack_stream "Cipherpack Data Stream" @@ -207,11 +199,17 @@ public final class Cipherpack { */ public static PackHeader checkSignThenDecrypt(final List<String> sign_pub_keys, final String dec_sec_key_fname, final String passphrase, - final ByteInStream_Feed source, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener) { - return null; + final ByteInStream_Feed source_feed, + final CipherpackListener listener, final String destination_fname) { + return checkSignThenDecrypt1(sign_pub_keys, + dec_sec_key_fname, passphrase, + source_feed, + listener, destination_fname); } + private static native PackHeader checkSignThenDecrypt1(final List<String> sign_pub_keys, + final String dec_sec_key_fname, final String passphrase, + final ByteInStream_Feed source_feed, + final CipherpackListener listener, final String destination_fname); /** * Check cipherpack signature of the source then decrypt into the plaintext destination file. @@ -221,11 +219,11 @@ public final class Cipherpack { * @param dec_sec_key_fname The private key of the receiver (terminal device), used to decrypt the file-key. * It shall match one of the keys used to encrypt. * @param passphrase The passphrase for `dec_sec_key_fname`, may be an empty string for no passphrase. - * @param source The source location of the cipherpack containing the encrypted payload, either a filename or a URL. - * @param destination_fname The filename of the plaintext destination file. - * @param overwrite If true, overwrite a potentially existing `destination_fname`. + * @param source_loc The source location of the cipherpack containing the encrypted payload, either a filename or a URL. + * @param source_timeout_ms The timeout in milliseconds for waiting on new bytes from source, e.g. if location is a URL * @param listener The CipherpackListener listener used for notifications and optionally * to send the plaintext destination bytes via CipherpackListener::contentProcessed() + * @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. * @return PackInfo, which is PackInfo::isValid() if successful, otherwise not. * * @see @ref cipherpack_stream "Cipherpack Data Stream" @@ -234,9 +232,15 @@ public final class Cipherpack { */ public static PackHeader checkSignThenDecrypt(final List<String> sign_pub_keys, final String dec_sec_key_fname, final String passphrase, - final String source, - final String destination_fname, final boolean overwrite, - final CipherpackListener listener) { - return null; + final String source_loc, final long source_timeout_ms, + final CipherpackListener listener, final String destination_fname) { + return checkSignThenDecrypt2(sign_pub_keys, + dec_sec_key_fname, passphrase, + source_loc, source_timeout_ms, + listener, destination_fname); } + private static native PackHeader checkSignThenDecrypt2(final List<String> sign_pub_keys, + final String dec_sec_key_fname, final String passphrase, + final String source_loc, final long source_timeout_ms, + final CipherpackListener listener, final String destination_fname); } diff --git a/java/org/cipherpack/PackHeader.java b/java/org/cipherpack/PackHeader.java index 1a4fc64..1b9b4dd 100644 --- a/java/org/cipherpack/PackHeader.java +++ b/java/org/cipherpack/PackHeader.java @@ -54,11 +54,12 @@ public class PackHeader { public final String host_key_fingerprint; /** List of public keys fingerprints used to encrypt the file-key, see @ref cipherpack_stream "Cipherpack Data Stream". */ - public final String[] term_keys_fingerprint; + public final List<String> term_keys_fingerprint; /** Index of the matching public key fingerprints used to decrypt the file-key or -1 if not found or performing the encryption operation.. */ public final int term_key_fingerprint_used_idx; + /** True if packet is valid, otherwise false. */ public final boolean valid; PackHeader() { @@ -70,7 +71,7 @@ public class PackHeader { this.payload_version_parent = "0"; this.crypto_cfg = new CryptoConfig(); this.host_key_fingerprint = ""; - this.term_keys_fingerprint = new String[0]; + this.term_keys_fingerprint = new ArrayList<String>(); this.term_key_fingerprint_used_idx = -1; this.valid = false; } @@ -82,7 +83,7 @@ public class PackHeader { final String pversion, final String pversion_parent, final CryptoConfig crypto_cfg_, final String host_key_fingerprint_, - final String[] term_keys_fingerprint_, + final List<String> term_keys_fingerprint_, final int term_key_fingerprint_used_idx_, final boolean valid_) { this.target_path = target_path_; @@ -110,7 +111,7 @@ public class PackHeader { final StringBuilder term_fingerprint = new StringBuilder(); { if( 0 <= term_key_fingerprint_used_idx ) { - term_fingerprint.append( "dec '").append(term_keys_fingerprint[term_key_fingerprint_used_idx]).append("', "); + term_fingerprint.append( "dec '").append(term_keys_fingerprint.get(term_key_fingerprint_used_idx)).append("', "); } if( force_all_fingerprints || 0 > term_key_fingerprint_used_idx ) { term_fingerprint.append("enc["); @@ -137,6 +138,8 @@ public class PackHeader { return res; } + public final boolean isValid() { return valid; } + /** * Return a string representation * @return string representation diff --git a/src/cipherpack/crypto0.cpp b/src/cipherpack/crypto0.cpp index abd252e..0a5ebb0 100644 --- a/src/cipherpack/crypto0.cpp +++ b/src/cipherpack/crypto0.cpp @@ -39,7 +39,7 @@ void Environment::env_init() noexcept { curl_global_init(CURL_GLOBAL_ALL); } -const std::string Constants::package_magic = "CIPHERPACK_0001"; +const std::string Constants::package_magic = "CIPHERPACK_0002"; static const std::string default_pk_type = "RSA"; static const std::string default_pk_fingerprt_hash_algo = "SHA-256"; diff --git a/src/cipherpack/crypto1.cpp b/src/cipherpack/crypto1.cpp index 7713c0e..ffb731c 100644 --- a/src/cipherpack/crypto1.cpp +++ b/src/cipherpack/crypto1.cpp @@ -339,31 +339,24 @@ PackHeader cipherpack::encryptThenSign(const CryptoConfig& crypto_cfg, const std::string& target_path, const std::string& intention, const std::string& payload_version, const std::string& payload_version_parent, - CipherpackListenerRef listener) { + CipherpackListenerRef listener, + const std::string destination_fname) { + Environment::env_init(); const bool decrypt_mode = false; - PackHeader ph = encryptThenSign_Impl(crypto_cfg, - enc_pub_keys, - sign_sec_key_fname, passphrase, - source, - target_path, intention, - payload_version, - payload_version_parent, - listener); - listener->notifyEnd(decrypt_mode, ph, ph.isValid()); - return ph; -} -PackHeader cipherpack::encryptThenSign(const CryptoConfig& crypto_cfg, - const std::vector<std::string>& enc_pub_keys, - const std::string& sign_sec_key_fname, const std::string& passphrase, - jau::io::ByteInStream& source, - const std::string& target_path, const std::string& intention, - const std::string& payload_version, - const std::string& payload_version_parent, - const std::string& destination_fname, const bool overwrite, - CipherpackListenerRef listener) { - const bool decrypt_mode = false; - Environment::env_init(); + if( destination_fname.empty() ) { + PackHeader ph = encryptThenSign_Impl(crypto_cfg, + enc_pub_keys, + sign_sec_key_fname, passphrase, + source, + target_path, intention, + payload_version, + payload_version_parent, + listener); + listener->notifyEnd(decrypt_mode, ph, ph.isValid()); + return ph; + } + const jau::fraction_timespec ts_creation = jau::getWallClockTime(); PackHeader header(target_path, @@ -423,14 +416,14 @@ PackHeader cipherpack::encryptThenSign(const CryptoConfig& crypto_cfg, { const jau::fs::file_stats output_stats(destination_fname); if( output_stats.exists() ) { - if( overwrite && output_stats.is_file() ) { + if( output_stats.is_file() ) { if( !jau::fs::remove(destination_fname, false /* recursive */) ) { ERR_PRINT2("Encrypt failed: Failed deletion of existing output file %s", output_stats.to_string(true).c_str()); my_listener->notifyEnd(decrypt_mode, header, false); return header; } } else { - ERR_PRINT2("Encrypt failed: Not overwriting existing output file %s", output_stats.to_string(true).c_str()); + ERR_PRINT2("Encrypt failed: Not overwriting existing %s", output_stats.to_string(true).c_str()); my_listener->notifyEnd(decrypt_mode, header, false); return header; } @@ -835,22 +828,19 @@ static PackHeader checkSignThenDecrypt_Impl(const std::vector<std::string>& sign PackHeader cipherpack::checkSignThenDecrypt(const std::vector<std::string>& sign_pub_keys, const std::string& dec_sec_key_fname, const std::string& passphrase, jau::io::ByteInStream& source, - CipherpackListenerRef listener) { + CipherpackListenerRef listener, + const std::string destination_fname) { + Environment::env_init(); const bool decrypt_mode = true; - PackHeader ph = checkSignThenDecrypt_Impl(sign_pub_keys, - dec_sec_key_fname, passphrase, - source, listener); - listener->notifyEnd(decrypt_mode, ph, ph.isValid()); - return ph; -} -PackHeader cipherpack::checkSignThenDecrypt(const std::vector<std::string>& sign_pub_keys, - const std::string& dec_sec_key_fname, const std::string& passphrase, - jau::io::ByteInStream& source, - const std::string& destination_fname, const bool overwrite, - CipherpackListenerRef listener) { - const bool decrypt_mode = true; - Environment::env_init(); + if( destination_fname.empty() ) { + PackHeader ph = checkSignThenDecrypt_Impl(sign_pub_keys, + dec_sec_key_fname, passphrase, + source, listener); + listener->notifyEnd(decrypt_mode, ph, ph.isValid()); + return ph; + } + jau::fraction_timespec ts_creation; PackHeader header(ts_creation); @@ -895,14 +885,14 @@ PackHeader cipherpack::checkSignThenDecrypt(const std::vector<std::string>& sign { const jau::fs::file_stats output_stats(destination_fname); if( output_stats.exists() ) { - if( overwrite && output_stats.is_file() ) { + if( output_stats.is_file() ) { if( !jau::fs::remove(destination_fname, false /* recursive */) ) { - ERR_PRINT2("Decrypt failed: Failed deletion of existing output file %s", destination_fname.c_str()); + ERR_PRINT2("Decrypt failed: Failed deletion of existing output file %s", output_stats.to_string(true).c_str()); my_listener->notifyEnd(decrypt_mode, header, false); return header; } } else { - ERR_PRINT2("Decrypt failed: Not overwriting existing output file %s", destination_fname.c_str()); + ERR_PRINT2("Decrypt failed: Not overwriting existing %s", output_stats.to_string(true).c_str()); my_listener->notifyEnd(decrypt_mode, header, false); return header; } diff --git a/test/cipherpack/data_test.hpp b/test/cipherpack/data_test.hpp index 37398d8..ddcedd1 100644 --- a/test/cipherpack/data_test.hpp +++ b/test/cipherpack/data_test.hpp @@ -39,7 +39,6 @@ class TestData { public: static constexpr const jau::fraction_i64 io_timeout = 10_s; - static constexpr const bool overwrite = true; static const std::string enc_pub_key1_fname; static const std::string dec_sec_key1_fname; diff --git a/test/cipherpack/test_01_cipherpack.cpp b/test/cipherpack/test_01_cipherpack.cpp index 6d82942..0b43a7c 100644 --- a/test/cipherpack/test_01_cipherpack.cpp +++ b/test/cipherpack/test_01_cipherpack.cpp @@ -83,6 +83,9 @@ class Test01Cipherpack : public TestData { fname_payload_decrypted_lst.push_back(name+".enc.dec"); } data() { + // setenv("cipherpack.debug", "true", 1 /* overwrite */); + setenv("cipherpack.verbose", "true", 1 /* overwrite */); + add_test_file("test_cipher_01_11kiB.bin", 1024*11); add_test_file("test_cipher_02_65MiB.bin", 1024*1024*65); } @@ -123,16 +126,15 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); jau::io::ByteInStream_File enc_stream(fname_payload_encrypted_lst[file_idx], true /* use_binary */); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_stream, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_stream, + silentListener, fname_payload_decrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: Decypted %s to %s\n", fname_payload_encrypted_lst[file_idx].c_str(), fname_payload_decrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -144,16 +146,15 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key2_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: Encrypted %s to %s\n", fname_payload_encrypted_lst[file_idx].c_str(), fname_payload_decrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); jau::io::ByteInStream_File enc_stream(fname_payload_encrypted_lst[file_idx], true /* use_binary */); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key2_fname, dec_sec_key_passphrase, - enc_stream, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_stream, + silentListener, fname_payload_decrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: Decypted %s to %s\n", fname_payload_encrypted_lst[file_idx].c_str(), fname_payload_decrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -165,16 +166,15 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key3_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); jau::io::ByteInStream_File enc_stream(fname_payload_encrypted_lst[file_idx], true /* use_binary */); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key3_fname, dec_sec_key_passphrase, - enc_stream, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_stream, + silentListener, fname_payload_decrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: Decypted %s to %s\n", fname_payload_encrypted_lst[file_idx].c_str(), fname_payload_decrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test01_enc_dec_file_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -189,8 +189,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -200,8 +199,8 @@ class Test01Cipherpack : public TestData { // Error: Not encrypted for terminal key 4 jau::io::ByteInStream_File enc_stream(fname_payload_encrypted_lst[file_idx], true /* use_binary */); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key4_fname, dec_sec_key_passphrase, - enc_stream, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_stream, + silentListener, fname_payload_decrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: Decypted %s to %s\n", fname_payload_encrypted_lst[file_idx].c_str(), fname_payload_decrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == false ); @@ -211,8 +210,8 @@ class Test01Cipherpack : public TestData { const std::vector<std::string> sign_pub_keys_nope { sign_pub_key4_fname }; jau::io::ByteInStream_File enc_stream(fname_payload_encrypted_lst[file_idx], true /* use_binary */); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys_nope, dec_sec_key3_fname, dec_sec_key_passphrase, - enc_stream, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_stream, + silentListener, fname_payload_decrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: Decypted %s to %s\n", fname_payload_encrypted_lst[file_idx].c_str(), fname_payload_decrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == false ); @@ -229,8 +228,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -242,8 +240,8 @@ class Test01Cipherpack : public TestData { { jau::io::ByteInStream_URL enc_stream(uri_encrypted, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test11_dec_http_ok: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test11_dec_http_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -251,8 +249,8 @@ class Test01Cipherpack : public TestData { { jau::io::ByteInStream_URL enc_stream(uri_encrypted, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key2_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test11_dec_http_ok: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test11_dec_http_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -260,8 +258,8 @@ class Test01Cipherpack : public TestData { { jau::io::ByteInStream_URL enc_stream(uri_encrypted, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key3_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test11_dec_http_ok: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test11_dec_http_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -278,8 +276,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -291,8 +288,8 @@ class Test01Cipherpack : public TestData { { jau::io::ByteInStream_URL enc_stream(uri_encrypted, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test11_dec_http_ok: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test11_dec_http_ok: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == true ); @@ -309,8 +306,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test02_enc_dec_file_error: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -323,8 +319,8 @@ class Test01Cipherpack : public TestData { // Error: Not encrypted for terminal key 4 jau::io::ByteInStream_URL enc_stream(uri_encrypted, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key4_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test12_dec_http_error: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test12_dec_http_error: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == false ); @@ -334,8 +330,8 @@ class Test01Cipherpack : public TestData { const std::vector<std::string> sign_pub_keys_nope { sign_pub_key4_fname }; jau::io::ByteInStream_URL enc_stream(uri_encrypted, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys_nope, dec_sec_key2_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test12_dec_http_error: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test12_dec_http_error: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == false ); @@ -345,8 +341,8 @@ class Test01Cipherpack : public TestData { const std::string uri_encrypted_err = url_input_root + "doesnt_exists.enc"; jau::io::ByteInStream_URL enc_stream(uri_encrypted_err, io_timeout); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key2_fname, dec_sec_key_passphrase, - enc_stream, file_decrypted, overwrite, - silentListener); + enc_stream, + silentListener, file_decrypted); jau::PLAIN_PRINT(true, "test12_dec_http_error: Decypted %s to %s\n", uri_encrypted.c_str(), file_decrypted.c_str()); jau::PLAIN_PRINT(true, "test12_dec_http_error: %s\n", ph2.toString(true, true).c_str()); REQUIRE( ph2.isValid() == false ); @@ -466,8 +462,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test21_enc_dec_fed_ok: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test21_enc_dec_fed_ok: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -478,8 +473,8 @@ class Test01Cipherpack : public TestData { std::thread feeder_thread= std::thread(&feed_source_00, &enc_feed); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_feed, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_feed, + silentListener, fname_payload_decrypted_lst[file_idx]); if( feeder_thread.joinable() ) { feeder_thread.join(); } @@ -493,8 +488,8 @@ class Test01Cipherpack : public TestData { std::thread feeder_thread= std::thread(&feed_source_01, &enc_feed); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_feed, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_feed, + silentListener, fname_payload_decrypted_lst[file_idx]); if( feeder_thread.joinable() ) { feeder_thread.join(); } @@ -511,8 +506,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test21_enc_dec_fed_ok: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test21_enc_dec_fed_ok: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -523,8 +517,8 @@ class Test01Cipherpack : public TestData { std::thread feeder_thread= std::thread(&feed_source_10, &enc_feed); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_feed, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_feed, + silentListener, fname_payload_decrypted_lst[file_idx]); if( feeder_thread.joinable() ) { feeder_thread.join(); } @@ -546,8 +540,7 @@ class Test01Cipherpack : public TestData { enc_pub_keys, sign_sec_key1_fname, sign_sec_key_passphrase, source, fname_payload_lst[file_idx], "test_case", payload_version, payload_version_parent, - fname_payload_encrypted_lst[file_idx], overwrite, - silentListener); + silentListener, fname_payload_encrypted_lst[file_idx]); jau::PLAIN_PRINT(true, "test22_enc_dec_fed_irq: Encrypted %s to %s\n", fname_payload_lst[file_idx].c_str(), fname_payload_encrypted_lst[file_idx].c_str()); jau::PLAIN_PRINT(true, "test22_enc_dec_fed_irq: %s\n", ph1.toString(true, true).c_str()); REQUIRE( ph1.isValid() == true ); @@ -558,8 +551,8 @@ class Test01Cipherpack : public TestData { std::thread feeder_thread= std::thread(&feed_source_20, &enc_feed); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_feed, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_feed, + silentListener, fname_payload_decrypted_lst[file_idx]); if( feeder_thread.joinable() ) { feeder_thread.join(); } @@ -573,8 +566,8 @@ class Test01Cipherpack : public TestData { std::thread feeder_thread= std::thread(&feed_source_21, &enc_feed); cipherpack::PackHeader ph2 = cipherpack::checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, - enc_feed, fname_payload_decrypted_lst[file_idx], overwrite, - silentListener); + enc_feed, + silentListener, fname_payload_decrypted_lst[file_idx]); if( feeder_thread.joinable() ) { feeder_thread.join(); } diff --git a/test/java/test/org/cipherpack/Test01Cipherpack.java b/test/java/test/org/cipherpack/Test01Cipherpack.java index 4401423..c197b7a 100644 --- a/test/java/test/org/cipherpack/Test01Cipherpack.java +++ b/test/java/test/org/cipherpack/Test01Cipherpack.java @@ -24,35 +24,164 @@ package test.org.cipherpack; -import jau.test.junit.util.SingletonJunitCase; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.cipherpack.CPFactory; -import org.cipherpack.CPVersion; +import org.cipherpack.CPUtils; +import org.cipherpack.Cipherpack; +import org.cipherpack.CipherpackListener; +import org.cipherpack.CryptoConfig; +import org.cipherpack.PackHeader; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; -/** - * Testing BTManager bring up using fat `Direct-BT Jaulib Fat Jar` and - * - test loading native libraries - * - show all installed adapter - * - no extra permissions required - */ @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class Test01Cipherpack extends SingletonJunitCase { +public class Test01Cipherpack extends data_test { static final boolean DEBUG = false; - @Test(timeout = 40000) // long timeout for valgrind - public final void test01_ManagerBringup() { + static final String payload_version = "0"; + static final String payload_version_parent = "0"; + + static final int IDX_11kiB = 0; + static final int IDX_65MiB = 1; + static List<String> fname_payload_lst = new ArrayList<String>(); + static List<String> fname_payload_encrypted_lst = new ArrayList<String>(); + static List<String> fname_payload_decrypted_lst = new ArrayList<String>(); + + static boolean remove_file(final String name) { + final File file = new File( name ); + try { + if( file.exists() ) { + if( !file.delete() ) { + CPUtils.println(System.err, "Remove.1: Failed deletion of existing file "+name); + return false; + } + } + return true; + } catch (final Exception ex) { + CPUtils.println(System.err, "Remove.2: Failed deletion of existing file "+name+": "+ex.getMessage()); + ex.printStackTrace(); + } + return false; + } + static void add_test_file(final String name, final long size) { + Assert.assertTrue( remove_file(name) ); + Assert.assertTrue( remove_file(name+".enc") ); + Assert.assertTrue( remove_file(name+".enc.dec") ); + { + final String one_line = "Hello World, this is a test and I like it. Exactly 100 characters long. 0123456780 abcdefghjklmnop.."; + final Charset charset = Charset.forName("ASCII"); + final byte[] one_line_bytes = one_line.getBytes(charset); + + final File file = new File( name ); + OutputStream out = null; + try { + Assert.assertFalse( file.exists() ); + + out = new FileOutputStream(file); + + for(long i=0; i < size; i+=one_line_bytes.length) { + out.write( one_line_bytes ); + } + out.write( (byte)'X' ); // make it odd + + } catch (final Exception ex) { + CPUtils.println(System.err, "Write SMPKeyBin: Failed "+name+": "+ex.getMessage()); + ex.printStackTrace(); + } finally { + try { + if( null != out ) { + out.close(); + } + } catch (final IOException e) { + e.printStackTrace(); + } + } + + } + fname_payload_lst.add(name); + fname_payload_encrypted_lst.add(name+".enc"); + fname_payload_decrypted_lst.add(name+".enc.dec"); + } + + static { { - // System.setProperty("cipherpack.debug", "true"); - System.setProperty("cipherpack.verbose", "true"); - // System.setProperty("jau.debug", "true"); // java - // System.setProperty("jau.verbose", "true"); // java + // System.setProperty("org.cipherpack.debug", "true"); // java + // System.setProperty("org.cipherpack.verbose", "true"); // java + // System.setProperty("cipherpack.debug", "true"); // native + System.setProperty("cipherpack.verbose", "true"); // native } + add_test_file("test_cipher_01_11kiB.bin", 1024*11); + add_test_file("test_cipher_02_65MiB.bin", 1024*1024*65); + } + + static boolean system(final String[] command) { + Process proc = null; + try{ + proc = Runtime.getRuntime().exec(command); + proc.waitFor(); + return true; + } + catch(final Exception ex) + { + if(proc!=null) { + proc.destroy(); + } + ex.printStackTrace(); + } + return false; + } + + @AfterClass + public static void httpd_stop() { + Assert.assertTrue( system(new String[]{"killall", "mini_httpd"}) ); + Assert.assertTrue( system(new String[]{"killall", "mini_httpd"}) ); + } + + static void httpd_start() { + Assert.assertTrue( system(new String[]{"killall", "mini_httpd"}) ); + Assert.assertTrue( system(new String[]{"killall", "mini_httpd"}) ); + Assert.assertTrue( system(new String[]{"/usr/sbin/mini_httpd", "-p", "8080"}) ); + } + + CipherpackListener silentListener = new CipherpackListener(); + + @Test(timeout = 10000) + public final void test01_enc_dec_file_ok() { CPFactory.checkInitialized(); - CPVersion.printVersionInfo(System.err); + final List<String> enc_pub_keys = Arrays.asList(enc_pub_key1_fname, enc_pub_key2_fname, enc_pub_key3_fname); + final List<String> sign_pub_keys = Arrays.asList(sign_pub_key1_fname, sign_pub_key2_fname, sign_pub_key3_fname); + { + final int file_idx = IDX_11kiB; + final String source_loc = fname_payload_lst.get(file_idx); + final PackHeader ph1 = Cipherpack.encryptThenSign(CryptoConfig.getDefault(), + enc_pub_keys, + sign_sec_key1_fname, sign_sec_key_passphrase, + source_loc, io_timeout, + fname_payload_lst.get(file_idx), "test_case", payload_version, payload_version_parent, + silentListener, fname_payload_encrypted_lst.get(file_idx)); + CPUtils.fprintf_td(System.err, "test01_enc_dec_file_ok: Encrypted %s to %s\n", fname_payload_lst.get(file_idx), fname_payload_encrypted_lst.get(file_idx)); + CPUtils.fprintf_td(System.err, "test01_enc_dec_file_ok: %s\n", ph1.toString(true, true)); + Assert.assertTrue( ph1.isValid() ); + + final String enc_stream_loc = fname_payload_encrypted_lst.get(file_idx); + final PackHeader ph2 = Cipherpack.checkSignThenDecrypt(sign_pub_keys, dec_sec_key1_fname, dec_sec_key_passphrase, + enc_stream_loc, io_timeout, + silentListener, fname_payload_decrypted_lst.get(file_idx)); + CPUtils.fprintf_td(System.err, "test01_enc_dec_file_ok: Decypted %s to %s\n", fname_payload_encrypted_lst.get(file_idx), fname_payload_decrypted_lst.get(file_idx)); + CPUtils.fprintf_td(System.err, "test01_enc_dec_file_ok: %s\n", ph2.toString(true, true)); + Assert.assertTrue( ph2.isValid() ); + } } public static void main(final String args[]) { diff --git a/test/java/test/org/cipherpack/data_test.java b/test/java/test/org/cipherpack/data_test.java new file mode 100644 index 0000000..231c88f --- /dev/null +++ b/test/java/test/org/cipherpack/data_test.java @@ -0,0 +1,61 @@ +/* + * Author: Sven Gothel <[email protected]> + * Copyright (c) 2021 Gothel Software e.K. + * Copyright (c) 2021 ZAFENA AB + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package test.org.cipherpack; + +import jau.test.junit.util.SingletonJunitCase; + +public class data_test extends SingletonJunitCase { + public static final long io_timeout = 10000; // 10_s; + + public static final String enc_pub_key1_fname = "../../../test_keys/terminal_rsa1.pub.pem"; + public static final String dec_sec_key1_fname = "../../../test_keys/terminal_rsa1"; + + public static final String enc_pub_key2_fname = "../../../test_keys/terminal_rsa2.pub.pem"; + public static final String dec_sec_key2_fname = "../../../test_keys/terminal_rsa2"; + + public static final String enc_pub_key3_fname = "../../../test_keys/terminal_rsa3.pub.pem"; + public static final String dec_sec_key3_fname = "../../../test_keys/terminal_rsa3"; + + public static final String enc_pub_key4_fname = "../../../test_keys/terminal_rsa4.pub.pem"; + public static final String dec_sec_key4_fname = "../../../test_keys/terminal_rsa4"; + + public static final String dec_sec_key_passphrase = ""; + + public static final String sign_pub_key1_fname = "../../../test_keys/host_rsa1.pub.pem"; + public static final String sign_sec_key1_fname = "../../../test_keys/host_rsa1"; + + public static final String sign_pub_key2_fname = "../../../test_keys/host_rsa2.pub.pem"; + public static final String sign_sec_key2_fname = "../../../test_keys/host_rsa2"; + + public static final String sign_pub_key3_fname = "../../../test_keys/host_rsa3.pub.pem"; + public static final String sign_sec_key3_fname = "../../../test_keys/host_rsa3"; + + public static final String sign_pub_key4_fname = "../../../test_keys/host_rsa4.pub.pem"; + public static final String sign_sec_key4_fname = "../../../test_keys/host_rsa4"; + + public static final String sign_sec_key_passphrase = ""; + + public static final String url_input_root = "http://localhost:8080/"; +} |