2013年2月24日日曜日

[OpenSSL]OpenSSL ライブラリを使用したプログラム

テストプログラム
#include <iostream>
#include <iomanip>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/des.h>
#include <openssl/aes.h>
using namespace std;
static unsigned char test_data[32]={
        0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x20,
        0x4E,0x6F,0x77,0x20,0x69,0x73,0x20,0x74,
        0x68,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,
        0x66,0x6F,0x72,0x20,0x00,0x00,0x00,0x00,
};
static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
static unsigned char cbc2_key[8]={0xf1,0xe0,0xd3,0xc2,0xb5,0xa4,0x97,0x86};
static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};

/* DES CBC 用 encode 済み確認データ */
static unsigned char cbc_ok[32]={
    0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4,
    0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb,
    0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68,
    0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4
};

/* 3DES CBC 用 encode 済み確認データ */
static unsigned char cbc3_ok[32]={
    0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0,
    0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC,
    0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4,
    0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75
};

static unsigned char aes_cbc_key[] = {
    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
    0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10
};

static unsigned char aes_cbc_iv[] = {
    0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0x01,
    0x98,0x76,0x54,0x32,0x10,0xfe,0xdc,0xba
};

/* AES 128 bit CBC 用 encode 済み確認データ */
static unsigned char aes128_cbc_ok[] = {
    0xea,0xca,0xd1,0x95,0xf1,0x00,0xf8,0x77,
    0x5d,0x8b,0xb8,0x2a,0x5e,0xb7,0x04,0xf6,
    0x0f,0x8f,0x2c,0x09,0xaf,0xf6,0x76,0x06,
    0xbd,0x1e,0x19,0xac,0x57,0x68,0xfc,0x2d
};

/**
 * @brief バッファの dump を表示する
 *
 * @param p バッファポインタ
 * @param len バッファ長
 */
static void disp_dump(unsigned char* p, int len)
{
    int i;

    for (i = 0; i < len; i++) {
        cout << hex << setw(2) << setfill('0') << (unsigned int)(*(p + i)) << " ";
        if (((i+1)%16==0) && ((i+1) != len)) {
            cout << endl;
        }
    }
    cout << endl;
    cout << endl;
}

/**
 * @brief MD5 のテスト
 *
 * コマンドラインでの MD5 値を求める方法
 * @code
 * $ openssl dgst -md5 test_data.dat
 * MD5(test_data.dat)= c7e05d2749805b61e43ddf7a4e73aa3d
 * @endcode
 *
 * @retval 0
 */
static int digest_md5_test(void)
{
    MD5_CTX ctx;
    unsigned char md[MD5_DIGEST_LENGTH];

    cout << "Digest MD5" << endl;
    MD5_Init(&ctx);
    MD5_Update(&ctx, test_data, sizeof(test_data));
    MD5_Final(md, &ctx);
    disp_dump(md, sizeof(md));

    return 0;
}

/**
 * @brief SHA1 のテスト
 *
 * コマンドラインでの SHA1 値を求める方法
 * @code
 * $ openssl dgst -sha1 test_data.dat
 * SHA1(test_data.dat)= 3f115bbb9bc96fed0fe2b5b3f2a50442203d3599
 * @endcode
 *
 * @retval 0
 */
static int digest_sha1_test(void)
{
    SHA_CTX ctx;
    unsigned char sha[SHA_DIGEST_LENGTH];

    cout << "Digest SHA1" << endl;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, test_data, sizeof(test_data));
    SHA1_Final(sha, &ctx);
    disp_dump(sha, sizeof(sha));

    return 0;
}

/**
 * @brief DES CBC モードのテスト
 *
 * コマンドラインでのエンコード * @code
 * $ openssl enc -des-cbc -e -in test_data.dat -out enc.out
 * -p -nosalt -iv fedcba9876543210 -K 0123456789abcdef -nopad
 * key=0123456789ABCDEF
 * iv =FEDCBA9876543210
 * @endcode
 *
 * コマンドラインでのデコード
 * @code
 * $ openssl enc -des-cbc -d -in enc.out -out dec.out
 * -p -nosalt -iv fedcba9876543210 -K 0123456789abcdef -nopad
 * key=0123456789ABCDEF
 * iv =FEDCBA9876543210
 * @endcode
 *
 * @retval 0
 */
static int enc_des_cbc_test(void)
{
    int i;

    unsigned char des_enc[32];
    unsigned char des_dec[32];
    DES_cblock iv3;
    des_key_schedule schedule;

    memset(des_enc, 0, sizeof(des_enc));
    memset(des_dec, 0, sizeof(des_dec));

    /*** 暗号化 ***/
    /* Key schedule 作成 */
    i = DES_set_key_checked(&cbc_key, &schedule);
    if (i != 0) {
        cout << "Key error " << i << endl;
    }

    /* IV 準備 */
    memcpy(&iv3, cbc_iv, sizeof(cbc_iv));

    /* Encode */
    cout << "DES CBC encrypt" << endl;
    des_ncbc_encrypt((const unsigned char*)test_data, des_enc, sizeof(test_data), schedule, &iv3, DES_ENCRYPT);
    if (memcmp(des_enc, cbc_ok, sizeof(cbc_ok)) != 0) {
        cout << "cbc_encrypt encrypt error" << endl;
    }
    disp_dump(des_enc, sizeof(des_enc));

    /*** 復号化 ***/
    /* Key schedule 作成 */
    i = DES_set_key_checked(&cbc_key, &schedule);
    if (i != 0) {
        cout << "Key error " << i << endl;
    }

    /* IV 準備 */
    memcpy(&iv3, cbc_iv, sizeof(cbc_iv));

    /* Decode */
    cout << "DES CBC decrypt" << endl;
    des_ncbc_encrypt((const unsigned char*)des_enc, des_dec, sizeof(test_data), schedule, &iv3, DES_DECRYPT);
    if (memcmp(des_dec, test_data, sizeof(test_data)) != 0) {
        cout << "cbc_encrypt decrypt error" << endl;
    }
    disp_dump(des_dec, sizeof(des_dec));

    return 0;
}

/**
 * @brief 3DES CBC モードのテスト
 *
 * コマンドラインでのエンコード
 * @code
 * $ openssl enc -des-ede3-cbc -e -in test_data.dat -out enc.out -p -nosalt
 * -iv fedcba9876543210 -K 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 -nopad
 * key=0123456789ABCDEFF1E0D3C2B5A49786FEDCBA9876543210
 * iv =FEDCBA9876543210
 * @endcode
 * * コマンドラインでのデコード
 * @code
 * $ openssl enc -des-ede3-cbc -d -in enc.out -out dec.out -p -nosalt
 * -iv fedcba9876543210 -K 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 -nopad
 * key=0123456789ABCDEFF1E0D3C2B5A49786FEDCBA9876543210
 * iv =FEDCBA9876543210
 * @endcode
 *
 * @retval 0
 */
static int enc_3des_cbc_test(void)
{
    int i;
    unsigned char des_enc[32];
    unsigned char des_dec[32];
    DES_cblock iv3;
    des_key_schedule schedule1, schedule2, schedule3;

    memset(des_enc, 0, sizeof(des_enc));
    memset(des_dec, 0, sizeof(des_dec));

    /*** 暗号化 ***/
    /* Key schedule 作成 */
    i = DES_set_key_checked(&cbc_key, &schedule1);
    if (i != 0) {
        cout << "Key error (1) " << i << endl;
    }
    i = DES_set_key_checked(&cbc2_key, &schedule2);
    if (i != 0) {
        cout << "Key error (2) " << i << endl;
    }
    i = DES_set_key_checked(&cbc3_key, &schedule3);
    if (i != 0) {
        cout << "Key error (3) " << i << endl;
    }

    /* IV 準備 */
    memcpy(&iv3, cbc_iv, sizeof(cbc_iv));

    /* Encode */
    cout << "3DES CBC encrypt" << endl;
    des_ede3_cbc_encrypt((const unsigned char*)test_data, des_enc, sizeof(test_data), schedule1, schedule2, schedule3, &iv3, DES_ENCRYPT);
    if (memcmp(des_enc, cbc3_ok, sizeof(cbc3_ok)) != 0) {
        cout << "des_ede3_cbc_encrypt encrypt error" << endl;
    }
    disp_dump(des_enc, sizeof(des_enc));

    /*** 復号化 ***/
    /* Key schedule 作成 */
    i = DES_set_key_checked(&cbc_key, &schedule1);
    if (i != 0) {
        cout << "Key error (1) " << i << endl;
    }
    i = DES_set_key_checked(&cbc2_key, &schedule2);
    if (i != 0) {
        cout << "Key error (2) " << i << endl;
    }
    i = DES_set_key_checked(&cbc3_key, &schedule3);
    if (i != 0) {
        cout << "Key error (3) " << i << endl;
    }

    /* IV 準備 */
    memcpy(&iv3, cbc_iv, sizeof(cbc_iv));

    /* Decode */
    cout << "3DES CBC decrypt" << endl;
    des_ede3_cbc_encrypt((const unsigned char*)des_enc, des_dec, sizeof(des_enc), schedule1, schedule2, schedule3, &iv3, DES_DECRYPT);
    if (memcmp(des_dec, test_data, sizeof(test_data)) != 0) {
        cout << "des_ede3_cbc_encrypt encrypt error" << endl;
    }
    disp_dump(des_dec, sizeof(des_dec));

    return 0;
}

/**
 * @brief AES 128bit CBC モードのテスト
 *
 * コマンドラインでのエンコード
 * @code
 * $ openssl enc -aes-128-cbc -e -in test_data.dat -out enc.out -p -nosalt
 * -iv 23456789abcdef019876543210fedcba -K 0123456789abcdeffedcba9876543210 -nopad
 * key=0123456789ABCDEFFEDCBA9876543210
 * iv =23456789ABCDEF019876543210FEDCBA
 * @endcode
 * * コマンドラインでのデコード
 * @code
 * $ openssl enc -aes-128-cbc -d -in enc.out -out dec.out -p -nosalt
 * -iv 23456789abcdef019876543210fedcba -K 0123456789abcdeffedcba9876543210 -nopad
 * key=0123456789ABCDEFFEDCBA9876543210
 * iv =23456789ABCDEF019876543210FEDCBA
 * @endcode
 *
 * @retval 0
 */
static int enc_aes128_cbc_test(void)
{
    int i;
    unsigned char aes_enc[32];
    unsigned char aes_dec[32];
    AES_KEY key;
    unsigned char iv[AES_BLOCK_SIZE];

    memset(aes_enc, 0, sizeof(aes_enc));
    memset(aes_dec, 0, sizeof(aes_dec));

    /*** 暗号化 ***/
    /* AES Key 作成 */
    i = AES_set_encrypt_key(aes_cbc_key, 128, &key);

    /* IV 準備 */
    memcpy(iv, aes_cbc_iv, sizeof(aes_cbc_iv));

    /* Encode */
    cout << "AES 128 CBC encrypt" << endl;
    AES_cbc_encrypt((const unsigned char*)test_data, aes_enc, sizeof(test_data), &key, iv, AES_ENCRYPT);
    if (memcmp(aes_enc, aes128_cbc_ok, sizeof(aes128_cbc_ok)) != 0) {
        cout << "AES_cbc_encrypt encrypt error" << endl;
    }
    disp_dump(aes_enc, sizeof(aes_enc));

    /*** 復号化 ***/
    /* AES Key 作成 */
    i = AES_set_decrypt_key(aes_cbc_key, 128, &key);

    /* IV 準備 */
    memcpy(iv, aes_cbc_iv, sizeof(aes_cbc_iv));

    /* Decode */
    cout << "AES 128 CBC decrypt" << endl;
    AES_cbc_encrypt((const unsigned char*)aes_enc, aes_dec, sizeof(aes_enc), &key, iv, AES_DECRYPT);
    if (memcmp(aes_dec, test_data, sizeof(test_data)) != 0) {
        cout << "AES_cbc_encrypt decrypt error" << endl;
    }
    disp_dump(aes_dec, sizeof(aes_dec));

    return 0;
}

int main(void)
{
    digest_md5_test();
    digest_sha1_test();
    enc_des_cbc_test();
    enc_3des_cbc_test();
    enc_aes128_cbc_test();

    return 0;
}

コンパイル
$ g++ openssl_test.cpp -o openssl_test.out -lssl -Wall

実行結果
$ ./openssl_test.out
Digest MD5
c7 e0 5d 27 49 80 5b 61 e4 3d df 7a 4e 73 aa 3d
Digest SHA1
3f 11 5b bb 9b c9 6f ed 0f e2 b5 b3 f2 a5 04 42
20 3d 35 99
DES CBC encrypt
cc d1 73 ff ab 20 39 f4 ac d8 ae fd df d8 a1 eb
46 8e 91 15 78 88 ba 68 1d 26 93 97 f7 fe 62 b4
DES CBC decrypt
37 36 35 34 33 32 31 20 4e 6f 77 20 69 73 20 74
68 65 20 74 69 6d 65 20 66 6f 72 20 00 00 00 00
3DES CBC encrypt
3f e3 01 c9 62 ac 01 d0 22 13 76 3c 1c bd 4c dc
79 96 57 c0 64 ec f5 d4 1c 67 38 12 cf de 96 75
3DES CBC decrypt
37 36 35 34 33 32 31 20 4e 6f 77 20 69 73 20 74
68 65 20 74 69 6d 65 20 66 6f 72 20 00 00 00 00
AES 128 CBC encrypt
ea ca d1 95 f1 00 f8 77 5d 8b b8 2a 5e b7 04 f6
0f 8f 2c 09 af f6 76 06 bd 1e 19 ac 57 68 fc 2d
AES 128 CBC decrypt
37 36 35 34 33 32 31 20 4e 6f 77 20 69 73 20 74
68 65 20 74 69 6d 65 20 66 6f 72 20 00 00 00 00

openssl コマンドを使った場合の結 果
上記プログラム中の test_data[] と同じ内容のバイナリデータ (test_data.dat) を準備して openssl コマンドで結果を確認
  • hash
    $ openssl dgst -md5 test_data.dat
    MD5(test_data.dat)= c7e05d2749805b61e43ddf7a4e73aa3d
    $ openssl dgst -sha1 test_data.dat
    SHA1(test_data.dat)= 3f115bbb9bc96fed0fe2b5b3f2a50442203d3599
      
  • DES CBC による暗号化
    $ openssl enc -des-cbc -e -in test_data.dat -out enc.out -p -nosalt -iv fedcba9876543210 -K 0123456789abcdef -nopad
    key=0123456789ABCDEF
    iv =FEDCBA9876543210
      
  • DES CBC による復号化
    $ openssl enc -des-cbc -d -in enc.out -out dec.out -p -nosalt -iv fedcba9876543210 -K 0123456789abcdef -nopad
    key=0123456789ABCDEF
    iv =FEDCBA9876543210
      
  • 3DES CBC による暗号化
    $ openssl enc -des-ede3-cbc -e -in test_data.dat -out enc.out -p -nosalt -iv fedcba9876543210 -K 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 -nopad
    key=0123456789ABCDEFF1E0D3C2B5A49786FEDCBA9876543210
    iv =FEDCBA9876543210
      
  • 3DES CBC による複合化
    $ openssl enc -des-ede3-cbc -d -in enc.out -out dec.out -p -nosalt -iv fedcba9876543210 -K 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 -nopad
    key=0123456789ABCDEFF1E0D3C2B5A49786FEDCBA9876543210
    iv =FEDCBA9876543210
      
  • AES 128bit CBC による暗号化
    $ openssl enc -aes-128-cbc -e -in test_data.dat -out enc.out -p -nosalt -iv 23456789abcdef019876543210fedcba -K 0123456789abcdeffedcba9876543210 -nopad
    key=0123456789ABCDEFFEDCBA9876543210
    iv =23456789ABCDEF019876543210FEDCBA
      
  • AES 128bit CBC による復号化
    $ openssl enc -aes-128-cbc -d -in enc.out -out dec.out -p -nosalt -iv 23456789abcdef019876543210fedcba -K 0123456789abcdeffedcba9876543210 -nopad
    key=0123456789ABCDEFFEDCBA9876543210
    iv =23456789ABCDEF019876543210FEDCBA
      

0 件のコメント:

コメントを投稿