pgp: switch from rnp to gpgme

master
bqv 2 years ago
parent 30a7f9eeff
commit a0d1c104e4
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -51,7 +51,6 @@
- libxml2 (dynamic, dependency)
- lmdb (dynamic, dependency)
- libomemo-c (libsignal-protocol-c) (dynamic, dependency)
- rnp (dynamic, dependency)
- gpgme (dynamic, dependency)
- weechat (>= v3.0)
@ -158,14 +157,13 @@
* [ ] Delete bookmarks
* [ ] Roster
* [ ] OTR (libotr)
* [X] PGP (rnpgp)
* [X] Use keyrings (e.g. exported from gnupg)
* [X] PGP (gpgme)
* [X] Use keyrings (from gnupg)
* [X] Presence
* [X] Decryption
* [X] Encryption
* [X] Custom set/clear key (/pgp)
* [ ] Save pgp key set per jid/muc
* [ ] GPGME
* [ ] Room Explorer (https://search.jabber.network/docs/api)
** TODO [#C] Adhere to CCS (milestone v0.3)
** TODO [#D] Close all issues (milestone v1.0)

@ -9,7 +9,6 @@ FIND=find
INCLUDES=-Ilibstrophe -Ideps -Ideps/fmt/include \
$(shell xml2-config --cflags) \
$(shell pkg-config --cflags gpgme) \
$(shell pkg-config --cflags librnp) \
$(shell pkg-config --cflags libsignal-protocol-c)
CFLAGS+=$(DBGCFLAGS) \
-fno-omit-frame-pointer -fPIC \
@ -36,7 +35,6 @@ LDLIBS=-lstrophe \
-lpthread \
$(shell xml2-config --libs) \
$(shell pkg-config --libs gpgme) \
$(shell pkg-config --libs librnp) \
$(shell pkg-config --libs libsignal-protocol-c) \
-lgcrypt \
-llmdb

@ -6,47 +6,61 @@
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <rnp/rnp.h>
#include <gpgme.h>
#include <weechat/weechat-plugin.h>
#include "plugin.hh"
#include "pgp.hh"
#define RNP_SUCCESS 0
#define PGP_MESSAGE_HEADER "-----BEGIN PGP MESSAGE-----\r\n\r\n"
#define PGP_MESSAGE_FOOTER "\r\n-----END PGP MESSAGE-----\r\n"
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----\r\n\r\n"
#define PGP_SIGNATURE_FOOTER "\r\n-----END PGP SIGNATURE-----\r\n"
#define PGP_MESSAGE_HEADER "-----BEGIN PGP MESSAGE-----\r\n"
#define PGP_MESSAGE_FOOTER "\r\n-----END PGP MESSAGE-----"
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----\r\n"
#define PGP_SIGNATURE_FOOTER "\r\n-----END PGP SIGNATURE-----"
const char *PGP_ADVICE = "[PGP encrypted message (XEP-0027)]";
void pgp__init(struct t_pgp **pgp, const char *pub, const char *sec)
{
struct t_pgp *new_pgp;
rnp_input_t keyring;
gpgme_error_t err;
gpgme_data_t keydata;
gpgme_check_version(NULL);
new_pgp = (struct t_pgp*)calloc(1, sizeof(**pgp));
if (rnp_ffi_create(&new_pgp->context,
RNP_KEYSTORE_GPG, RNP_KEYSTORE_GPG) != RNP_SUCCESS) {
err = gpgme_new(&new_pgp->gpgme);
if (err) {
return;
}
gpgme_set_armor(new_pgp->gpgme, true);
err = gpgme_data_new_from_file(&keydata, pub, true);
if (err) {
return;
}
if (rnp_input_from_path(&keyring, pub) == RNP_SUCCESS) {
if (rnp_load_keys(new_pgp->context, RNP_KEYSTORE_GPG,
keyring, RNP_LOAD_SAVE_PUBLIC_KEYS) == RNP_SUCCESS) {
rnp_input_destroy(keyring);
}
err = gpgme_op_import(new_pgp->gpgme, keydata);
if (err) {
return;
}
gpgme_import_result_t impRes = gpgme_op_import_result(new_pgp->gpgme);
weechat_printf(nullptr, "(gpg) imported %d keys", impRes->imported);
err = gpgme_data_new_from_file(&keydata, sec, true);
if (err) {
return;
}
if (rnp_input_from_path(&keyring, sec) == RNP_SUCCESS) {
if (rnp_load_keys(new_pgp->context, RNP_KEYSTORE_GPG,
keyring, RNP_LOAD_SAVE_SECRET_KEYS) == RNP_SUCCESS) {
rnp_input_destroy(keyring);
}
err = gpgme_op_import(new_pgp->gpgme, keydata);
if (err) {
return;
}
impRes = gpgme_op_import_result(new_pgp->gpgme);
weechat_printf(nullptr, "(gpg) imported %d secret keys", impRes->imported);
*pgp = new_pgp;
}
@ -54,335 +68,236 @@ void pgp__free(struct t_pgp *pgp)
{
if (pgp)
{
if (pgp->context)
free(pgp->context);
if (pgp->gpgme)
gpgme_release(pgp->gpgme);
free(pgp);
}
}
char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *target, const char *message)
{
rnp_op_encrypt_t encrypt = NULL;
rnp_key_handle_t key = NULL;
rnp_input_t keyfile = NULL;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
std::string encrypted;
gpgme_key_t keys[3] = {NULL,NULL,NULL};
char * result = NULL;
rnp_result_t ret;
/* create memory input and file output objects for the message and encrypted message */
if ((ret = rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false)) !=
RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
goto encrypt_finish;
}
int ret;
gpgme_error_t err;
gpgme_data_t in, out;
if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create output object: %s\n", weechat_prefix("error"), reason);
/* Initialize input buffer. */
err = gpgme_data_new_from_mem(&in, message, strlen(message), false);
if (err) {
goto encrypt_finish;
}
/* create encryption operation */
if ((ret = rnp_op_encrypt_create(&encrypt, pgp->context, input, output)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create encrypt operation: %s\n", weechat_prefix("error"), reason);
/* Initialize output buffer. */
err = gpgme_data_new(&out);
if (err) {
goto encrypt_finish;
}
/* setup encryption parameters */
rnp_op_encrypt_set_armor(encrypt, true);
rnp_op_encrypt_set_file_name(encrypt, "message.txt");
rnp_op_encrypt_set_file_mtime(encrypt, time(NULL));
rnp_op_encrypt_set_compression(encrypt, "ZIP", 6);
rnp_op_encrypt_set_cipher(encrypt, RNP_ALGNAME_AES_256);
rnp_op_encrypt_set_aead(encrypt, "None");
/* locate recipient's key and add it to the operation context. */
if ((ret = rnp_locate_key(pgp->context, "keyid", target, &key)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to locate recipient key: %s\n", weechat_prefix("error"), reason);
/* Encrypt data. */
err = gpgme_get_key(pgp->gpgme, target, &keys[0], false);
if (err) {
goto encrypt_finish;
}
if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to add recipient: %s\n", weechat_prefix("error"), reason);
err = gpgme_get_key(pgp->gpgme, source, &keys[1], false);
if (err) {
goto encrypt_finish;
}
rnp_key_handle_destroy(key);
key = NULL;
/* locate carbon-copy key and add it to the operation context. */
if ((ret = rnp_locate_key(pgp->context, "keyid", source, &key)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to locate recipient key: %s\n", weechat_prefix("error"), reason);
err = gpgme_op_encrypt(pgp->gpgme, keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
if (err) {
goto encrypt_finish;
}
if ((ret = rnp_op_encrypt_add_recipient(encrypt, key)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to add recipient: %s\n", weechat_prefix("error"), reason);
goto encrypt_finish;
}
rnp_key_handle_destroy(key);
key = NULL;
/* execute encryption operation */
if ((ret = rnp_op_encrypt_execute(encrypt)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: encryption failed: %s\n", weechat_prefix("error"), reason);
if (gpgme_encrypt_result_t enc_result = gpgme_op_encrypt_result(pgp->gpgme);
enc_result->invalid_recipients)
{
goto encrypt_finish;
}
gpgme_data_seek(out, 0, SEEK_SET);
char data[512 + 1];
while ((ret = gpgme_data_read(out, data, 512)) > 0)
{
encrypted += std::string_view(data, ret);
}
uint8_t *buf;
size_t buf_len;
gpgme_data_release(in);
gpgme_data_release(out);
rnp_output_memory_get_buf(output, &buf, &buf_len, false);
result = strndup((char *)buf + strlen(PGP_MESSAGE_HEADER),
buf_len - strlen(PGP_MESSAGE_HEADER) - strlen(PGP_MESSAGE_FOOTER));
result = strndup(encrypted.data() + strlen(PGP_MESSAGE_HEADER),
encrypted.size() - strlen(PGP_MESSAGE_HEADER) - strlen(PGP_MESSAGE_FOOTER));
encrypt_finish:
rnp_op_encrypt_destroy(encrypt);
rnp_input_destroy(keyfile);
rnp_input_destroy(input);
rnp_output_destroy(output);
rnp_key_handle_destroy(key);
return result;
}
//"hQIMAzlgcSFDGLKEAQ//cGG3DFughC5xBF7xeXz1RdayOfhBAPfoZIq62MVuSnfS\nMfig65Zxz1LtAnnFq90TZY7hiHPBtVlYqg47AbSoYweMdpXsKgbUrd3NNf6k2nsZ\nUkChCtyGuHi8pTzclfle7gT0nNXJ1WcLCZ4ORZCrg3D5A+YTO9tdmE8GQsTT6TdV\nbbxF5yR4JF5SzFhuFL3ZoXPXrWylcwKXarYfoOTa6M2vSsCwApVIXQgJ/FI46sLT\nb0B/EVCjFvcvjkNr7+K7mQtth+x0a0pC4BtEhRvnIRAe/sdGp8NY+DP76clx4U+k\nIDG4H92F632pR6eEIoZttnBoaj0O4sTVAJCao5AoecR4w2FDqBWWtIyQp5vbo17/\nMtzungkk5vQP6Jhu36wa+JKpbHoxomVpHPZfAtIoyaY6pzQ0bUomIlSVpbZDvF68\nZKTlFd89Pm5x0JO5gsVYvf+N9Ed33d34n/0CFz5K5Tgu4Bk0v4LWEy3wtNsuQB4p\nkBSZJk7I2BakcRwP0zwld6rRHFIX1pb7zqThBPZGB9RkWPltiktUTibOII12tWhi\nksFpQJ8l1A8h9vM5kUXIeD6H2yP0CBUEIZF3Sf+jiSRZ/1/n3KoUrKEzkf/y4xgv\n1LA4pMjNLEr6J2fqGyYRFv4Bxv3PIvF17V5CwOtguxGRJHJXdIzm1BSHSqXxHezS\nYAFXMUb9fw3QX7Ed23KiyZjzd/LRsQBqMs9RsYyZB2PqF9x84lQYYbE8lErrryvK\nUEtmJKPw3Hvb7kgGox5vl5+KCg9q64EU9TgQpufYNShKtDz7Fsvc+ncgZoshDUeo\npw==\n=euIB"
char *pgp__decrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *ciphertext)
{
rnp_input_t input = NULL;
rnp_output_t output = NULL;
std::string decrypted;
uint8_t * buf = NULL;
size_t buf_len = 0;
char * result = NULL;
rnp_result_t ret;
int ret;
buf_len = strlen(PGP_MESSAGE_HEADER) + strlen(ciphertext) + strlen(PGP_MESSAGE_FOOTER) + 1;
buf = (uint8_t*)malloc(sizeof(char) * buf_len);
buf_len = snprintf((char *)buf, buf_len, PGP_MESSAGE_HEADER "%s" PGP_MESSAGE_FOOTER, ciphertext);
/* create file input and memory output objects for the encrypted message and decrypted
* message */
if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
gpgme_error_t err;
gpgme_data_t in, out;
/* Initialize input buffer. */
err = gpgme_data_new_from_mem(&in, (char *)buf, buf_len, false);
if (err) {
goto decrypt_finish;
}
if ((ret = rnp_output_to_memory(&output, 0)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create output object: %s\n", weechat_prefix("error"), reason);
/* Initialize output buffer. */
err = gpgme_data_new(&out);
if (err) {
goto decrypt_finish;
}
if ((ret = rnp_decrypt(pgp->context, input, output)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: public-key decryption failed: %s\n", weechat_prefix("error"), reason);
/* Decrypt data. */
err = gpgme_op_decrypt(pgp->gpgme, in, out);
if (err) {
goto decrypt_finish;
}
free(buf);
/* get the decrypted message from the output structure */
if (rnp_output_memory_get_buf(output, &buf, &buf_len, false) != RNP_SUCCESS) {
if (gpgme_decrypt_result_t dec_result = gpgme_op_decrypt_result(pgp->gpgme);
dec_result->unsupported_algorithm)
{
goto decrypt_finish;
}
gpgme_data_seek(out, 0, SEEK_SET);
char data[512 + 1];
while ((ret = gpgme_data_read(out, data, 512)) > 0)
{
decrypted += std::string_view(data, ret);
}
result = strndup((const char *)buf, (int)buf_len);
gpgme_data_release(in);
gpgme_data_release(out);
result = strndup(decrypted.data(), decrypted.size());
decrypt_finish:
rnp_input_destroy(input);
rnp_output_destroy(output);
return result;
}
char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate)
{
rnp_op_verify_t verify = NULL;
rnp_input_t input = NULL;
rnp_input_t signature = NULL;
uint8_t * buf = NULL;
size_t buf_len = 0;
size_t sigcount = 0;
char * result = NULL;
rnp_result_t ret;
int ret;
buf_len = strlen(PGP_SIGNATURE_HEADER) + strlen(certificate) + strlen(PGP_SIGNATURE_FOOTER) + 1;
buf = (uint8_t*)malloc(sizeof(char) * buf_len);
buf_len = snprintf((char *)buf, buf_len, PGP_SIGNATURE_HEADER "%s" PGP_SIGNATURE_FOOTER, certificate);
/* create file input memory objects for the signed message and verified message */
if ((ret = rnp_input_from_memory(&input, buf, buf_len, false)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
goto verify_finish;
}
gpgme_verify_result_t vrf_result;
gpgme_error_t err;
gpgme_data_t in, out;
if ((ret = rnp_input_from_memory(&signature, buf, buf_len, false)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create input object: %s\n", weechat_prefix("error"), reason);
/* Initialize input buffer. */
err = gpgme_data_new_from_mem(&in, (char *)buf, buf_len, false);
if (err) {
goto verify_finish;
}
if ((ret = rnp_op_verify_detached_create(&verify, pgp->context, input, signature)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to create verification context: %s\n", weechat_prefix("error"), reason);
/* Initialize output buffer. */
err = gpgme_data_new(&out);
if (err) {
goto verify_finish;
}
//if ((
ret = rnp_op_verify_execute(verify)
;
// ) != RNP_ERROR_SIGNATURE_INVALID)
// if (ret != RNP_ERROR_SIGNATURE_INVALID) {
// const char *reason = rnp_result_to_string(ret);
// weechat_printf(buffer, "%spgp: failed to execute verification operation: %s\n", weechat_prefix("error"), reason);
// goto verify_finish;
// }
/* now check signatures and get some info about them */
if ((ret = rnp_op_verify_get_signature_count(verify, &sigcount)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to get signature count: %s\n", weechat_prefix("error"), reason);
/* Verify data. */
err = gpgme_op_verify(pgp->gpgme, in, out, nullptr);
if (err) {
goto verify_finish;
}
if (vrf_result = gpgme_op_verify_result(pgp->gpgme);
!(vrf_result->signatures->summary & GPGME_SIGSUM_VALID))
{
goto verify_finish;
}
for (size_t i = 0; i < sigcount; i++) {
rnp_op_verify_signature_t sig = NULL;
rnp_key_handle_t key = NULL;
rnp_signature_handle_t signature = NULL;
char * keyid = NULL;
if ((ret = rnp_op_verify_get_signature_at(verify, i, &sig)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to get signature %d: %s\n", weechat_prefix("error"), (int)i, reason);
goto verify_finish;
}
if ((ret = rnp_op_verify_signature_get_key(sig, &key)) == RNP_SUCCESS) {
if ((ret = rnp_key_get_keyid(key, &keyid)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to get key id %d: %s\n", weechat_prefix("error"), (int)i, reason);
rnp_key_handle_destroy(key);
goto verify_finish;
}
if ((ret = rnp_key_get_signature_at(key, 0, &signature)) == RNP_SUCCESS) {
if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to get key id: %s\n", weechat_prefix("error"), reason);
rnp_key_handle_destroy(key);
goto verify_finish;
}
rnp_signature_handle_destroy(signature);
}
} else {
if ((ret = rnp_op_verify_signature_get_handle(sig, &signature)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to get signature's %d handle: %s\n", weechat_prefix("error"), (int)i, reason);
goto verify_finish;
}
if ((ret = rnp_signature_get_keyid(signature, &keyid)) != RNP_SUCCESS) {
const char *reason = rnp_result_to_string(ret);
weechat_printf(buffer, "%spgp: failed to get key id: %s\n", weechat_prefix("error"), reason);
rnp_key_handle_destroy(key);
goto verify_finish;
}
}
result = strdup(keyid);
rnp_buffer_destroy(keyid);
rnp_key_handle_destroy(key);
break;
}
result = strdup(vrf_result->signatures->fpr);
verify_finish:
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_input_destroy(signature);
return result;
}
char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message)
{
rnp_input_t keyfile = NULL;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
rnp_op_sign_t sign = NULL;
rnp_key_handle_t key = NULL;
std::string signature;
uint8_t * buf = NULL;
size_t buf_len = 0;
char * result = NULL;
int ret;
/* create file input and memory output objects for the encrypted message and decrypted
* message */
if (rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false) !=
RNP_SUCCESS) {
weechat_printf(buffer, "%spgp: failed to create input object\n", weechat_prefix("error"));
goto sign_finish;
}
gpgme_error_t err;
gpgme_data_t in, out;
gpgme_key_t key;
if (rnp_output_to_memory(&output, 0) != RNP_SUCCESS) {
weechat_printf(buffer, "%spgp: failed to create output object\n", weechat_prefix("error"));
/* Initialize input buffer. */
err = gpgme_data_new_from_mem(&in, (char *)message, strlen(message), false);
if (err) {
goto sign_finish;
}
/* initialize and configure sign operation */
if (rnp_op_sign_detached_create(&sign, pgp->context, input, output) != RNP_SUCCESS) {
weechat_printf(buffer, "%spgp: failed to create sign operation\n", weechat_prefix("error"));
/* Initialize output buffer. */
err = gpgme_data_new(&out);
if (err) {
goto sign_finish;
}
/* armor, file name, compression */
rnp_op_sign_set_armor(sign, true);
rnp_op_sign_set_file_name(sign, "message.txt");
rnp_op_sign_set_file_mtime(sign, time(NULL));
rnp_op_sign_set_compression(sign, "ZIP", 6);
/* signatures creation time - by default will be set to the current time as well */
rnp_op_sign_set_creation_time(sign, time(NULL));
/* signatures expiration time - by default will be 0, i.e. never expire */
rnp_op_sign_set_expiration_time(sign, 365 * 24 * 60 * 60);
/* set hash algorithm - should be compatible for all signatures */
rnp_op_sign_set_hash(sign, RNP_ALGNAME_SHA256);
/* now add signatures. First locate the signing key, then add and setup signature */
if (rnp_locate_key(pgp->context, "keyid", source, &key) != RNP_SUCCESS) {
weechat_printf(buffer, "%spgp: failed to locate signing key: %s\n", weechat_prefix("error"), source);
/* Include signature within key. */
{
gpgme_keylist_mode_t kmode = gpgme_get_keylist_mode(pgp->gpgme);
kmode |= GPGME_KEYLIST_MODE_SIGS;
err = gpgme_set_keylist_mode(pgp->gpgme, kmode);
}
if (err) {
goto sign_finish;
}
if (rnp_op_sign_add_signature(sign, key, NULL) != RNP_SUCCESS) {
weechat_printf(buffer, "%spgp: failed to add signature for key: %s\n", weechat_prefix("error"), source);
err = gpgme_get_key(pgp->gpgme, source, &key, false);
if (err) {
weechat_printf(nullptr, "(gpg) get key fail for %s", source);
goto sign_finish;
}
rnp_key_handle_destroy(key);
key = NULL;
/* finally do signing */
if (rnp_op_sign_execute(sign) != RNP_SUCCESS) {
weechat_printf(buffer, "%spgp: failed to sign with key: %s\n", weechat_prefix("error"), source);
err = gpgme_signers_add(pgp->gpgme, key);
if (err) {
weechat_printf(nullptr, "(gpg) add key fail for %s", source);
goto sign_finish;
}
/* get the signature from the output structure */
if (rnp_output_memory_get_buf(output, &buf, &buf_len, false) != RNP_SUCCESS) {
/* Sign data. */
err = gpgme_op_sign(pgp->gpgme, in, out, GPGME_SIG_MODE_DETACH);
if (err) {
weechat_printf(nullptr, "(gpg) sign fail for %s", source);
goto sign_finish;
}
if (gpgme_sign_result_t sgn_result = gpgme_op_sign_result(pgp->gpgme);
!sgn_result->signatures)
{
weechat_printf(nullptr, "(gpg) signature fail for %s", source);
}
gpgme_data_seek(out, 0, SEEK_SET);
char data[512 + 1];
while ((ret = gpgme_data_read(out, data, 512)) > 0)
{
signature += std::string_view(data, ret);
}
gpgme_data_release(in);
gpgme_data_release(out);
result = strndup((char *)buf + strlen(PGP_SIGNATURE_HEADER),
buf_len - strlen(PGP_SIGNATURE_HEADER) - strlen(PGP_SIGNATURE_FOOTER));
result = strndup(signature.data() + strlen(PGP_SIGNATURE_HEADER),
signature.size() - strlen(PGP_SIGNATURE_HEADER) - strlen(PGP_SIGNATURE_FOOTER));
sign_finish:
rnp_input_destroy(keyfile);
rnp_key_handle_destroy(key);
rnp_op_sign_destroy(sign);
rnp_input_destroy(input);
rnp_output_destroy(output);
return result;
}

@ -4,11 +4,13 @@
#pragma once
#include <string>
extern const char *PGP_ADVICE;
struct t_pgp
{
struct rnp_ffi_st *context;
struct gpgme_context *gpgme;
const char *keyid;
};

Loading…
Cancel
Save