【问题标题】:Making conversion similar to BN_hex2bn + BN_bn2bin without openSSL in C在 C 中不使用 openSSL 进行类似于 BN_hex2bn + BN_bn2bin 的转换
【发布时间】:2019-05-15 04:41:44
【问题描述】:

我目前使用 openSSL 将值从加密字符串转换为我认为的二进制数组。然后我解密这个“数组”(传递给 EVP_DecryptUpdate)。我是这样进行转换的:

    BIGNUM *bnEncr = BN_new();
    if (0 == BN_hex2bn(&bnEncr, encrypted)) { // from hex to big number
        printf("ERROR\n");
    }
    unsigned int numOfBytesEncr = BN_num_bytes(bnEncr);
    unsigned char encrBin[numOfBytesEncr];
    if (0 == BN_bn2bin(bnEncr, encrBin)) { // from big number to binary
        printf("ERROR\n");
    }

然后我将 encrBin 传递给 EVP_DecryptUpdate 和解密工作。

我在我的代码中的很多地方都这样做了,现在想编写我自己的将十六进制转换为二进制数组的 C 函数,然后我可以将其传递给 EVP_DecryptUpdate。我尝试了这一点,并将我的加密十六进制字符串转换为 0 和 1 的数组,但事实证明 EVP_DecryptUpdate 无法使用它。从我在网上可以找到的内容来看,BN_bn2bin“创建了一个真正的二进制表示(即位序列)。更具体地说,它创建了一个数字的大端表示。”所以这不仅仅是一个 0 和 1 的数组,对吧?

有人可以解释我如何在 C 中自己进行十六进制->(真正的)二进制转换,这样我就能得到 EVP_DecryptUpdate 期望的格式吗?这很复杂吗?

【问题讨论】:

  • 你基本上是在问这个 SO 问题的答案:How to turn a hex string into an unsigned char array?(除了空格)。
  • @ReinierTorenbeek 我不这么认为 - 我需要将十六进制字符串转换为大端表示的位序列。那会和 unsigned char 数组一样吗?...

标签: c encryption openssl


【解决方案1】:

BN_bn2bin “创建一个真正的二进制表示(即 位序列)。更具体地说,它创建了一个大端 数字的表示。”所以这不仅仅是一个 0 和 1s,对吧?

这里提到的位序列表示为一个字节数组。对于每个包含 8 位的字节,这可以解释为“0 和 1 的数组”。它不是一个“值为 0 或 1 的整数数组”,如果这就是您所要求的。

由于您不清楚BN_bn2bin() 的工作原理,因此只需分析代码sn-p 的最终结果会有所帮助。你可以这样做(省略任何错误检查):

#include <stdio.h>
#include <openssl/bn.h>

int main(
    int argc,
    char **argv)
{
    const char *hexString = argv[1];

    BIGNUM *bnEncr = BN_new();
    BN_hex2bn(&bnEncr, hexString);
    unsigned int numOfBytesEncr = BN_num_bytes(bnEncr);
    unsigned char encrBin[numOfBytesEncr];
    BN_bn2bin(bnEncr, encrBin);
    fwrite(encrBin, 1, numOfBytesEncr, stdout);
}

这会将encrBin 的内容输出到标准输出,这绝不是一件好事,但是您可以通过hexdump 之类的工具将其通过管道传输,或者将其重定向到文件以使用十六进制进行分析编辑。它看起来像这样:

$ ./bntest 74162ac74759e85654e0e7762c2cdd26 | hexdump -C
00000000  74 16 2a c7 47 59 e8 56  54 e0 e7 76 2c 2c dd 26 |t.*.GY.VT..v,,.&|
00000010

或者,如果您确实想查看那些 0 和 1:

$ ./bntest  74162ac74759e85654e0e7762c2cdd26 | xxd -b -c 4
00000000: 01110100 00010110 00101010 11000111  t.*.
00000004: 01000111 01011001 11101000 01010110  GY.V
00000008: 01010100 11100000 11100111 01110110  T..v
0000000c: 00101100 00101100 11011101 00100110  ,,.&

这表明你的问题

谁能解释我如何进行十六进制->(真正的)二进制转换 我自己在 C 中,所以我会得到 EVP_DecryptUpdate 期望的格式? 这很复杂吗?

本质上和SO问题How to turn a hex string into an unsigned char array?一样,就像我commented一样。

【讨论】:

    【解决方案2】:

    不清楚你为什么想要这个,而且绝对不建议你自己实现转换函数(它们可能会停止使用任何数量的 OpenSSL 内部更改)但是如果你对它感兴趣的话@987654321 @:

    static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
    {
        int n;
        size_t i, lasti, j, atop, mask;
        BN_ULONG l;
    
        /*
         * In case |a| is fixed-top, BN_num_bytes can return bogus length,
         * but it's assumed that fixed-top inputs ought to be "nominated"
         * even for padded output, so it works out...
         */
        n = BN_num_bytes(a);
        if (tolen == -1) {
            tolen = n;
        } else if (tolen < n) {     /* uncommon/unlike case */
            BIGNUM temp = *a;
    
            bn_correct_top(&temp);
            n = BN_num_bytes(&temp);
            if (tolen < n)
                return -1;
        }
    
        /* Swipe through whole available data and don't give away padded zero. */
        atop = a->dmax * BN_BYTES;
        if (atop == 0) {
            OPENSSL_cleanse(to, tolen);
            return tolen;
        }
    
        lasti = atop - 1;
        atop = a->top * BN_BYTES;
        for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) {
            l = a->d[i / BN_BYTES];
            mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
            *--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
            i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
        }
    
        return tolen;
    }
    

    【讨论】:

    • 对...这看起来很复杂...关于 OpenSSL 的内部更改 - 您是指解密功能的更改?
    猜你喜欢
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2012-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多