生成随机 n 字节 Base64 字符串后的不可打印字符 [英] Non-printable character after generating random n-byte Base64 string

查看:20
本文介绍了生成随机 n 字节 Base64 字符串后的不可打印字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用 openssl 生成 32 字节的 base64 字符串,但它并不总是生成 32 字节的字符串,有时输出会出现乱码且无法正确显示

I was trying to generate a 32byte base64 string using openssl, but it does not always produce 32 byte string and sometimes the output is garbled and not displayed correctly

#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]=''; // Null terminate

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

    return EXIT_SUCCESS;
}

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

Compiling and running with gcc rand_str.c -lcrypto && ./a.out | tail -1, sometimes produces something like:

I6YaDVSRPw5Ux+2paY4u4ToMKtZXQoBj`

有时输出的长度甚至不到 32 个字节.

And sometimes the output is not even 32 bytes in length.

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

My goal is to replicate what this command does: openssl rand -base64 32

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

What do I need to do differently?

推荐答案

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

Thanks to the solutions posted above, I was able to fix this problem. Here is the result:

#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, "", 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,这使得字符串看起来和我原来的帖子一样.


The main issue with my original attempt was that when the null terminator is passed through the base64 filter, it is not recognized as the end of the string, but rather it is converted to base64 which makes the string look the way it did in my original post.

因此,建议的解决方案是在写入原始字符串后从 BIO 中删除 base64 过滤器,然后只留下 out BIO.由于 out BIO 只是一个接收器,我们几乎可以向它写入任何内容,并且它不会修改它的输入.因此,这提供了将空终止符写入底层缓冲区并稍后检索完整字符串的机会.

So the suggested solution is to remove the base64 filter from the BIO after writing the original string, this then leaves just the out BIO. Since the out BIO is simply a sink, we can write pretty much anything to it and it does not modify it's input. So this gives the opportunity to write a null terminator into the underlying buffer and retrieve the complete string later.

这篇关于生成随机 n 字节 Base64 字符串后的不可打印字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆