base 64復号
今日、あるプロジェクトで160バイトのbase 64符号化された列が得られました.
この列を復号するために、関連base 64の復号方法をネット上で検索し、まとめると以下の2つの方法がある.
そこで私はこのbase 64コードを上のいずれかの関数に転送し、結果は復号に失敗しました.
解析の結果,この2つの復号化方法は本質的に同じであることが分かった.すなわち,方法1(base 64_decode関数)が最終的に呼び出された方法2(unbase 64関数)のEVP_である.xxxシリーズ関数なので、エラーの原因はこれらのEVP_にまとめられています.xxx関数について、EVPを分析した.DecodeUpdateソースコードを発見し、EVP_DecodeUpdate実装には、次のコードの行があります.
/* If the current line is > 80 characters, scream alot */if (ln >= 80) { rv= -1; goto end; }
ここでln>=80は、現在解析されている行の80バイトを超えるとエラーとなる、すなわちEVP_DecodeUpdateはbase 64列を解析する際に現在の行のバイト数を規定している:80バイトを超えてはならない.
したがって、上記の160バイトのbase 64符号化を以下のように変更することができます.
このような方法で上の2つの関数のいずれかに伝えればよい.もちろん、rを追加した後、上の2つの関数に伝わられたとき、このbase 64の長さも160+2*2=164であるべきだ.私たちは2つのリターン改行符を追加したからだ.
char *input = "MHYCAQACIAt4ZA2cTIdqd5ik+3u1UzGfFCPgNdgKg/IxZanXTl9aAiBRI77clgTw3sDLNXrnwWp/XVF42hNFsjdoE4z018b8gAQKQywcKi/CmqDmXAIhAIS2OqlyZ46VEF/Py5zCG35MZsKcS0l1jwoA/heqWt0R";
この列を復号するために、関連base 64の復号方法をネット上で検索し、まとめると以下の2つの方法がある.
static int base64_decode(char *in, int inl, char *out, int *outl)
{
int len=0;
BIO *b64,*bmem;
void *ch = NULL;
b64=BIO_new(BIO_f_base64());
bmem=BIO_new_mem_buf(in, inl);
b64 = BIO_push(b64,bmem);
*outl = 0;
while ((len = BIO_read(b64, out, 1024)) > 0) {
*outl += len;
}
out[*outl]=0;
BIO_free_all(bmem);
return 0;
}
static unsigned char* unbase64(char *in, int inl, int* outl)
{
EVP_ENCODE_CTX ctx;
int orgLen = (((inl+2)/4)*3) + 1;
unsigned char* orgBuf = new unsigned char[orgLen];
int result, tmpLen, ret;
EVP_DecodeInit(&ctx);
ret = EVP_DecodeUpdate(&ctx, (unsigned char *)orgBuf, &result, (unsigned char *)in, inl);
if (ret !=1) {
return NULL;
}
EVP_DecodeFinal(&ctx, (unsigned char *)&orgBuf[result], &tmpLen);
result += tmpLen;
*outl = result;
return orgBuf;
}
そこで私はこのbase 64コードを上のいずれかの関数に転送し、結果は復号に失敗しました.
解析の結果,この2つの復号化方法は本質的に同じであることが分かった.すなわち,方法1(base 64_decode関数)が最終的に呼び出された方法2(unbase 64関数)のEVP_である.xxxシリーズ関数なので、エラーの原因はこれらのEVP_にまとめられています.xxx関数について、EVPを分析した.DecodeUpdateソースコードを発見し、EVP_DecodeUpdate実装には、次のコードの行があります.
/* If the current line is > 80 characters, scream alot */if (ln >= 80) { rv= -1; goto end; }
ここでln>=80は、現在解析されている行の80バイトを超えるとエラーとなる、すなわちEVP_DecodeUpdateはbase 64列を解析する際に現在の行のバイト数を規定している:80バイトを超えてはならない.
したがって、上記の160バイトのbase 64符号化を以下のように変更することができます.
char *input = "MHYCAQACIAt4ZA2cTIdqd5ik+3u1UzGfFCPgNdgKg/IxZanXTl9aAiBRI77clgTw3sDLNXrnwWp\r
/XVF42hNFsjdoE4z018b8gAQKQywcKi/CmqDmXAIhAIS2OqlyZ46VEF/Py5zCG35MZsKcS0l1jw\r
oA/heqWt0R";
75 \r
64
//char *input = "MHYCAQACIAt4ZA2cTIdqd5ik+3u1UzGfFCPgNdgKg/IxZanXTl9aAiBRI77clgTw\r
3sDLNXrnwWp/XVF42hNFsjdoE4z018b8gAQKQywcKi/CmqDmXAIhAIS2OqlyZ46V\r
EF/Py5zCG35MZsKcS0l1jwoA/heqWt0R";
このような方法で上の2つの関数のいずれかに伝えればよい.もちろん、rを追加した後、上の2つの関数に伝わられたとき、このbase 64の長さも160+2*2=164であるべきだ.私たちは2つのリターン改行符を追加したからだ.