Symfoware

Symfowareについての考察blog

nginx 拡張モジュール SHA1ハッシュの計算とbase64エンコード

nginxの拡張モジュールを作ってみています。
nginx 拡張モジュールの作り方

SHA1_HMACの計算方法とbase64エンコードについて調べてみました。


SHA1、HMAC、base64



lua-nginx-module

こちらのソースが非常に参考になりました。
具体的には、ngx_http_lua_string.c

暗号化するとき、opensslモジュールが必要になります。
configureするときに、--with-http_ssl_moduleを指定します。


# ./configure --prefix=/opt/nginx \
> --with-http_ssl_module \
> --add-module=/usr/local/src/sample-module





試行錯誤しながら書いたソースがこちら。


  1. #include <ngx_config.h>
  2. #include <ngx_core.h>
  3. #include <ngx_http.h>
  4. #include "ngx_sha1.h"
  5. #include <openssl/evp.h>
  6. #include <openssl/hmac.h>
  7. // nginx.confの設定値取得用
  8. typedef struct {
  9.     ngx_flag_t enable; // on,offフラグ
  10. } ngx_http_sample_loc_conf_t;
  11. static ngx_int_t ngx_http_sample_handler(ngx_http_request_t *r);
  12. static void *ngx_http_sample_create_loc_conf(ngx_conf_t *cf);
  13. static char *ngx_http_sample_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
  14. static ngx_int_t ngx_http_sample_init(ngx_conf_t *cf);
  15. // confファイルの記載内容読み取り指定
  16. static ngx_command_t ngx_http_sample_commands[] = {
  17.     // on,off制御
  18.     { ngx_string("sample"), // キーの名称
  19.      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, // どのconfを読むか
  20.      ngx_conf_set_flag_slot, // on,off 0,1の読み取り
  21.      NGX_HTTP_LOC_CONF_OFFSET,
  22.      offsetof(ngx_http_sample_loc_conf_t, enable), // ngx_http_sample_loc_conf_t->enableに設定
  23.      NULL },
  24.     
  25.      ngx_null_command
  26. };
  27. static ngx_http_module_t ngx_http_sample_module_ctx = {
  28.     NULL, /* preconfiguration */
  29.     ngx_http_sample_init, /* postconfiguration */
  30.     NULL, /* create main configuration */
  31.     NULL, /* init main configuration */
  32.     NULL, /* create server configuration */
  33.     NULL, /* merge server configuration */
  34.     ngx_http_sample_create_loc_conf, /* create location configuration */
  35.     ngx_http_sample_merge_loc_conf /* merge location configuration */
  36. };
  37. ngx_module_t ngx_http_sample_module = {
  38.     NGX_MODULE_V1,
  39.     &ngx_http_sample_module_ctx, /* module context */
  40.     ngx_http_sample_commands, /* module directives */
  41.     NGX_HTTP_MODULE,             /* module type */
  42.     NULL,                         /* init master */
  43.     NULL,                         /* init module */
  44.     NULL,                         /* init process */
  45.     NULL,                         /* init thread */
  46.     NULL,                         /* exit thread */
  47.     NULL,                         /* exit process */
  48.     NULL,                         /* exit master */
  49.     NGX_MODULE_V1_PADDING
  50. };
  51. // conf読み取り初期化
  52. static void *
  53. ngx_http_sample_create_loc_conf(ngx_conf_t *cf)
  54. {
  55.     ngx_http_sample_loc_conf_t *conf;
  56.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sample_loc_conf_t));
  57.     if (conf == NULL) {
  58.         return NGX_CONF_ERROR;
  59.     }
  60.     
  61.     // 初期値はoff
  62.     conf->enable = NGX_CONF_UNSET;
  63.     
  64.     //conf->index = ngx_http_get_variable_index(cf, &ngx_http_sample_access_key);
  65.     //ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0, "ngx_http_sample_create_loc_conf");
  66.     
  67.     return conf;
  68. }
  69. // 読み取ったconfの値をマージする
  70. static char *
  71. ngx_http_sample_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
  72. {
  73.     ngx_http_sample_loc_conf_t *prev = parent;
  74.     ngx_http_sample_loc_conf_t *conf = child;
  75.     
  76.     ngx_conf_merge_value(conf->enable, prev->enable, 0);
  77.     
  78.     return NGX_CONF_OK;
  79. }
  80. // 初期化処理
  81. static ngx_int_t
  82. ngx_http_sample_init(ngx_conf_t *cf)
  83. {
  84.     ngx_http_handler_pt        *h;
  85.     ngx_http_core_main_conf_t *cmcf;
  86.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
  87.     h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
  88.     if (h == NULL) {
  89.         return NGX_ERROR;
  90.     }
  91.     *h = ngx_http_sample_handler;
  92.     //ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0, "ngx_http_sample_init");
  93.     return NGX_OK;
  94. }
  95. static ngx_int_t
  96. ngx_http_sample_handler(ngx_http_request_t *r)
  97. {
  98.     // ここに処理を記載する
  99.     ngx_http_sample_loc_conf_t *alcf;
  100.     
  101.     u_char                 *sec, *sts;
  102.     size_t                 lsec, lsts;
  103.     unsigned int             md_len;
  104.     unsigned char            md[EVP_MAX_MD_SIZE];
  105.     const EVP_MD            *evp_md;
  106.     ngx_str_t src, dst;
  107.     u_char *p;
  108.     
  109.     
  110.     // conf読み込み
  111.     alcf = ngx_http_get_module_loc_conf(r, ngx_http_sample_module);
  112.     
  113.     // onになっていなければ終了
  114.     if (!alcf->enable) {
  115.         return NGX_OK;
  116.     }
  117.     
  118.     sec = (u_char*)"sec_key"; // 暗号化キー
  119.     sts = (u_char*)"test_value"; // 暗号化する文字列
  120.     lsec = strlen((char*)sec);
  121.     lsts = strlen((char*)sts);
  122.     
  123.     ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "access sample module %d", lsec);
  124.     ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "access sample module %d", lsts);
  125.     
  126.     evp_md = EVP_sha1();
  127.     // HMAC計算 結果はmdに代入される
  128.     HMAC(evp_md, sec, lsec, sts, lsts, md, &md_len);
  129.     
  130.     // base64エンコード用にデータをコピー
  131.     p = ngx_pnalloc(r->connection->pool, md_len);
  132.     p = ngx_copy(p, md, md_len);
  133.     
  134.     // base64 変換元バイナリデータ
  135.     src.data = md;
  136.     src.len = md_len;
  137.     
  138.     // base64変換先 ここでdataに上記でコピーした値を設定
  139.     dst.len = ngx_base64_encoded_length(src.len);
  140.     dst.data = p;
  141.     // base64変換実行
  142.     ngx_encode_base64(&dst, &src);
  143.     
  144.     // 結果をログ出力
  145.     ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "access sample module %V", &dst);
  146.     
  147.     return NGX_OK;
  148. }






正しく動作しているかのチェック用のPythonプログラムはこれ。


  1. import hmac
  2. import hashlib
  3. import base64
  4. secret = 'sec_key'
  5. plaintext = 'test_value'
  6. signature = base64.b64encode(hmac.new(secret, plaintext, hashlib.sha1).digest())
  7. print signature






出力される値が双方
「iksyOnN66roGUOLY57ZgH8uVPXU=」
になります。

正しく処理されているようですね。
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/12/14(日) 17:20:05|
  2. 備忘録
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<nginx 拡張モジュール URLデコードの方法(ngx_unescape_uri) | ホーム | nginx 拡張モジュール 設定ファイルの値を取得する>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1568-dbfc6379
この記事にトラックバックする(FC2ブログユーザー)