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で頻繁に使用する部分をまとめます。例1「gpgmeutil.h」はgpgmeのテストコードから抜粋した、頻繁に使用する部分のコードです。
例1 gpgmeutil.h
#ifndef __GPGUTIL_H__ #define __GPGUTIL_H__ #include <stdlib.h> #include <locale.h> #include <errno.h> #define _FILE_OFFSET_BITS 64 #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 init_gpgme( void ) { /* Initialize the locale environment. */ setlocale( LC_ALL, "" ); gpgme_check_version( NULL ); gpgme_set_locale( NULL, LC_CTYPE, setlocale( LC_CTYPE, NULL ) ); #ifdef LC_MESSAGES gpgme_set_locale( NULL, LC_MESSAGES, setlocale( LC_MESSAGES, NULL ) ); #endif } /* from gpgme test code */ void print_data( gpgme_data_t dh ) { #define BUF_SIZE 512 char buf[BUF_SIZE + 1]; int ret; ret = gpgme_data_seek( dh, 0, SEEK_SET ); if( ret ) fail_if_err( gpgme_err_code_from_errno( errno ) ); while( ( ret = gpgme_data_read( dh, buf, BUF_SIZE ) ) > 0 ) fwrite( buf, ret, 1, stdout ); if( ret < 0 ) fail_if_err( gpgme_err_code_from_errno( errno ) ); /* Reset read position to the beginning so that dh can be used as input for another operation after this method call. For example, dh is an output from encryption and also is used as an input for decryption. Otherwise GPG_ERR_NO_DATA is returned since this method moves the read position. */ ret = gpgme_data_seek( dh, 0, SEEK_SET ); } char *nullout( char *src ) { if( src == NULL ) { return ""; } return src; } #endif /* __GPGUTIL_H__ */
実際に使用しているgpgmeのバージョンを表示して、GPGが使用可能かどうか確かめます。例2「initgpgme.c」は、そのコードです。
コードの説明にもありますが、gpgmeはcontextを処理の単位としています。gpgmeで何か処理を行う場合は必ずcontextを介する必要があります。
例2 initgpgme.c
#include <stdio.h> #include "gpgmeutil.h" int main( int argc, char **argv ) { gpgme_ctx_t ctx; gpgme_error_t err; char *version = NULL; init_gpgme(); (1) err = gpgme_new( &ctx ); fail_if_err( err ); version = gpgme_check_version( NULL ); if( version ) { printf( "gpgme version: [%s]\n", version ); } err = gpgme_engine_check_version( GPGME_PROTOCOL_OpenPGP ); if( err != GPG_ERR_NO_ERROR ) { printf( "OpenPGP is not enabled.\n" ); } err = gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP ); fail_if_err( err ); gpgme_release( ctx ); return 0; } /* * compile-command: "gcc -std=c99 -g3 -o initgpgme initgpgme.c" * Local variables: * compile-command: "make" * End: */
(1) | gpgmeは全ての操作をcontextを介して行う。contextを複数作成すれば、別々の動作を平行して行う事も出来る |
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) | キーを指定せずに復号化を行うとパスフレーズを使用した復号化になる |