如何使用 openSSL C++ 以 PEM 格式存储 Diffie HellMan 对象的密钥

How to store Diffie HellMan Object's Keys in PEM Format using openSSL C++

我在以 PEM 格式存储我的 DH 密钥时遇到了一个愚蠢的问题。这是以 Diffie Hellman 格式生成密钥的工作代码片段,我可以以 PEM 格式存储 DH 参数。但是,我在 openSSL 中找不到任何可以以 PEM 格式存储密钥的函数。

DH *privkey = DH_new();
/* Generate the parameters to be used */
DH_generate_parameters_ex(privkey, 2048, DH_GENERATOR_2, NULL)

/* Generate the public and private key pair */
DH_generate_key(privkey)

/* Store DH Params in PEM Format */
FILE* fptr = fopen("dhp.pem", "w");
PEM_write_DHparams(fptr, privkey);

/* Get PublicKey of Peer To generate Shared Secret ----*/
BIGNUM *pubkeyPeer = NULL;
BN_dec2bn(&pubkeyPeer, BN_bn2dec(GetPubKeyPeer());

/* Generate Shared Secret by getting Public Key of Peer */
unsigned char *secret;
int secret_size;
if (NULL == (secret= (unsigned char *)OPENSSL_malloc(sizeof(unsigned char) * (DH_size(privkey))))) {
        printf("Can Not Allocate Memory for Shared Secret ");
    }
if (0 > (secret_size = DH_compute_key(secret, pubkeyPeer, privkey))) {
        printf("Shared Secret Generation Failure ");
}

/* DUMP Shared Secret ---*/
BIO_dump_fp(stdout, (const char *)secret, secret_size);

这一切都很好,但我需要以 PEM 格式与同行分享我的 Public 密钥。是否有一些功能可以将我的 DH Public 密钥转换为 PEM 格式?

OpenSSL 有一个通用函数 PEM_write_PKCS8PrivateKey,它能够将 EVP_PKEY 密钥写入 PEM 格式的 PKCS8 结构。为了利用它,您必须像这样包装您的 DH 密钥,为简洁起见省略了错误检查:

EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_DH(pkey, privkey);
PEM_write_PKCS8PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, NULL);

PKCS8允许你加密内容,那些我没有在那个调用中设置的尾随参数用于设置加密细节。我在这里省略了它们,但您通常确实希望您的私钥 material 在实践中加密存储。

尝试一下(删除您的 BIO_dump_fp 调用后):

> dh_key
-----BEGIN PRIVATE KEY-----
MIICZAIBADCCAjkGByqGSM4+AgEwggIsAoIBAQCHqOYdtLZmPP+70ZxlGVmZjO72
CGYN0PJdLO7UQ147AOAN+PHWGVfU+vffRWGyqjAWw9kRNAlvqjv0KW2DDpp8IJ4M
ZJdRer1aip0wa89n7ZH55nJbR1jAIuCx70J1v3tsW/wR1F+QiLlB9U6x5Zu4vDmg
vxIwf1xP23DFgbI/drY6yuHKpreQLVJSZzVIig7xPG2aUb+kqzrYNHeWUk2O9qFn
taQYJdln4UTlFAVkJRzKy4PmtIb2s8o/eXFQYCbAuFf2iZYoVt7UAQq9C+Yhw6OW
ClTnEMN18mN11wFBA6S1QzDBmK8SYRbSJ24RcV9pOHf61+8JytsJSukeGhWXAoIB
AD+zLJtzE00LLndQZmDtvUhMp7GPIe8gVAf0eToaC6ElENvBUHe+Rj//T+1KrAu1
Vb46bBsMa0exvDdzv36Mb2KQEij4woy7GKVa4xNBAAplAZb5Mcd6V/Ld9GPl6ewU
S3d95iqquKhiisN20oLW7Thk5nmCQo68gx0UNI9vL5GTtQRa8nZxZOHfyWfB+z8u
VaS9G//oO5yA0FK5hdGC6grbKjtzE9P+FMhISx4FJYi5t9K70t8BYZns0G4VV80J
FbM1O7tk4Ow3f9AoNw35K1LHiRQozcZ+thhLUj0dskbDL2MHhJDwDvjWR9FI1HlU
UV4jJ8/vmMWCZktMD2zEFlkCIQCM+DZCpwmgl7RHmXZAEp2imbGkfR6zdQujCLD+
ZPX70wQiAiBvWQZVf0vXQPl+ovrzFwbia4oDGbPwYtQ83yaLtFo0hw==
-----END PRIVATE KEY-----

显示 PEM 输出。通过 asn1parse 管道显示其内容:

> dh_key | openssl asn1parse
    0:d=0  hl=4 l= 612 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :00
    7:d=1  hl=4 l= 569 cons: SEQUENCE
   11:d=2  hl=2 l=   7 prim: OBJECT            :X9.42 DH
   20:d=2  hl=4 l= 556 cons: SEQUENCE
   24:d=3  hl=4 l= 257 prim: INTEGER           :87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597
  285:d=3  hl=4 l= 256 prim: INTEGER           :3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659
  545:d=3  hl=2 l=  33 prim: INTEGER           :8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3
  580:d=1  hl=2 l=  34 prim: OCTET STRING      [HEX DUMP]:0220537AF1D957AB4D23D3779A22F2DD20F3330A0179DCF50AE922491EFB08976517

这实际上也包括参数。