2010年3月14日日曜日

pythonとCでbase64

pythonのbase64モジュールを使った場合

import base64
print base64.b64encode('data to be encoded')        # → 'ZGF0YSB0byBiZSBlbmNvZGVk'
print base64.b64decode('ZGF0YSB0byBiZSBlbmNvZGVk')  # → 'data to be encoded'



C言語のOpenSSLライブラリを使った場合

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

#include <openssl/ssl.h>


//結果dst_dataは改行文字(0x0a = \n)付きでNUL終端なし
//改行文字(0x0a = \n)までの長さを返す
//0以下を返すとエラー
int base64encode( char *dst_data, int dst_data_buf_size, void *src_data, int src_len )
{
    int r;
    BIO *mem, *b64, *chain;
    BUF_MEM *bptr;
    
    if( dst_data==NULL || dst_data_buf_size<=0 || src_data==NULL || src_len<=0 )
        return -1;
    
    b64 = BIO_new(BIO_f_base64());
    if( b64==NULL )
        return -2;
    
    mem = BIO_new(BIO_s_mem());
    if( mem==NULL )
    {
        BIO_vfree(b64);
        return -3;
    }
    
    chain = BIO_push(b64, mem);
    
    r = BIO_write(chain, src_data, src_len);
    if( r<=0 )
    {
        BIO_free_all(chain);
        return -4;
    }
    
    r = BIO_flush(chain);
    if( r<=0 )
    {
        BIO_free_all(chain);
        return -5;
    }
    
    BIO_get_mem_ptr(chain, &bptr);
    if( dst_data_buf_size < bptr->length )
    {
        BIO_free_all(chain);
        return -6;
    }
    
    memcpy( dst_data, bptr->data, bptr->length );
    r = bptr->length;
    
    BIO_free_all(chain);
    
    return r;
}

//src_dataにはNUL終端は必要ないが、改行(0x0a = \n)は必須
//結果dst_dataのデータ長を返す
//0以下を返すとエラー
//制限事項として、変換結果とdst_data_buf_sizeが同じ長さの場合エラーを返す。
//必ず、変換結果より大きなサイズのバッファを用意しなければならない。
int base64decode( void *dst_data, int dst_data_buf_size, char *src_data, int src_len )
{
    int r;
    BIO *mem, *b64, *chain;
    
    if( dst_data==NULL || dst_data_buf_size<=0 || src_data==NULL || src_len<=0 )
        return -1;
    
    b64 = BIO_new(BIO_f_base64());
    if( b64==NULL )
        return -2;
    
    mem = BIO_new_mem_buf(src_data, src_len);
    if( mem==NULL )
    {
        BIO_vfree(b64);
        return -3;
    }
    
    chain = BIO_push(b64, mem);
    
    r = BIO_read(chain, dst_data, dst_data_buf_size);
    if( r<0 )
    {
        BIO_free_all(chain);
        return -4;
    }
    if( r>=dst_data_buf_size )
    {
        BIO_free_all(chain);
        return -5;
    }
    
    BIO_free_all(chain);
    
    return r;
}

int main(int argc,char **argv)
{
    int r;
    char *data = "data to be encoded";
    char a[256];
    char b[256];
    
    r = base64encode( a, sizeof(a), data, strlen(data) );
    if( r<=0 )
    {
        printf("err=%d\n",r);
        exit(1);
    }
    a[r-1] = '\0';
    printf("%s\n",a);
    
    strcat(a,"\n");
    r = base64decode( b, sizeof(b), a, strlen(a) );
    if( r<=0 )
    {
        printf("err=%d\n",r);
        exit(1);
    }
    b[r] = '\0';
    printf("%s\n",b);
    
    return 0;
}

0 件のコメント: