webpg-npapi 0.6.1
FB::variant webpgPluginAPI::gpgEncrypt ( const std::string &  data,
const FB::VariantList &  enc_to_keyids,
bool  sign = false 
)

Encrypts the data passed in data with the key ids passed in enc_to_keyids and optionally signs the data.

Parameters:
dataThe data to encrypt.
enc_to_keyidsA VariantList of key ids to encrypt to (recpients).
signThe data should be also be signed.
Returns:
FB::variant response
response {
    "data":"—————BEGIN PGP MESSAGE—————
            Version: GnuPG v1.4.11 (GNU/Linux)
            
            jA0EAwMC3hG5kEn899BgyWQW6CHxijX8Zw9oe1OAb7zlofpbVLXbvvyKWPKN3mSk
            i244qGDD8ReGbG87/w52pyNFHd8848TS5r5RwVyDaU8uGFg1XeUSyywAg4p5hg+v
            8Ad/SJfwG0WHXfX9HXoWdkQ+sRkl
            =8KTs
            —————END PGP MESSAGE—————",
    "error":false
}
Parameters:
dataThe data to encrypt.
enc_to_keyidsA VariantList of key ids to encrypt to (recpients).
signThe data should be also be signed.

Definition at line 1146 of file webpgPluginAPI.cpp.

References get_gpgme_ctx().

Referenced by gpgSymmetricEncrypt(), and webpgPluginAPI().

{
    /* declare variables */
    gpgme_ctx_t ctx = get_gpgme_ctx();
    gpgme_error_t err;
    gpgme_data_t in, out;
#ifdef HAVE_W32_SYSTEM
    // FIXME: W32 doesn't like the array sized by the contents of the
    // enc_to_keyids - for now set to 100
    gpgme_key_t key[100];
#else
    gpgme_key_t key[enc_to_keyids.size()];
#endif
    int nrecipients;
    FB::variant recipient;
    FB::VariantList recpients;
    gpgme_encrypt_result_t enc_result;
    FB::VariantMap response;
    bool unusable_key = false;

    err = gpgme_data_new_from_mem (&in, data.c_str(), data.length(), 0);
    if (err != GPG_ERR_NO_ERROR)
        return get_error_map(__func__, gpgme_err_code (err), gpgme_strerror (err), __LINE__, __FILE__);

    err = gpgme_data_set_encoding(in, GPGME_DATA_ENCODING_ARMOR);
    if(err != GPG_ERR_NO_ERROR)
        return get_error_map(__func__, gpgme_err_code (err), gpgme_strerror (err), __LINE__, __FILE__);

    err = gpgme_data_new (&out);
    if (err != GPG_ERR_NO_ERROR)
        return get_error_map(__func__, gpgme_err_code (err), gpgme_strerror (err), __LINE__, __FILE__);

    err = gpgme_data_set_encoding(out, GPGME_DATA_ENCODING_ARMOR);
    if(err != GPG_ERR_NO_ERROR)
        return get_error_map(__func__, gpgme_err_code (err), gpgme_strerror (err), __LINE__, __FILE__);

    for (nrecipients=0; nrecipients < enc_to_keyids.size(); nrecipients++) {

        recipient = enc_to_keyids[nrecipients];

        err = gpgme_get_key (ctx, recipient.convert_cast<std::string>().c_str(), &key[nrecipients], 0);
        if(err != GPG_ERR_NO_ERROR)
            return get_error_map(__func__, gpgme_err_code (err),
                gpgme_strerror (err), __LINE__, __FILE__,
                recipient.convert_cast<std::string>().c_str());

        // Check if key is unusable/invalid
        unusable_key = key[nrecipients]->invalid? true :
            key[nrecipients]->expired? true :
            key[nrecipients]->revoked? true :
            key[nrecipients]->disabled? true : false;

        if (unusable_key) {
            // Somehow an ususable/invalid key has been passed to the method
            std::string keyid = key[nrecipients]->subkeys->fpr;

            std::string strerror = key[nrecipients]->invalid? "Invalid key" :
            key[nrecipients]->expired? "Key expired" :
            key[nrecipients]->revoked? "Key revoked" :
            key[nrecipients]->disabled? "Key disabled" : "Unknown error";

            err = key[nrecipients]->invalid? 53 :
            key[nrecipients]->expired? 153 :
            key[nrecipients]->revoked? 94 :
            key[nrecipients]->disabled? 53 : GPG_ERR_UNKNOWN_ERRNO;

            return get_error_map(__func__, gpgme_err_code (err), strerror, __LINE__, __FILE__, keyid);
        }

    }

    // NULL terminate the key array
    key[enc_to_keyids.size()] = NULL;

    if (sign) {
        if (enc_to_keyids.size() < 1) {
            // NOTE: This doesn't actually work due to an issue with gpgme-1.3.2.
            //  see: https://bugs.g10code.com/gnupg/issue1440 for details
            //err = gpgme_op_encrypt_sign (ctx, NULL, GPGME_ENCRYPT_NO_ENCRYPT_TO, in, out);
            return "Signed Symmetric Encryption is not yet implemented";
        } else {
            err = gpgme_op_encrypt_sign (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
        }
    } else {
        if (enc_to_keyids.size() < 1) {
            // Symmetric encrypt
            err = gpgme_op_encrypt (ctx, NULL, GPGME_ENCRYPT_NO_ENCRYPT_TO, in, out);
        } else {
            err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
        }
    }

    if (err != GPG_ERR_NO_ERROR)
        return get_error_map(__func__, gpgme_err_code (err), gpgme_strerror (err), __LINE__, __FILE__);

    if (enc_to_keyids.size() < 1) {
        // This was a symmetric operation, and gpgme_op_encrypt does not return
        //  an error if the passphrase is incorrect, so we need to check the
        //  returned value for actual substance.
        gpgme_data_seek(out, 0, SEEK_SET);
        char buf[513];
        gpgme_data_read (out, buf, 512);
        int buflen = strlen(buf);
        if (buflen < 52) {
            gpgme_release (ctx);
            gpgme_data_release (in);
            gpgme_data_release (out);
            FB::VariantMap error_map_obj;
            error_map_obj["error"] = true;
            error_map_obj["method"] = __func__;
            error_map_obj["gpg_error_code"] = "11";
            error_map_obj["error_string"] = "Passphrase did not match";
            error_map_obj["line"] = __LINE__;
            error_map_obj["file"] = __FILE__;
            return error_map_obj;
        }
    }

    enc_result = gpgme_op_encrypt_result (ctx);
    if (enc_result->invalid_recipients)
    {
        return get_error_map(__func__, gpgme_err_code (err), gpgme_strerror (err), __LINE__, __FILE__);
    }

    size_t out_size = 0;
    std::string out_buf;
    out_buf = gpgme_data_release_and_get_mem (out, &out_size);
    /* strip the size_t data out of the output buffer */
    out_buf = out_buf.substr(0, out_size);
    /* set the output object to NULL since it has
        already been released */
    out = NULL;

    /* if any of the gpgme objects have not yet
        been release, do so now */
    for (nrecipients=0; nrecipients < enc_to_keyids.size(); nrecipients++)
        gpgme_key_unref(key[nrecipients]);

    if (ctx)
        gpgme_release (ctx);
    if (in)
        gpgme_data_release (in);
    if (out)
        gpgme_data_release (out);

    response["data"] = out_buf;
    response["error"] = false;

    return response;
}

Here is the call graph for this function:

 All Classes Functions