gpt4 book ai didi

c - d2i_RSA_PUBKEY 总是返回 NULL

转载 作者:太空宇宙 更新时间:2023-11-04 02:21:52 26 4
gpt4 key购买 nike

我必须处理一些与 AIX 相关的 Openssl 错误,并尝试编写一些测试代码。简而言之,我想读取缓冲区中的 RSA key 文件,而不是从缓冲区中获取数据以进行一些检查。当我运行测试程序时,我总是得到“错误:RSA 为 NULL”,这意味着缓冲区为空。

我用这个命令行创建了测试键:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -outform DER -out testprivate_key.pem
openssl rsa -in testprivate_key.pem -inform DER -outform DER -pubout -out testpublic_key.pem

我必须承认我对 Openssl 编程一无所知,因此非常欢迎任何提示。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <openssl/pem.h>
#include <openssl/err.h> /* ERR_* */
#include <openssl/rand.h> /* RAND_* */
#include <openssl/bn.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>


unsigned char buf[1024*10];

/* const char keyfiles[][32] = { "testpublic_key32.pem", "testpublic_key64.pem" }; */

int get_buffer () {
RSA *pub_key = NULL;
/* FILE *key_file; */
/* key_file = fopen( keyfiles[0],"rt"); */
FILE *key_file = fopen("testpublic_key.pem","r"); // read in key file
if (!key_file)
{
printf("Failed to open key file\n");
exit(1);
}
pub_key = PEM_read_RSA_PUBKEY(key_file,&pub_key,NULL,NULL); // fill buffer
BIO *mem = BIO_new(BIO_s_mem());
RSA_print(mem,pub_key,0);
BIO_read(mem,buf,1024*10);

BUF_MEM *bio_buf=NULL;
BIO_get_mem_ptr(mem,&bio_buf);
RSA_free(pub_key);
BIO_free(mem);


}


int get_key(const unsigned char *buf, int len) {

RSA *rsa = d2i_RSA_PUBKEY(NULL, &buf, len); // get data from buffer and do some checks
if (rsa != NULL) {
if (rsa->e != NULL) {
printf("BN : <%s> (hex) -- <%s> (dec)\n", BN_bn2hex(rsa->e), BN_bn2dec(rsa->e));
if (BN_is_odd(rsa->e) == 0) {
printf("Error : RSA public exponent is even\n");
} else {
printf("RSA public exponent is OK.\n");
return 0;
}
}
RSA_free(rsa);
}
else {
printf("Error : RSA is NULL\n");
}
return 1;
}

int main() {
get_buffer();
return get_key(buf, sizeof buf);
}

编译字符串:

gcc -lcrypto -o openssl_odd_even openssl_odd_even.c
/home/packagebuilder/test/openssl_bignum_issue # ./openssl_odd_even
Error : RSA is NULL

最佳答案

我不确定当您可以轻松地直接引用 RSA 结构中加载的 key 时,您为什么要将 key 扔到一些基本缓冲区中。但假设您有一些理由,让我们从基础开始,并解释整个过程中发生了什么。

通过 CLI 生成 key

您可以以任何您想要的形式(PEM 或 DER)生成 key 对。对于我们来说,我们想要 PEM,所以我们必须使用 genpkey 接口(interface)。如果我们想要 DER,我们可以只使用 genrsa 接口(interface),这要容易得多。无论如何,语法看起来像这样。请注意以 PEM 格式生成输出的特定请求(从而使我们诚实地命名 .pem 文件):

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -outform PEM -out testprivate_key.pem

这应该生成 testprivate_key.pem,它看起来像这样:

-----BEGIN PRIVATE KEY-----
... base64 encoding of the key pair here ...
-----END PRIVATE KEY-----

接下来,我们需要这个 key 对中的公钥。我们也可以使用 openssl rsa CLI 来获取它。

openssl rsa -in testprivate_key.pem -inform PEM -pubout -out testpublic_key.pem -outform PEM

这应该创建 testpublic_key.pem,它应该如下所示:

-----BEGIN PUBLIC KEY-----
... bas64 encoding of public key here ...
-----END PUBLIC KEY-----

这会处理关键文件。关于代码。


从 PEM 编码文件读取 RSA 公钥

一旦我们有了这些文件,我们就可以使用 openssl libcrypto(对于 Windows 是 libeay32)将它们中的任何一个读取到程序中。这个简单的示例应用程序从当前工作目录读取 PEM 编码的公钥,然后将其以 DER 形式存储在内存缓冲区中,然后使用 BIO_dump(非常 来自 bio api 的便捷实用函数):

#include <stdio.h>
#include <stdlib.h>

#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

int main()
{
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();

// read the PEM from disk (assumes current working directory)
FILE *fp = fopen("testpublic_key.pem", "r");
if (fp == NULL)
{
perror("testpublic_key.pem");
return EXIT_FAILURE;
}

// load from disk
RSA *pub_key = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
if (pub_key == NULL)
{
perror("Failed to load RSA public key from PEM file");
return EXIT_FAILURE;
}

// no longer need this
fclose(fp);

// from here we can use pub_key however we want. in this case we're
// goin ot store it in a memory buffer in DER form.
unsigned char buff[4*1024], *p = buff;
int len = i2d_RSA_PUBKEY(pub_key, &p);
if (len > 0)
{
// show the content of the buffer in the console using BIO-dump
BIO* bio = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_dump(bio, (const char*)buff, len);
BIO_flush(bio);
BIO_free(bio);
}

RSA_free(pub_key);

return EXIT_SUCCESS;
}

编译它并从我们之前创建的关键文件所在的工作目录运行 locatd,将给我们类似的东西:

示例输出(显然不同)

0000 - 30 82 01 22 30 0d 06 09-2a 86 48 86 f7 0d 01 01   0.."0...*.H.....
0010 - 01 05 00 03 82 01 0f 00-30 82 01 0a 02 82 01 01 ........0.......
0020 - 00 9c b5 e2 ff c0 1b e8-c1 4d cc bb 76 c1 8b d6 .........M..v...
0030 - eb b6 ec 92 a3 e3 38 82-50 16 13 3d 2c bc ef 49 ......8.P..=,..I
0040 - 21 3c d6 83 ae 4d be b7-d5 7c 67 11 84 a4 ed 4e !<...M...|g....N
0050 - 86 b4 c8 41 3e c4 70 e5-a1 cf 9d 13 26 6c bf f2 ...A>.p.....&l..
0060 - 5c 7e 4f 04 a6 0e e0 9d-90 55 87 67 e7 f8 58 62 \~O......U.g..Xb
0070 - a6 ff 85 a0 99 68 62 58-0b 02 66 74 3d f6 19 05 .....hbX..ft=...
0080 - 7d e3 51 fa b1 c2 db e2-f3 e8 fa f5 5f 36 95 67 }.Q........._6.g
0090 - cf 8f eb 32 7e 39 5d e1-37 30 57 5a 1d 25 9d fa ...2~9].70WZ.%..
00a0 - ad 50 63 f5 23 14 b2 2a-de 10 7d b8 7e 83 2b b9 .Pc.#..*..}.~.+.
00b0 - 8c 8b aa 73 7b 4a 91 be-68 5d d8 ad d0 76 e0 de ...s{J..h]...v..
00c0 - 15 bc c6 9a 77 f2 31 a9-11 e3 b7 83 ce ae e2 96 ....w.1.........
00d0 - 6b 9c 2b 20 b9 e5 d7 22-27 46 10 2b 91 5c a3 67 k.+ ..."'F.+.\.g
00e0 - 7e ea 8c d0 69 e1 06 0e-eb 1a a4 dd 22 b9 5e f8 ~...i.......".^.
00f0 - f1 8a db 73 86 57 f2 d5-d1 70 10 24 f7 08 1d 76 ...s.W...p.$...v
0100 - 14 2e de d0 47 95 ce ac-52 fc 4a 16 c5 19 29 cd ....G...R.J...).
0110 - 94 40 f2 23 4d 63 03 5f-10 8a 21 6b 5d 5a 3c 30 .@.#Mc._..!k]Z<0
0120 - 1d 02 03 01 00 01 ......

现在您可以将此缓冲区与您的 get_key 函数一起使用来检查 key 本身的各个部分(尽管我不知道为什么要这样做,因为当它从 PEM 加载时,您已经有了 RSA*)。修改源代码以添加您的 get_key 函数及其对公钥的检查为我们提供了以下内容:

#include <stdio.h>
#include <stdlib.h>

#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

int get_key(const unsigned char *buf, int len)
{
int result = 1;

RSA *rsa = d2i_RSA_PUBKEY(NULL, &buf, len);
if (rsa != NULL)
{
if (rsa->e != NULL)
{
printf("BN : <%s> (hex) -- <%s> (dec)\n", BN_bn2hex(rsa->e), BN_bn2dec(rsa->e));
if (BN_is_odd(rsa->e) == 0)
{
printf("Error : RSA public exponent is even\n");
}
else
{
printf("RSA public exponent is OK.\n");
result = 0;
}
}
RSA_free(rsa);
}
else
{
printf("Error : RSA is NULL\n");
}
return result;
}

int main()
{
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();

// read the PEM from disk (assumes current working directory)
FILE *fp = fopen("testpublic_key.pem", "r");
if (fp == NULL)
{
perror("testpublic_key.pem");
return EXIT_FAILURE;
}

// load from disk
RSA *pub_key = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
if (pub_key == NULL)
{
perror("Failed to load RSA public key from PEM file");
return EXIT_FAILURE;
}

// no longer need this
fclose(fp);

// from here we can use pub_key however we want. in this case we're
// goin ot store it in a memory buffer in DER form.
unsigned char buff[4*1024], *p = buff;
int len = i2d_RSA_PUBKEY(pub_key, &p);
if (len > 0)
{
// show the content of the buffer in the console using BIO-dump
BIO* bio = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_dump(bio, (const char*)buff, len);
BIO_flush(bio);
BIO_free(bio);
}

RSA_free(pub_key);

// run get_key
printf("get_key returned %d\n", get_key(buff, len));

return EXIT_SUCCESS;
}

输出

0000 - 30 82 01 22 30 0d 06 09-2a 86 48 86 f7 0d 01 01   0.."0...*.H.....
0010 - 01 05 00 03 82 01 0f 00-30 82 01 0a 02 82 01 01 ........0.......
0020 - 00 9c b5 e2 ff c0 1b e8-c1 4d cc bb 76 c1 8b d6 .........M..v...
0030 - eb b6 ec 92 a3 e3 38 82-50 16 13 3d 2c bc ef 49 ......8.P..=,..I
0040 - 21 3c d6 83 ae 4d be b7-d5 7c 67 11 84 a4 ed 4e !<...M...|g....N
0050 - 86 b4 c8 41 3e c4 70 e5-a1 cf 9d 13 26 6c bf f2 ...A>.p.....&l..
0060 - 5c 7e 4f 04 a6 0e e0 9d-90 55 87 67 e7 f8 58 62 \~O......U.g..Xb
0070 - a6 ff 85 a0 99 68 62 58-0b 02 66 74 3d f6 19 05 .....hbX..ft=...
0080 - 7d e3 51 fa b1 c2 db e2-f3 e8 fa f5 5f 36 95 67 }.Q........._6.g
0090 - cf 8f eb 32 7e 39 5d e1-37 30 57 5a 1d 25 9d fa ...2~9].70WZ.%..
00a0 - ad 50 63 f5 23 14 b2 2a-de 10 7d b8 7e 83 2b b9 .Pc.#..*..}.~.+.
00b0 - 8c 8b aa 73 7b 4a 91 be-68 5d d8 ad d0 76 e0 de ...s{J..h]...v..
00c0 - 15 bc c6 9a 77 f2 31 a9-11 e3 b7 83 ce ae e2 96 ....w.1.........
00d0 - 6b 9c 2b 20 b9 e5 d7 22-27 46 10 2b 91 5c a3 67 k.+ ..."'F.+.\.g
00e0 - 7e ea 8c d0 69 e1 06 0e-eb 1a a4 dd 22 b9 5e f8 ~...i.......".^.
00f0 - f1 8a db 73 86 57 f2 d5-d1 70 10 24 f7 08 1d 76 ...s.W...p.$...v
0100 - 14 2e de d0 47 95 ce ac-52 fc 4a 16 c5 19 29 cd ....G...R.J...).
0110 - 94 40 f2 23 4d 63 03 5f-10 8a 21 6b 5d 5a 3c 30 .@.#Mc._..!k]Z<0
0120 - 1d 02 03 01 00 01 ......
BN : <010001> (hex) -- <65537> (dec)
RSA public exponent is OK.
get_key returned 0

删除不需要的代码

现实情况是,您一开始就不需要中间缓冲区,我希望这是显而易见的。只需从磁盘加载正确制作的 PEM,并使用由此产生的 RSA* 来检查公共(public)指数。结果就是这样:

#include <stdio.h>
#include <stdlib.h>

#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

int check_key_exponent(RSA *rsa)
{
int result = 1;

if (rsa && rsa->e)
{
printf("BN : <%s> (hex) -- <%s> (dec)\n", BN_bn2hex(rsa->e), BN_bn2dec(rsa->e));
if (BN_is_odd(rsa->e) == 0)
{
printf("Error : RSA public exponent is even\n");
}
else
{
printf("RSA public exponent is OK.\n");
result = 0;
}
}
else
{
printf("Error : RSA is NULL\n");
}
return result;
}

int main()
{
OpenSSL_add_all_algorithms();
OpenSSL_add_all_ciphers();

// read the PEM from disk (assumes current working directory)
FILE *fp = fopen("testpublic_key.pem", "r");
if (fp == NULL)
{
perror("testpublic_key.pem");
return EXIT_FAILURE;
}

// load from disk
RSA *pub_key = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
if (pub_key == NULL)
{
perror("Failed to load RSA public key from PEM file");
return EXIT_FAILURE;
}

// no longer need this
fclose(fp);

// run get_key
printf("check_key_exponent returned %d\n", check_key_exponent(pub_key));

RSA_free(pub_key);

return EXIT_SUCCESS;
}

输出

BN : <010001> (hex) -- <65537> (dec)
RSA public exponent is OK.
check_key_exponent returned 0

关于c - d2i_RSA_PUBKEY 总是返回 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56478002/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com