生成随机n字节Base64字符串后的不可打印字符

我试图使用openssl生成一个32byte base64字符串,但它并不总是产生32字节字符串,有时输出是乱码并且没有正确显示

#include  #include  #include  #include  #include  #include  #include  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; } 

使用gcc rand_str.c -lcrypto && ./a.out | tail -1编译和运行 gcc rand_str.c -lcrypto && ./a.out | tail -1 ,有时产生类似的东西:

I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`

有时输出甚至不是32个字节。

我的目标是复制这个命令的作用: openssl rand -base64 32


我需要做些什么不同的事情?

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

NUL是一个有效的随机字节,因此strlen有时会返回小于所需的值(32)。

` 是由于base64缓冲区没有NUL终结符,所以它正在读出一些随机垃圾。 我不知道有什么方法可以强制OpenSSL添加NUL,但是你可以告诉printf在哪里停止:

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

使用gcc rand_str.c -lcrypto && ./a.out |进行编译和运行 tail -1,有时产生类似的东西:

 I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`   

BIO's 生产C字符串。 它们不是NULL终止的。

从链中删除Base64 BIO后再执行一次BIO_write并写入NULL字符。

感谢上面发布的解决方案,我能够解决这个问题。 结果如下:

 #include  #include  #include  #include  #include  #include  #include  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终结符通过base64filter时,它不会被识别为字符串的结尾,而是被转换为base64,这使得字符串看起来就像它在我原来的那样。post。

所以建议的解决方案是在写完原始字符串后从BIO删除base64filter,然后只留下out BIO。 由于out BIO只是一个接收器,我们可以写任何东西,它不会修改它的输入。 因此,这使得有机会将空终止符写入底层缓冲区并稍后检索完整的字符串。