2016-07-13 5 views
1

を生成した後、私はOpenSSLを使用して32バイトのbase64文字列を生成しようとしていたが、それは常に32バイトの文字列を生成していないと、時々、出力が正しく非印字可能な文字のランダムなnバイトBase64文字列

#include <openssl/rand.h> 
#include <openssl/bio.h> 
#include <openssl/evp.h> 
#include <openssl/buffer.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int Base64Encode(const unsigned char* buffer, unsigned char** b64text) { //Encodes a binary safe base 64 string 
    BIO *bio, *b64; 
    BUF_MEM *bufferPtr; 

    b64 = BIO_new(BIO_f_base64()); 
    bio = BIO_new(BIO_s_mem()); 
    bio = BIO_push(b64, bio); 

    BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); //Ignore newlines - write everything in one line 
    BIO_write(bio, buffer, strlen(buffer)); 
    BIO_flush(bio); 
    BIO_get_mem_ptr(bio, &bufferPtr); 
    BIO_set_close(bio, BIO_NOCLOSE); 
    BIO_free_all(bio); 

    *b64text=bufferPtr->data; 

    return (0); //success 
} 

int main() { 
    unsigned char buffer[35], *base64EncodeOutput; 
    int ret = RAND_bytes(buffer, 32); 
    buffer[32]='\0'; // Null terminate 

    (void)Base64Encode(buffer, &base64EncodeOutput); 
    (void)printf("Return value of the operation was: %d\n%s\n", ret, base64EncodeOutput); 

    return EXIT_SUCCESS; 
} 
を表示文字化けしていません時には出力は、長さも、32バイトではありません

I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`�

そして:

コンパイルとgcc rand_str.c -lcrypto && ./a.out | tail -1で実行されているが、時々のようなものを生成します。 openssl rand -base64 32


は、私は違った何をする必要があります:

私の目標は、このコマンドが何を複製するのですか? STRLENは、時々所望の値(32)未満を返すよう

答えて

1

上記のソリューションのおかげで、私はこの問題を解決できました。ここでの結果は次のとおりです。

#include <openssl/rand.h> 
#include <openssl/bio.h> 
#include <openssl/evp.h> 
#include <openssl/buffer.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

static char* base64_bytes(int size) { 
    char *buff = malloc(size + 1), *bytes = NULL; 
    int chunk; 
    BIO *b64, *out; 
    BUF_MEM *bptr; 

    // Create a base64 filter/sink 
    if ((b64 = BIO_new(BIO_f_base64())) == NULL) { 
     return NULL; 
    } 

    // Create a memory source 
    if ((out = BIO_new(BIO_s_mem())) == NULL) { 
     return NULL; 
    } 

    // Chain them 
    out = BIO_push(b64, out); 
    BIO_set_flags(out, BIO_FLAGS_BASE64_NO_NL); 

    // Generate random bytes 
    if (!RAND_bytes(buff, size)) { 
     return NULL; 
    } 

    // Write the bytes 
    BIO_write(out, buff, size); 
    BIO_flush(out); 

    // Now remove the base64 filter 
    out = BIO_pop(b64); 

    // Write the null terminating character 
    BIO_write(out, "\0", 1); 
    BIO_get_mem_ptr(out, &bptr); 

    // Allocate memory for the output and copy it to the new location 
    bytes = malloc(bptr->length); 
    strncpy(bytes, bptr->data, bptr->length); 

    // Cleanup 
    BIO_set_close(out, BIO_CLOSE); 
    BIO_free_all(out); 
    free(buff); 

    return bytes; 
} 

int main() { 
    char *b64 = base64_bytes(32); 
    puts(b64); 

    free(b64); 

    return EXIT_SUCCESS; 
} 

私のオリジナルの試みとの主な問題は、NULLターミネータがbase64フィルタを通過したとき、それは文字列の終わりとして認識されていないということでしたが、むしろそれはありますbase64に変換され、文字列は元の投稿と同じように見えます。

元の文字列を書き込んだ後にBIOからbase64フィルタを削除することをお勧めします。この場合、BIOはoutとなります。 out BIOは単純にシンクなので、ほとんど何も書き込むことができず、入力を変更しません。これにより、NULLターミネータを基になるバッファに書き込んで、後で完全な文字列を取得する機会が与えられます。

2

BIO_write(bio, buffer, strlen(buffer));

NULは、有効なランダムバイトです。

` はNULターミネーターを持たないbase64バッファーのため、ランダムなゴミを読み込んでいます。私はNULを追加するためにOpenSSLを強制的にどのような方法を知りませんが、あなたはどこに停止するのprintfを伝えることができます:

(void)printf("Return value of the operation was: %d\n%.44s\n", ret, base64EncodeOutput);

+0

お返事ありがとうございます。 '%44s'と'%.44s'の違いは何ですか? – smac89

+1

%44sは最低44文字、%.44sは最大44文字を出力します。文字列が最小文字列よりも短い場合、文字列は空白で埋められます。最大値よりも長い場合、切り捨てられます。 – Alcaro

+0

ちょうど新しいことを学びました。ありがとう – smac89

2

をコンパイルし、& & -lcrypto GCC rand_str.cで実行している./ a.out |

I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`� 

BIO'sない農産物C-文字列を実行します。尾-1は、時々のようなものを生成します。それらはNULLで終了しません。

さらにBIO_writeを実行し、Base64 BIOをチェーンから削除した後にNULL文字を書き込みます。

関連する問題