While trying to verify corrupted file signature, I used this code :
gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t input_signed = NULL; gpgme_data_t output_data = NULL; gpgme_verify_result_t vresult; ssize_t chars_read; error = renson::error::kNoError; try { // set the locale setlocale(LC_ALL, ""); // check the GPG version gpgme_check_version(NULL); gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL)); // verify if OpenPGP is supported err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); if (err) { LOG_ERROR("Error during gpgme_engine_check_version: " + std::string(gpgme_strerror(err))); throw renson::error::kBadConfiguration; } // create the context for the GPGME operations err = gpgme_new(&ctx); if (err) { LOG_ERROR("Error during gpgme_new: " + std::string(gpgme_strerror(err))); throw renson::error::kInvalidOperation; } // check if the input path is valid if (!exists(input_file_path_)) { LOG_ERROR("Given input file does not exist: " + input_file_path_.string()); throw renson::error::kWrongInputParam; } if (!is_regular_file(input_file_path_)) { LOG_ERROR("Given input path is a directory, not a file: " + input_file_path_.string()); throw renson::error::kWrongInputParam; } if (!exists(output_path.parent_path())) { LOG_ERROR("Output directory does not exist for: " + output_path.parent_path().string()); throw renson::error::kWrongInputParam; } // open signed input file err = gpgme_data_new_from_file(&input_signed, input_file_path_.string().c_str(), 1); if (err) { LOG_ERROR("Error during gpgme_data_new_from_file on " + input_file_path_.string() + ": " + std::string(gpgme_strerror(err))); throw renson::error::kWrongInputParam; } // create output data err = gpgme_data_new(&output_data); if (err) { LOG_ERROR("Error during gpgme_data_new: " + std::string(gpgme_strerror(err))); throw renson::error::kInvalidOperation; } // call the actual verify call: "gpg --verify xxx.gpg" err = gpgme_op_verify(ctx, input_signed, NULL, output_data); if (err) { LOG_ERROR("Error during gpgme_op_verify: " + std::string(gpgme_strerror(err))); throw renson::error::kFileSignatureError; } // interpret the result from gpg vresult = gpgme_op_verify_result(ctx); if (gpgme_err_code(vresult->signatures->status) != GPG_ERR_NO_ERROR) { LOG_ERROR("unexpected signature status: " + std::string(gpgme_strerror(vresult->signatures->status))); throw renson::error::kFileSignatureError; } else if (vresult->signatures->next) { LOG_ERROR("unexpected number of signatures"); throw renson::error::kFileSignatureError; } else if (vresult->signatures->summary == GPGME_SIGSUM_RED) { LOG_ERROR("unexpected signature summary " + std::to_string(vresult->signatures->summary)); throw renson::error::kFileSignatureError; } else if (vresult->signatures->wrong_key_usage) { LOG_ERROR("unexpected wrong key usage"); throw renson::error::kFileSignatureError; } else if (gpgme_err_code(vresult->signatures->validity_reason) != GPG_ERR_NO_ERROR) { LOG_ERROR("unexpected validity reason: " + std::string(gpgme_strerror(vresult->signatures->validity_reason))); throw renson::error::kFileSignatureError; } // Open the output file std::ofstream output_fs = std::ofstream(output_path.string(), std::ofstream::binary); if (!output_fs.good()) { LOG_ERROR("Error opening file: " + output_path.string()); throw renson::error::kFileWriteError; } // Rewind the "output_data" data object err = gpgme_data_seek(output_data, 0, SEEK_SET); if (err) { LOG_ERROR("Error during gpgme_data_seek: " + std::string(gpgme_strerror(err))); throw renson::error::kInvalidOperation; } // Read the contents of output_data and place it into "contents" const int buffer_size = 256 * 1024; char contents[buffer_size]; while ((chars_read = gpgme_data_read(output_data, contents, buffer_size)) > 0) { // Write the contents of contents to "output_fs" output_fs.write(contents, chars_read); if (!output_fs.good()) { LOG_ERROR("Error writing file: " + output_path.string()); throw renson::error::kFileWriteError; } } } catch (renson::error::Error& e) { error = e; } // cleanup if (input_signed) gpgme_data_release(input_signed); if (output_data) gpgme_data_release(output_data); // when no exception was thrown, return true, otherwise false return error == renson::error::kNoError;
}
I works fine with a regular gpg file, however, passing a corrupted file, it got stuck at gpgme_op_verify and never return anything.
however using gpgme command works fine and returns that file is corrupted.
Any help ?