生成随机 n 字节 Base64 字符串后的不可打印字符
Non-printable character after generating random n-byte Base64 string
我试图使用 openssl 生成一个 32 字节的 base64 字符串,但它并不总是生成 32 字节的字符串,有时输出是乱码且显示不正确
#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]='[=10=]'; // 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
,有时会产生如下内容:
I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`�
有时输出的长度甚至不到 32 个字节。
我的目标是复制此命令的作用:
openssl rand -base64 32
我需要做哪些不同的事情?
BIO_write(bio, buffer, strlen(buffer));
NUL 是一个有效的随机字节,因此 strlen 有时会 return 小于所需值 (32)。
`` 是由于 base64 缓冲区没有 NUL 终止符,因此它正在读取一些随机垃圾。我不知道有什么方法可以强制 OpenSSL 添加 NUL,但是你可以告诉 printf 在哪里停止:
(void)printf("Return value of the operation was: %d\n%.44s\n", ret, base64EncodeOutput);
Compiling and running with gcc rand_str.c -lcrypto && ./a.out | tail -1, sometimes produces something like:
I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`�
BIO's
不会生成 C 字符串。它们不是 NULL 终止的。
再执行一次BIO_write
并在从链中删除Base64
BIO后写入NULL字符。
感谢上面 posted 的解决方案,我能够解决这个问题。这是结果:
#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, "[=10=]", 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;
}
我最初尝试的主要问题是,当空终止符通过 base64
过滤器时,它不会被识别为字符串的结尾,而是被转换为 base64,这使得字符串看起来像我原来的方式 post.
所以建议的解决方案是在写入原始字符串后从 BIO
中删除 base64 过滤器,然后只留下 out
BIO。由于 out
BIO 只是一个接收器,我们可以向它写入几乎任何东西,它不会修改它的输入。因此,这提供了将空终止符写入底层缓冲区并稍后检索完整字符串的机会。
我试图使用 openssl 生成一个 32 字节的 base64 字符串,但它并不总是生成 32 字节的字符串,有时输出是乱码且显示不正确
#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]='[=10=]'; // 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
,有时会产生如下内容:
I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`�
有时输出的长度甚至不到 32 个字节。
我的目标是复制此命令的作用:
openssl rand -base64 32
我需要做哪些不同的事情?
BIO_write(bio, buffer, strlen(buffer));
NUL 是一个有效的随机字节,因此 strlen 有时会 return 小于所需值 (32)。
`` 是由于 base64 缓冲区没有 NUL 终止符,因此它正在读取一些随机垃圾。我不知道有什么方法可以强制 OpenSSL 添加 NUL,但是你可以告诉 printf 在哪里停止:
(void)printf("Return value of the operation was: %d\n%.44s\n", ret, base64EncodeOutput);
Compiling and running with gcc rand_str.c -lcrypto && ./a.out | tail -1, sometimes produces something like:
I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`�
BIO's
不会生成 C 字符串。它们不是 NULL 终止的。
再执行一次BIO_write
并在从链中删除Base64
BIO后写入NULL字符。
感谢上面 posted 的解决方案,我能够解决这个问题。这是结果:
#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, "[=10=]", 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;
}
我最初尝试的主要问题是,当空终止符通过 base64
过滤器时,它不会被识别为字符串的结尾,而是被转换为 base64,这使得字符串看起来像我原来的方式 post.
所以建议的解决方案是在写入原始字符串后从 BIO
中删除 base64 过滤器,然后只留下 out
BIO。由于 out
BIO 只是一个接收器,我们可以向它写入几乎任何东西,它不会修改它的输入。因此,这提供了将空终止符写入底层缓冲区并稍后检索完整字符串的机会。