简体   繁体   中英

Format RSA Key to Public Key with OpenSSL in C++

I have an RSA key of 538 hexadecimal characters like this:

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. 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:

    -----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:

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. I hope you can guide me on how to do things using OpenSSL functions.

There are different types and keysizes of RSA keys. 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.
    • Paste the hexadecial characters into a text file.
    • Read the text file into a fp with "r" option, using fopen.
    • Reading the key using this function automatically puts the public key into the format you want (which is PEM format ).
  2. use RSA_public_encrypt to encrypt as you said. Use the RSA structure from above.

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.

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:

ASN1 RSA format: d2i_RSAPublicKey_bio

PEM RSA format: PEM_read_bio_RSAPublicKey

which will return a RSA pointer you can use. It all depends on the format you have your RSA public key in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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