GnuPGME: GPG Signature C++ - c++

Has anyone written any tutorials or have any documentation on how to use GnuPGME so I would be able to write a function such as gpgSign(std::string fileToBeSigned, std::string outPutFileName) in C++?

Below is a C example with verbose comments that does what you are looking for - it is not the most direct approach, but should illustrate the how to accomplish signing a file. It does not handle selection of signers, but the GPGME docs should help you there.
You can save the file and make edits and test directly from the command line. To compile, just save as "gpgsign.c", and execute gcc gpgsign.c -lgpgme -o gpgsign (NOTE: you must have libgpgme installed). Then you can execute the using gpgsign <input file> <output file>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#include <gpgme.h>
#define fail_if_err(err) \
do { \
if (err) { \
fprintf (stderr, "%s:%d: %s: %s\n", \
__FILE__, __LINE__, gpgme_strsource (err), \
gpgme_strerror (err)); \
exit (1); \
} \
} \
while (0)
void gpgSign(const char *fileToBeSigned, const char *outputFileName) {
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t in, out;
FILE *outputFile;
int BUF_SIZE = 512;
char buf[BUF_SIZE + 1];
int ret;
/* Set the GPGME signature mode
GPGME_SIG_MODE_NORMAL : Signature with data
GPGME_SIG_MODE_CLEAR : Clear signed text
GPGME_SIG_MODE_DETACH : Detached signature */
gpgme_sig_mode_t sigMode = GPGME_SIG_MODE_CLEAR;
/* Begin setup of GPGME */
gpgme_check_version (NULL);
setlocale (LC_ALL, "");
gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
#ifndef HAVE_W32_SYSTEM
gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
#endif
/* End setup of GPGME */
// Create the GPGME Context
err = gpgme_new (&ctx);
// Error handling
fail_if_err (err);
// Set the context to textmode
gpgme_set_textmode (ctx, 1);
// Enable ASCII armor on the context
gpgme_set_armor (ctx, 1);
// Create a data object pointing to the input file
err = gpgme_data_new_from_file (&in, fileToBeSigned, 1);
// Error handling
fail_if_err (err);
// Create a data object pointing to the out buffer
err = gpgme_data_new (&out);
// Error handling
fail_if_err (err);
// Sign the contents of "in" using the defined mode and place it into "out"
err = gpgme_op_sign (ctx, in, out, sigMode);
// Error handling
fail_if_err (err);
// Open the output file
outputFile = fopen (outputFileName, "w+");
// Rewind the "out" data object
ret = gpgme_data_seek (out, 0, SEEK_SET);
// Error handling
if (ret)
fail_if_err (gpgme_err_code_from_errno (errno));
// Read the contents of "out" and place it into buf
while ((ret = gpgme_data_read (out, buf, BUF_SIZE)) > 0) {
// Write the contents of "buf" to "outputFile"
fwrite (buf, ret, 1, outputFile);
}
// Error handling
if (ret < 0)
fail_if_err (gpgme_err_code_from_errno (errno));
// Close "outputFile"
fclose(outputFile);
// Release the "in" data object
gpgme_data_release (in);
// Release the "out" data object
gpgme_data_release (out);
// Release the context
gpgme_release (ctx);
}
int
main (int argc, char **argv) {
if (argc != 3) {
printf("Usage: gpgsign <input file> <output file>\n");
exit (1);
}
printf("Signing %s and placing the result into %s\n", argv[1], argv[2]);
gpgSign(argv[1], argv[2]);
return 0;
}

This answer probably comes too late, but if I were you I'd rather use Keyczar which is a high-level crypto toolkit with a simple API. Java, C++, Python bindings are available.
GPGME is still quite low-level IMO for someone who needs crypto functionality without too much tweaking. Of course a crypto expert needs this type of complexity.
Personally, I try to avoid libraries that require me to set up this engine and that context in 100 lines of boilerplate code before I can do something basic... but I am no expert at anything.

Related

LibAio: Why I can obtain data without calling io_getevents method?

I tried to read file contents using Libaio, but I found that even if I didn't call io_getevents method, the expected contents are obtained.
Is it necessary to call the io_getevents method after I call the io_submit method?
If yes, why this issue happened?
If no, when should I call io_getevents to the read result? Can I repead to call it multi times?
here is the demo code:
#include <stdio.h>
#include <libaio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define error() printf("error [%s : %d]\n", __FILE__, __LINE__)
#define BUFF_SIZE 51
#define BUFF_CNT 50
#define READLEN 4194304
int main(int argc, char *argv[])
{
int fd = open(__FILE__, O_RDONLY);
if (fd == -1) {
error();
return -1;
}
io_context_t ctx = 0;
int err = io_setup(BUFF_CNT, &ctx);
if (err != 0) {
error();
return -1;
}
struct iocb *io = (struct iocb *)malloc(sizeof(struct iocb));
if (NULL == io) {
printf("alloc struct iocb failed");
return -1;
}
memset(io, 0x00, sizeof(io));
char double_check_m_buf[READLEN];
io_prep_pread(io, fd, double_check_m_buf, READLEN, 0);
int rc = io_submit(ctx, 1, &io);
if (rc < 0) {
printf("aio send read one block failed");
return -1;
}
printf("aio send read one block success, len: %d \n content: %s",strlen(double_check_m_buf), double_check_m_buf);
There are two things that may be going on here.
There are a bunch of cases where io_submit can't do asynchronous I/O. When those happen, it falls back to synchronous I/O. It's up to the caller to realize the requested I/O happened inline of the call.
In your case, you need to open the file with O_RDONLY|O_DIRECT. That will likely do the trick, presuming your filesystem supports AIO.
If you open __FILE__ with O_DIRECT, io_submit will bypass the kernel's buffer cache. It may still complete rapidly. Depending on what the underlying storage is, it may very well complete before you can inspect the buffer. It's an off-chance, but still, it's possible.
The only way to be sure your I/O has completed is to call io_getevents. That's the only way to retrieve the error if it fails. Here, __FILE__ is likely far shorter than 4 MiB, so you'll need the length of the read that's returned in that structure as well.

Link / use external library in QtCreator

With mingw's Msys tool I've successfully build the opus-codec from source 1.1.tar.gz. The build produced some files, amongst which are libopus.a and libopus-0.dll. Now I want to try the trivial-example.c in QtCreator. I added the lib to my .pro-file and included opus.h in my main file. The compiler complains that it can't find the headers that are included in opus.h Shouldn't these be included within the lib? How do I need to setup my application to run the "trivial-example"?
My folder structure is:
main.cpp
opus_lib_test.pro
opus_lib_test.pro.user
include [folder]
opus.h (from the source include folder)
libs [folder]
libopus.a
libopus-0.dll
My .pro-file looks like
QT += core
QT -= gui
TARGET = opus_lib_test
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
INCLUDEPATH += $$PWD/include
LIBS += -L"C:/Qt/Qt5.2.1/Tools/QtCreator/bin/opus_lib_test/libs/" -llibopus
SOURCES += main.cpp
HEADERS += include/opus.h
and my main.cpp is here:
//#include <QCoreApplication>
#include "opus.h"
int main(int argc, char *argv[])
{
// QCoreApplication a(argc, argv);
// return a.exec();
// ----------------------------- trivial_example.c
char *inFile;
FILE *fin;
char *outFile;
FILE *fout;
opus_int16 in[FRAME_SIZE*CHANNELS];
opus_int16 out[MAX_FRAME_SIZE*CHANNELS];
unsigned char cbits[MAX_PACKET_SIZE];
int nbBytes;
/*Holds the state of the encoder and decoder */
OpusEncoder *encoder;
OpusDecoder *decoder;
int err;
if (argc != 3)
{
fprintf(stderr, "usage: trivial_example input.pcm output.pcm\n");
fprintf(stderr, "input and output are 16-bit little-endian raw files\n");
return EXIT_FAILURE;
}
/*Create a new encoder state */
encoder = opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &err);
if (err<0)
{
fprintf(stderr, "failed to create an encoder: %s\n", opus_strerror(err));
return EXIT_FAILURE;
}
/* Set the desired bit-rate. You can also set other parameters if needed.
The Opus library is designed to have good defaults, so only set
parameters you know you need. Doing otherwise is likely to result
in worse quality, but better. */
err = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE));
if (err<0)
{
fprintf(stderr, "failed to set bitrate: %s\n", opus_strerror(err));
return EXIT_FAILURE;
}
inFile = argv[1];
fin = fopen(inFile, "r");
if (fin==NULL)
{
fprintf(stderr, "failed to open file: %s\n", strerror(errno));
return EXIT_FAILURE;
}
/* Create a new decoder state. */
decoder = opus_decoder_create(SAMPLE_RATE, CHANNELS, &err);
if (err<0)
{
fprintf(stderr, "failed to create decoder: %s\n", opus_strerror(err));
return EXIT_FAILURE;
}
outFile = argv[2];
fout = fopen(outFile, "w");
if (fout==NULL)
{
fprintf(stderr, "failed to open file: %s\n", strerror(errno));
return EXIT_FAILURE;
}
while (1)
{
int i;
unsigned char pcm_bytes[MAX_FRAME_SIZE*CHANNELS*2];
int frame_size;
/* Read a 16 bits/sample audio frame. */
fread(pcm_bytes, sizeof(short)*CHANNELS, FRAME_SIZE, fin);
if (feof(fin))
break;
/* Convert from little-endian ordering. */
for (i=0;i<CHANNELS*FRAME_SIZE;i++)
in[i]=pcm_bytes[2*i+1]<<8|pcm_bytes[2*i];
/* Encode the frame. */
nbBytes = opus_encode(encoder, in, FRAME_SIZE, cbits, MAX_PACKET_SIZE);
if (nbBytes<0)
{
fprintf(stderr, "encode failed: %s\n", opus_strerror(nbBytes));
return EXIT_FAILURE;
}
/* Decode the data. In this example, frame_size will be constant because
the encoder is using a constant frame size. However, that may not
be the case for all encoders, so the decoder must always check
the frame size returned. */
frame_size = opus_decode(decoder, cbits, nbBytes, out, MAX_FRAME_SIZE, 0);
if (frame_size<0)
{
fprintf(stderr, "decoder failed: %s\n", opus_strerror(err));
return EXIT_FAILURE;
}
/* Convert to little-endian ordering. */
for(i=0;i<CHANNELS*frame_size;i++)
{
pcm_bytes[2*i]=out[i]&0xFF;
pcm_bytes[2*i+1]=(out[i]>>8)&0xFF;
}
/* Write the decoded audio to file. */
fwrite(pcm_bytes, sizeof(short), frame_size*CHANNELS, fout);
}
/*Destroy the encoder state*/
opus_encoder_destroy(encoder);
opus_decoder_destroy(decoder);
fclose(fin);
fclose(fout);
return EXIT_SUCCESS;
}
The header files referenced in opus.h:
#include "opus_types.h"
#include "opus_defines.h"
They are both from source include folder, the same as opus.h. I think your problem will be solved if you copy all .h files (5 including opus.h) from source include folder into include [folder] in your folder structure.
Header files are not included in lib, only cpp files are included. You need to specify header files separately.

Node.JS C++ Native Addon read/write file?

The current problem I am facing with my project is that I do not know how to read/write files from the native node.js addon.
I have to build a type of encryption decryption ( RC6 algorithm ) program. But in order to encrypt files, i should be able to somehow read and write to them from "node-webkit". I am building the .cc file with nw-gyp, and tried multiple possibilities but none worked.
I am building my project with "grunt-node-webkit-builder" and I simply want to read/write one file from the build folder "nw" where nw.exe is located.
The Structure looks like this:
.webkitbuilds
.releases
.nw
.win
.nw
encrypt.txt
ffmpegsumo.dll
icudt.dll
libEGL.dll
libGLESv2.dll
nw.exe
nw.pak
How can I read in my c++ native node.js addon that "encrypt.txt" file.
Help ?
Edit:
Is there any way to use libuv with crypto ++ ?
EDIT 2:
I have the following code. The moment I execute it, the window freezes.
hello.cc:
#include <node.h>
#include <v8.h>
#include <stdio.h>
#include <fcntl.h>
using namespace v8;
#define __S_IREAD 0400 /* Read by owner. */
#define __S_IWRITE 0200 /* Write by owner. */
#define __S_IEXEC 0100 /* Execute by owner. */
#define S_IRUSR __S_IREAD /* Read by owner. */
uv_loop_t* loop;
uv_fs_t open_req;
void open_cb(uv_fs_t* req);
const char* path = "encrypt.txt";
void open_cb(uv_fs_t* req) {
int result = req->result;
if (result == -1) {
fprintf(stderr, "Error at opening file: %s\n",
uv_strerror(uv_last_error(loop)));
}
uv_fs_req_cleanup(req);
printf("Successfully opened file.\n");
}
char *get(v8::Local<v8::Value> value, const char *fallback = "") {
if (value->IsString()) {
v8::String::AsciiValue string(value);
char *str = (char *) malloc(string.length() + 1);
strcpy(str, *string);
return str;
}
char *str = (char *) malloc(strlen(fallback) + 1);
strcpy(str, fallback);
return str;
}
Handle<Value> Encrypt(const Arguments& args) {
HandleScope scope;
char* textToEncrypt = get(args[0], "str");
char* password = get(args[1], "str");
loop = uv_default_loop();
int r = uv_fs_open(loop, &open_req, path, O_RDONLY, S_IRUSR, open_cb);
if (r) {
fprintf(stderr, "Error at opening file: %s\n",
uv_strerror(uv_last_error(loop)));
}
uv_run(loop, UV_RUN_DEFAULT);
return scope.Close(String::New("done"));
}
void Init(Handle<Object> exports) {
exports->Set(String::NewSymbol("Encrypt"),
FunctionTemplate::New(Encrypt)->GetFunction());
}
NODE_MODULE(hello, Init)
In Javascript :
var application = require('./js/build/Release/hello');
var encrypted_data = "";
$(document).ready(function() {
$('#btn_encrypt').on('click', function() {
encrypted_data = application.Encrypt("val","val");
console.log(encrypted_data);
})
});

ioctrl using SCSI pass through

Using Windows I can easily communicate with my USB device using the following simplified code:
DWORD dwJunk; // discard results from DeviceIOControl()
int iReply;
char cBuffer[100];
// cBuffer is initialized here.
HANDLE hDevice; // handle to the drive to be examined
CString sDrive = _T(\\\\.\\H:); // drive H: for this test
hDevice = CreateFile(sDrive, // drive to open
GENERIC_READ | GENERIC_WRITE, // read and write access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
iReply = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &cBuffer, sizeof(cBuffer), &cBuffer, sizeof(cBuffer), &dwJunk, (LPOVERLAPPED)NULL);
I'm trying to do the same in linux but have not been able to figure out the ioctrl() parameters, or better put the structure. A code snippet would be vey much appreciated. Thanks.
Unfortunately the code I modified using your link didn't return any results. Here's the stripped code I used. ioctl() returned without errors:
#define DEF_TIMEOUT 5000 // 5 seconds
char cDiskName[] = "/dev/sg3";
int fd = open(cDiskName, O_RDWR);
if (fd < 0)
{
printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno));
return 1;
}
unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0};
struct sg_io_hdr io_hdr;
unsigned char cIOBuffer[100];
// buffer initialization code omitted
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(turCmbBlk);
io_hdr.mx_sb_len = sizeof(cIOBuffer);
io_hdr.dxfer_direction = SG_DXFER_NONE;
io_hdr.cmdp = turCmbBlk;
io_hdr.sbp = cIOBuffer;
io_hdr.timeout = DEF_TIMEOUT;
if (ioctl(fd, SG_IO, &io_hdr) < 0)
{
printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno));
}
// Code returned here without any errors but cIOBuffer remains unchanged.
Maybe the call needs a different request code?
Here's some more documentation:
Notes on Linux's SG driver version 2.1.36
SCSI-Programming, page 8 (handle_SCSI_cmd function), page 9, page 11 (example) and some more
Generic SCSI Target Subsystem for Linux
See here:
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
Parameters:
Filedescriptor (must be open!)
Request code number (depends on device)
Untyped pointer to memory (going to / coming from driver)
Example
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
void main(int argc, char **argv)
{
const char *filename;
int fd;
filename = argv[1];
fd = open(filename, O_WRONLY);
ioctl(fd, USBDEVFS_RESET, 0);
close(fd);
return;
}
Documentation:
ioctl(2) - Linux man page
IOCTL(2)
Generic I/O Control operations (GNU libc)
The ioctl() Requests
usb.c (Example that might help you)
Linux / Unix Command: ioctl
How to Reset USB Device in Linux (Example)
An example Program with IOCTL
Edit
#define BUFF_SIZE 100 // - Buffersize
#define DEF_TIMEOUT 5000 // 5 seconds
char cDiskName[] = "/dev/sg3";
int fd = open(cDiskName, O_RDWR);
if (fd < 0)
{
printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno));
return 1;
}
unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0};
struct sg_io_hdr *p = (struct sg_io_hdr *) malloc(sizeof(struct sg_io_hdr)); // - dynamic memory allocation - free() required somewhere
unsigned char cIOBuffer[BUFF_SIZE];
unsigned char replyBuffer[BUFF_SIZE]; // - dxfer buffer
// buffer initialization code omitted
memset(p, 0, sizeof(struct sg_io_hdr));
p->interface_id = 'S';
p->cmd_len = sizeof(turCmbBlk);
p->mx_sb_len = BUFF_SIZE;
p->dxfer_direction = SG_DXFER_NONE;
p->cmdp = turCmbBlk;
p->sbp = cIOBuffer;
p->timeout = DEF_TIMEOUT;
p->flags = SG_FLAG_DIRECT_IO; // - Does this help?
p->dxferp = replyBuffer; // - Set dxferp buffer - (A)
p->dxfer_len = BUFF_SIZE; // - buffersize
if (ioctl(fd, SG_IO, p) < 0)
{
printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno));
}
// Code returned here without any errors but cIOBuffer remains unchanged.
Note (A): Please try setting your input / output buffer you work on here.
Documentation:
SCSI Generic HOWTO, SG_IO_HDR_T
Tour the Linux generic SCSI driver

How to read the failure log message displayed when a system call failed in C++?

I have a C++ code that calls a test. I am doing a system call to execute this test. When this test fails, it will display something like this " ERROR: One or more devices of following component type(s) could not be discovered:"
I have a C++ code that runs on Linux redhat and it is capable of detecting if the system call pass or failed. But it can not capture the error message (ERROR: One or more devices of following component type(s) could not be discovered:) and append into the log file or print it.
Can someone please tell me how to capture the error message (ERROR: One or more devices of following component type(s) could not be discovered:)?
PS: I am an intern, any help would be really nice.
#include<iostream.h>
int main ()
{
int i;
if (system(NULL))
puts ("Ok");
else
exit (1);
i=system("hpsp --discover -verbose --user Admin --oapasswd password");
printf ("The value returned was: %d.\n",i);
return false;
}
Instead of using system() use popen(). This will open a pipe capturing the standard output of the test program so that your program can read it via the pipe.
Example EDITED:
#define _BSD_SOURCE 1
#define BUFFSIZE 400
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *cmd = "hpsp --discover -verbose --user Admin --oapasswd password";
char buf[BUFFSIZE];
char* searchResult;
int testPassed = 0;
FILE *ptr;
if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFFSIZE, ptr) != NULL)
{
if ((searchResult = strstr(buf, "The test passed")) != NULL )
{
testPassed = 1;
break;
}
}
if (testPassed)
printf("yea!!\n");
else
printf("boo!!\n");
pclose(ptr);
return 0;
}
You can use dup and dup2 to backup/store the stderr file descriptor to redirect to your log file. Well, I'm guessing that errors go to stderr anyways.
Here's an example if you just want to write to a log file.
//open log file, choose whatever flags you need
int logfd = open("whateveryourlogfileis", O_APPEND);
//back up stderr file descriptor
int stderr_copy = dup(STDERR_FILENO);
//redirect stderr to your opened log file
dup2(logfd, STDERR_FILENO);
//close the original file descriptor for the log file
close(logfd);
//system call here
//restore stderr
dup2(stderr_copy, STDERR_FILENO);
//close stderr copy
close(stderr_copy);
Note: dup2 closes the target file descriptor before dup2ing to it. dup just duplicates the file descriptor and returns to you the new file descriptor.