我正在尝试在OpenSSL中使用BN_ *函数。具体来说,我有以下代码:
#import <openssl/bn.h>
BIGNUM * num = BN_new();
BN_set_word(num, 42);
char * buffer = malloc((BN_num_bytes(num)+1) * sizeof(char));
buffer[BN_num_bytes(num)] = '\0';
int len = BN_bn2bin(num, buffer);
printf("42 in binary is %s\n", buffer);
然而,当我这样做时,我没有得到一串零和一个零。而是打印"42 in binary is *"
。据我所知,从网上可用的非常有限数量的例子我已经比较了这个例子,我已经正确地实现了这个。
为什么它不起作用的任何想法?
答案 0 :(得分:6)
BN_bn2bin
不会创建可打印的字符串 - 相反,它会创建一个真正的二进制表示(即一个位序列)。更具体地说,它创建了数字的大端表示。由于42适合一个字节,因此您得到一个字节0x2a,即ASCII中的“*”。
如果你想要0/1表示,你需要遍历所有字节,并自己进行打印(例如使用移位或查找表)。
答案 1 :(得分:0)
以下是一些实际将BN_bn2bin
输出转换为可打印字符串的代码,就像BN_bn2dec
和BN_bn2hex
的输出一样。它位于NodeJS库中,但是用C ++编写以提高速度。花了我一整天,可能不是最佳的(因为我从大学的第一年开始就没有编写任何C ++代码)。但它通过了一系列单元测试,所以我知道它有效!
https://github.com/malcolmocean/node-bignum
if (BN_is_zero(&bignum->bignum_)) {
to = (char*) OPENSSL_malloc(2*sizeof(char));
to[0] = '0';
to[1] = '\0';
} else {
unsigned char *binary = (unsigned char*) OPENSSL_malloc(BN_num_bytes(&bignum->bignum_)*sizeof(unsigned char));
int len = BN_bn2bin(&bignum->bignum_, binary);
to = (char*) OPENSSL_malloc((len*8+2)*sizeof(char));
int offset = 0;
if (BN_is_negative(&bignum->bignum_)) {
to[0] = '-';
offset--;
}
unsigned char x = binary[0];
while (!(x & 128) && x) {
x = x << 1;
offset++;
}
for (int i = 0; i < len; i++) {
unsigned char bits = binary[i];
int j=7;
while(bits) {
if (bits & 1) {
to[8*i+j-offset] = '1';
} else {
to[8*i+j-offset] = '0';
}
bits = bits >> 1;
j--;
}
if (i > 0) {
while (j >= 0) {
to[8*i+j-offset] = '0';
j--;
}
}
}
to[8*len-offset] = '\0';
OPENSSL_free(binary);
}