GPGMEを使う

2020/04/04 17:06:27

改訂履歴
改訂 0.002017/07/02 13:21:10aaauuue

初版


目次

1. はじめに
2. インストール
3. コンパイル方法
4. コード
4.1. 準備
4.2. キー
4.3. サイン
4.4. 暗号化と復号化
5. さいごに

GPGME(https://www.gnupg.org/software/gpgme/index.html)とは、GnuPG Make Easyの略で、コードから簡単にGnuPGの機能を使用する事を目的としたライブラリです。ライブラリはC言語で作成されているのですが、C++やPython、Rubyなど様々なバインディングが存在します。

今回は、gpgmeのテストコードを元にgpgmeを使用したコードを書いてみます。

動作確認には以下の環境を用いています。

  • Ubuntu 14.04 LTS

  • gcc 4.8.5

  • GPGME 1.9.0

Ubuntuではapt-getからインストールを行う事もできますが、それではバージョンが古いのでhttps://www.gnupg.org/download/index.html#gpgmeから最新版のコードをダウンロードてきます。gpgmeの他にlibgpg-errorというライブラリも必要となるので、それも同時にダウンロードしてきます。

コンパイルは通常のGNUパッケージ同様、configure,make,make installで完了します。gpgmeはあまり依存性のないライブラリなので、通常のシステムが稼動しているならば、コンパイルの時点で躓く事はないと思います。

gpgmeを使用したコードをコンパイルする時には、以下のようにします。

gcc -o foo foo.c `gpgme-config --cflags --libs`

ここから実際にコードを書いていきます。

まず、gpgmeで頻繁に使用する部分をまとめます。例1「gpgmeutil.h」はgpgmeのテストコードから抜粋した、頻繁に使用する部分のコードです。


GnuPGで使用できるキーを全て列挙してみます。例3「keys.c」はそのコードでです。

例3 keys.c


#include <stdio.h>
#include <stdlib.h>

#include "gpgmeutil.h"

void print_key( gpgme_key_t key )
{
     gpgme_subkey_t subkey;
     
     if( key ) {
          printf( "---keys---\n" );
          printf( "invalid %d\n" \
                  "fingerprint: [%s]\n" \
                  "uid: [%s]\n" \
                  "name: [%s]\n" \
                  "email: [%s]\n",
                  key->invalid,
                  nullout( key->fpr ),
                  nullout( key->_last_uid->uid ),
                  nullout( key->_last_uid->name ),
                  nullout( key->_last_uid->email ) 
                  );
          subkey = key->subkeys;
          while( subkey != NULL ) {
               printf( "===subkey===\n" );
               printf( "keyid: [%s]\n" \
                       "fingerprint: [%s]\n" \
                       "keygrip: [%s]\n",
                       nullout( subkey->keyid ),
                       nullout( subkey->fpr ),
                       nullout( subkey->keygrip )
                       );
               subkey = subkey->next;
          }
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t   ctx;
     gpgme_error_t err;
     gpgme_key_t   key;
     gpgme_key_t   akey;
     gpgme_data_t  buf;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     err = gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     fail_if_err( err );
                                                                                    (1)
     gpgme_set_armor( ctx, 1 );
                                                                                    (2)
     err = gpgme_op_keylist_start( ctx, NULL, 0 );                                  (2)
     fail_if_err( err );                                                            (2)
                                                                                    (2)
     while( !gpgme_op_keylist_next( ctx, &key ) ) {                                 (2)
          print_key( key );                                                         (2)
     }                                                                              (2)
                                                                                    (2)
     err = gpgme_op_keylist_end( ctx );                                             (2)
     fail_if_err( err );

     printf( "-----\ngetting key from id\n" );                                      (3)
     err = gpgme_get_key( ctx, "foo@bar.com", &key, 0 );
     fail_if_err( err );

     print_key( key );

     printf( "export valid key\n" );                                                (4)
     err = gpgme_data_new( &buf );                                                  (4)
     fail_if_err( err );                                                            (4)
                                                                                    (4)
     err = gpgme_op_export_keys( ctx, &key, 0, buf );                               (4)
     fail_if_err( err );                                                            (4)
                                                                                    (4)
     print_data( buf );

     gpgme_data_release( buf );
     gpgme_release( ctx );
     
     return 0;
}


/* 
 * compile-command: "gcc -std=c99 -g3 -o enumkey enumkey.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

gpgmeの動作をtext形式に。これ以後の出力は人に読める形式になる。

(2)

キーの列挙。GnuPGに登録されているキーが全て列挙される。

(3)

特定のキーの取得

(4)

取得したキーのエクスポート。特定のデータの取得と操作はgpgmeが用意したデータ構造を介して行う。


gpgmeからキーを使用してファイルにサインをしてみます。例4「sign.c」は実際のコードです。説明にもあるように、今回はサインの後ファイルの内容全てを暗号化して出力します。

例4 sign.c


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t           ctx;
     gpgme_error_t         err;
     gpgme_key_t           key;
     gpgme_data_t          in;
     gpgme_data_t          out;
     gpgme_data_t          plain;
     gpgme_sign_result_t   result;
     gpgme_verify_result_t vresult;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );                             (1)
     gpgme_set_textmode( ctx, 1 );                                                  (1)
     gpgme_set_armor( ctx, 1 );                                                     (2)
     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_get_key( ctx, "foo@bar.com", &key, 0 );
     fail_if_err( err );
                                                                                    (3)
     err = gpgme_data_new_from_file( &in, "sign.c", 1 );
     fail_if_err( err );

     err = gpgme_data_new( &out );
     fail_if_err( err );
                                                                                    (4)
     gpgme_signers_clear( ctx );                                                    (4)
     err = gpgme_signers_add( ctx, key );                                           (4)
     fail_if_err( err );                                                            (4)
     gpgme_key_unref( key );

     set_password( "xxx\n" );                                                       (5)
     err = gpgme_op_sign( ctx, in, out, GPGME_SIG_MODE_NORMAL );
     clear_password_buffer();
     fail_if_err( err );

     print_data( out );

     /* verify */
     err = gpgme_data_new( &plain );
     fail_if_err( err );

     gpgme_data_seek( out, 0, SEEK_SET );
     gpgme_data_seek( in, 0, SEEK_SET );
     err = gpgme_op_verify( ctx, out, NULL, plain );
     fail_if_err( err );
                                                                                    (6)
     vresult = gpgme_op_verify_result( ctx );
     if( vresult->signatures->summary & GPGME_SIGSUM_VALID ) {
          printf( "\nsignature is valid.\n" );
     } else {
          printf( "\nsignature is invalid.\n" );
     }

     gpgme_data_release( plain );
     gpgme_data_release( out );
     gpgme_data_release( in );

     gpgme_release( ctx );

     return 0;
}

/*
 * compile-command: "gcc -std=c99 -g3 -o sign sign.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

gpgmeの動作をtext形式に。これ以後の出力は人に読める形式になる。

(2)

サインをする時に使用するキーのパスフレーズを設定するためのコールバック関数を登録する

(3)

サインしたいデータをファイルから読み込む

(4)

サインに使用するキーの登録。ここでは一つしか登録していないが、複数回関数を呼び出す事で複数のキーを登録する事ができる。

(5)

サインを行う。今回はファイルの内容ごとサインをした。

(6)

サインの有効性の確認


例4「sign.c」ではファイルごと暗号化しました。しかし例5「sign2a.c」ではサインの内容のみ暗号化して出力します。

例5 sign2a.c


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t   ctx;
     gpgme_error_t err;
     gpgme_key_t   key;
     gpgme_data_t  in;
     gpgme_data_t  out;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     gpgme_set_textmode( ctx, 1 );
     gpgme_set_armor( ctx, 1 );
     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_get_key( ctx, "foo@bar.com", &key, 0 );
     fail_if_err( err );

     err = gpgme_data_new_from_file( &in, "sign2a.c", 1 );
     fail_if_err( err );

     err = gpgme_data_new( &out );
     fail_if_err( err );

     gpgme_signers_clear( ctx );
     err = gpgme_signers_add( ctx, key );
     fail_if_err( err );
     gpgme_key_unref( key );

     set_password( "xxx\n" );                                                       (1)
     err = gpgme_op_sign( ctx, in, out, GPGME_SIG_MODE_DETACH );
     clear_password_buffer();
     fail_if_err( err );

     print_data( out );

     gpgme_data_release( out );
     gpgme_data_release( in );

     gpgme_release( ctx );

     return 0;
}

/* 
 * compile-command: "gcc -std=c99 -g3 -o sign2a sign2a.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

ファイルとサインは別々に出力する


例6「sign2b.c」は、例5「sign2a.c」で出力したサインを検証するためのコードです。

例6 sign2b.c


#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t            ctx;
     gpgme_error_t          err;
     gpgme_key_t            key;
     gpgme_data_t           sig;
     gpgme_data_t           msg;
     gpgme_sign_result_t    result;
     gpgme_verify_result_t  vresult;
     FILE                  *fp_sig = NULL;
     FILE                  *fp_msg = NULL;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     gpgme_set_textmode( ctx, 1 );
     gpgme_set_armor( ctx, 1 );

     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_get_key( ctx, "foo@bar.com", &key, 0 );
     fail_if_err( err );

     gpgme_signers_clear( ctx );
     err = gpgme_signers_add( ctx, key );
     fail_if_err( err );
     gpgme_key_unref( key );
                                                                                    (1)
     fp_sig = fopen( "./sign2a.c.asc", "rb" );
     err = gpgme_data_new_from_stream( &sig, fp_sig );
     fail_if_err( err );

     fp_msg = fopen( "./sign2a.c", "rb" );
     err = gpgme_data_new_from_stream( &msg, fp_msg );
     fail_if_err( err );
                                                                                    (2)
     err = gpgme_op_verify( ctx, sig, msg, NULL );
     vresult = gpgme_op_verify_result( ctx );

     if( vresult->signatures->summary & GPGME_SIGSUM_VALID ) {
          printf( "valid signature for sign2a.c\n" );
     } else {
          printf( "invalid signature\n" );
     }

     gpgme_data_release( sig );
     gpgme_data_release( msg );

     gpgme_release( ctx );

     return 0;
}

/*
 * compile-command: "gcc -std=c99 -g3 -o sign2b sign2b.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

別々にしたサインの読み込み

(2)

サインの有効性の確認


gpgmeを使用してファイルなどの暗号化と復号化を行ってみます。

例7「encrypt_keys.c」はキーを使用してファイルを暗号化するためのコードです。GnuPGは暗号化の際に複数個のキーを使用する事ができます。もちろん、コードでもこれが再現可能で、その場合は、説明にもあるように暗号化に使用するキーを複数個指定します。

例7 encrypt_keys.c


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t   ctx;
     gpgme_error_t err;
     gpgme_key_t   key;
     gpgme_key_t   recp_keys[2] = { NULL, NULL };
     gpgme_data_t  in;
     gpgme_data_t  out;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     gpgme_set_textmode( ctx, 1 );
     gpgme_set_armor( ctx, 1 );
     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_get_key( ctx, "foo@bar.com", &key, 0 );
     fail_if_err( err );

     err = gpgme_data_new_from_file( &in, "encrypt_keys.c", 1 );
     fail_if_err( err );

     err = gpgme_data_new( &out );
     fail_if_err( err );
                                                                                    (1)
     recp_keys[0] = key;

     set_password( "xxx\n" );                                                       (2)
     err = gpgme_op_encrypt( ctx, recp_keys, GPGME_ENCRYPT_ALWAYS_TRUST, in, out );
     clear_password_buffer();
     fail_if_err( err );

     print_data( out );

     gpgme_data_release( out );
     gpgme_data_release( in );

     gpgme_release( ctx );

     return 0;
}


/* 
 * compile-command: "gcc -std=c99 -g3 -o encrypt_keys encrypt_keys.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

ファイルを暗号化するためのキーを登録。複数個のキーを指定すれば、複数個のキーで暗号化できる。

(2)

暗号化を行う


例8「decrypt_keys.c」はキーを用いて暗号化されたファイルを復号化するためのコードです。これも例7「encrypt_keys.c」同様、複数個のキーを指定すれば複数個のキーで復号化できます。

例8 decrypt_keys.c


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t   ctx;
     gpgme_error_t err;
     gpgme_key_t   key;
     gpgme_key_t   recp_keys[2] = { NULL, NULL };
     gpgme_data_t  in;
     gpgme_data_t  out;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     gpgme_set_textmode( ctx, 1 );
     gpgme_set_armor( ctx, 1 );
     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_get_key( ctx, "foo@bar.com", &key, 0 );
     fail_if_err( err );

     err = gpgme_data_new_from_file( &in, "encrypt_keys.c.gpg", 1 );
     fail_if_err( err );

     err = gpgme_data_new( &out );
     fail_if_err( err );
                                                                                    (1)
     gpgme_signers_clear( ctx );                                                    (1)
     err = gpgme_signers_add( ctx, key );                                           (1)
     fail_if_err( err );                                                            (1)
     gpgme_key_unref( key );

     set_password( "xxx\n" );
     err = gpgme_op_decrypt( ctx, in, out );
     clear_password_buffer();
     fail_if_err( err );

     print_data( out );

     gpgme_data_release( out );
     gpgme_data_release( in );

     gpgme_release( ctx );

     return 0;
}



/* 
 * compile-command: "gcc -std=c99 -g3 -o decrypt_keys decrypt_keys.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

復号化する時のキーを登録。複数個登録する事で、複数のキーによる復号化も可能


例9「encrypt_symmetric.c」は共通鍵暗号を使用してファイルを暗号化するコードです。

例9 encrypt_symmetric.c


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t   ctx;
     gpgme_error_t err;
     gpgme_data_t  in;
     gpgme_data_t  out;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     gpgme_set_textmode( ctx, 1 );
     gpgme_set_armor( ctx, 1 );
     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_data_new_from_file( &in, "encrypt_symmetric.c", 1 );
     fail_if_err( err );

     err = gpgme_data_new( &out );
     fail_if_err( err );

     set_password( "xxx\n" );                                                       (1)
     err = gpgme_op_encrypt( ctx, NULL, GPGME_ENCRYPT_ALWAYS_TRUST, in, out );
     clear_password_buffer();
     fail_if_err( err );

     print_data( out );

     gpgme_data_release( out );
     gpgme_data_release( in );

     gpgme_release( ctx );

     return 0;
}


/* 
 * compile-command: "gcc -std=c99 -g3 -o encrypt_symmetric encrypt_symmetric.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

(2)でキーを指定した部分をNULLにするとパスフレーズを使用した暗号化をする事ができる


例10「decrypt_symmetric.c」は共通鍵暗号で暗号化されたファイルを復号化するコードです。

例10 decrypt_symmetric.c


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "gpgmeutil.h"

static char *_password = NULL;

gpgme_error_t passphrase_cb( void *opaque, const char *uid_hint,
                             const char *passphrase_info, int last_was_bad,
                             int fd )
{
     int   res;
     char *pass = _password;
     int   passlen = strlen( pass );
     int   off = 0;

     do {
          res = write( fd, &pass[off], passlen - off );
          if( res > 0 )
               off += res;
     } while( res > 0 && off != passlen );

     return off == passlen ? 0 : gpgme_error_from_errno( errno );

     return 0;
}

void set_password( char *password )
{
     size_t len = 0;

     clear_password_buffer();

     len = strlen( password );
     _password = ( char * )malloc( sizeof( char ) * len );
     memset( _password, 0, len );

     strncpy( _password, password, len );
}

void clear_password_buffer()
{
     if( _password != NULL ) {
          free( _password );
          _password = NULL;
     }
}

int main( int argc, char **argv )
{
     gpgme_ctx_t   ctx;
     gpgme_error_t err;
     gpgme_data_t  in;
     gpgme_data_t  out;

     init_gpgme();

     err = gpgme_new( &ctx );
     fail_if_err( err );

     gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP );
     gpgme_set_textmode( ctx, 1 );
     gpgme_set_armor( ctx, 1 );
     gpgme_set_passphrase_cb( ctx, passphrase_cb, NULL );

     err = gpgme_data_new_from_file( &in, "encrypt_symmetric.c.gpg", 1 );
     fail_if_err( err );

     err = gpgme_data_new( &out );
     fail_if_err( err );

     set_password( "xxx\n" );                                                       (1)
     err = gpgme_op_decrypt( ctx, in, out );;
     clear_password_buffer();
     fail_if_err( err );

     print_data( out );

     gpgme_data_release( out );
     gpgme_data_release( in );

     gpgme_release( ctx );

     return 0;
}



/* 
 * compile-command: "gcc -std=c99 -g3 -o decrypt_symmetric decrypt_symmetric.c"
 * Local variables:
 * compile-command: "make"
 * End:
 */

(1)

キーを指定せずに復号化を行うとパスフレーズを使用した復号化になる


gpgmeに付属のテストコードを下敷に、簡単にですがコードをまとめてみました。コードを書いていて思ったのは、GnuPG Make Easyの言葉通り、非常に簡単にGnuPGの各種機能が使用できました。

今後のネットワーク環境では暗号化がますます重要な位置を占めてきます。その時に簡単にコードから暗号化などの機能が使用できるのはありがたいものです。この場を借りてGnuPG及びGPGMEの作者にお礼申し上げます。