简体   繁体   English

在C ++中使用OpenSSL将RSA密钥格式化为公钥

[英]Format RSA Key to Public Key with OpenSSL in C++

I have an RSA key of 538 hexadecimal characters like this: 我有一个538个十六进制字符的RSA密钥,如下所示:

3082010902820100C011E8900B1FFA6F4869448D4449FC57FF388B34A39C5783DE462CFD00FA6AFF30C24A579010A695EB3A0996E9417AF841874EE2A45FADBE287541BE0AC60EE40DD001220573F8EB4C0EEFEB549C16511B5FE5F2109A31BB8857C99EDAAFC8193AA8EDCE900CB31993A9CC3676CAC394105AD53A6DB2B0BE02C0A64F8103DEFA76BC9CFA256898565D545D35135D1D5D205EB99BC30DEF82DAD4664C7872372107CE28CC91AD34CE50E6C690F60B83DD4AD027C433FEDF243B710954E1A51456AA92125C3063CDCFD4E21B170F22A352F5C34350D9ADC91F0699CD5898E6BE39C0D5D58D2A3907C85B879AC8FAF98D997E2E0CDFF8ECCD3CB2354E31A582F3910203010001
  1. The first problem I have is that I need my key of 538 characters to get its public key (which according to an online program returns a 588-character key) but I can not find how to convert it. 我遇到的第一个问题是,我需要538个字符的密钥来获取其公共密钥(根据在线程序,该公共密钥会返回588个字符的密钥),但我找不到如何进行转换。 I am currently using that online program to get the public key. 我目前正在使用该在线程序来获取公共密钥。

  2. The second problem is when I already have the public Rsa key of 588 characters, i need to move to this format: 第二个问题是当我已经拥有588个字符的公共Rsa密钥时,我需要移至以下格式:

    -----BEGIN PUBLIC KEY----- MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgF35rHhOWi9+r4n9xM/ejvMEs Q8h6lams962k4U0WSdfySUevhyI1bd3FRIb5fFqSBt6qPTiiiIw0KXte5dANB6lP e6HdUPTA/U4xHWi2FB/BfAyPsOlUBfFp6dtkEEcEKt+Z8KTJYJEerRie24y+nsfZ MnLBst6tsEBfx/U75wIBAw== -----END PUBLIC KEY----- ----- BEGIN PUBLIC KEY ----- MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCgF35rHhOWi9 + r4n9xM / ejvMEs Q8h6lams962k4U0WSdfySUevhyI1bd3FRIb5fFqSBt6qPTiiiIw0KXte5dANB6lP e6HdUPTA / U4xHWi2FB / BfAyPsOlUBfFp6dtkEEcEKt + Z8KTJYJEerRie24y + nsfZ MnLBst6tsEBfx / U75wIBAw == ----- END PUBLIC KEY -----

Currently I do it "by hand" converting my RSA key from 588 characters to base64 and pasting the values ​​one by one in this way: 目前我是通过手工将我的RSA密钥从588个字符转换为base64并按以下方式逐个粘贴值的:

unsigned char* publicKey;

string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) 
{
    int i = 0;
    int j = 0;
    unsigned char char_array_3[3];
    unsigned char char_array_4[4];
    string ret;

    while (in_len--) 
    {
        char_array_3[i++] = *(bytes_to_encode++);

        if (i == 3) 
        {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for(i = 0; (i < 4) ; i++)
            {
                ret += base64_chars[char_array_4[i]];
            }

            i = 0;
        }
    }

    if (i)
    {
        for(j = i; j < 3; j++)
        {
            char_array_3[j] = '\0';
        }

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (j = 0; (j < i + 1); j++)
        {
            ret += base64_chars[char_array_4[j]];
        }

        while((i++ < 3))
        {
            ret += '=';
        }
    }

    return ret;
}

bool format_to_Public_Key()
{
    string Rsa_588 = "3082010902820....10203010001"; //588 Length RSA key

    if(Rsa_588.length() == 588)
    {
        string rsa_base64 = base64_encode(reinterpret_cast<unsigned char *>(stringHex_to_charHex(Rsa_588)), (Rsa_588.length() / 2));

        string format_rsa_base64 = "-----BEGIN PUBLIC KEY-----\n" +
                                   rsa_base64.substr(0, 64) + "\n" + 
                                   rsa_base64.substr(64, 64) + "\n" +
                                   rsa_base64.substr(128, 64) + "\n" +
                                   rsa_base64.substr(192, 64) + "\n" +
                                   rsa_base64.substr(256, 64) + "\n" +
                                   rsa_base64.substr(320, 64) + "\n" +
                                   rsa_base64.substr(384, 8) + "\n" +
                                   "-----END PUBLIC KEY-----\n";

        publicKey = (unsigned char*)format_rsa_base64.c_str();

        return true;
    }

All this is to use the RSA_public_encrypt() Api of OpenSSL, The problem is that I'm doing things "by hand" and I'm sure it can be done in a more efficient way but I do not know what. 所有这些都是使用OpenSSL的RSA_public_encrypt()Api,问题是我正在“手工”做事情,我敢肯定它可以以更有效的方式完成,但我不知道是什么。 I hope you can guide me on how to do things using OpenSSL functions. 我希望您能指导我如何使用OpenSSL函数。

There are different types and keysizes of RSA keys. RSA密钥有不同的类型和密钥大小。 It would be more helpful, if you specify each. 如果您指定每个,它会更有帮助。

There are 2 steps to achieving what you want. 有两个步骤可以实现您想要的。

  1. use OpenSSL function PEM_read_RSAPrivateKey to load the key into an OpenSSL RSA structure. 使用OpenSSL函数PEM_read_RSAPrivateKey将密钥加载到OpenSSL RSA结构中。
    • Paste the hexadecial characters into a text file. 将十六进制字符粘贴到文本文件中。
    • Read the text file into a fp with "r" option, using fopen. 使用fopen将文本文件读入带有“ r”选项的fp中
    • Reading the key using this function automatically puts the public key into the format you want (which is PEM format ). 使用此功能读取密钥会自动将公共密钥设置为所需的格式( PEM格式 )。
  2. use RSA_public_encrypt to encrypt as you said. 如您所说使用RSA_public_encrypt进行加密。 Use the RSA structure from above. 从上面使用RSA结构。

There are declarations for functions above. 上面有函数的声明。

 1. RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **x,
                                    pem_password_cb *cb, void *u);
 2. int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);

Assuming your key is a ASN.1 formated RSA key pair then you want to use the use the d2i_RSAPrivateKey_xxx methods to read in the key and use the PEM_write_bio_RSAPUBLICKey method to write out your public key. 假设您的密钥是ASN.1格式的RSA密钥对,那么您想使用d2i_RSAPrivateKey_xxx方法读取密钥,并使用PEM_write_bio_RSAPUBLICKey方法写出公共密钥。

eg 例如

bool load_and_export_rsa_public_key()
{
    auto* bio = BIO_new_file("rsa.key", "rb");
    if(!bio) return false;
    auto const rsa = d2i_RSAPrivateKey_bio(bio, nullptr);
    BIO_free(bio);

    if(!rsa) return false;

    auto const bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
    PEM_write_bio_RSAPublicKey(bio_out, rsa);
    RSA_free(rsa);
    return true;
}

UPDATE: If it's just a RSA public key then you can use: 更新:如果只是RSA公钥,则可以使用:

ASN1 RSA format: d2i_RSAPublicKey_bio ASN1 RSA格式: d2i_RSAPublicKey_bio

PEM RSA format: PEM_read_bio_RSAPublicKey PEM RSA格式: PEM_read_bio_RSAPublicKey

which will return a RSA pointer you can use. 这将返回您可以使用的RSA指针。 It all depends on the format you have your RSA public key in. 这完全取决于您拥有RSA公钥的格式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM