David
David

Reputation: 3442

RSA Public Key Conversion with just Modulus

I received an RSA-2048 bit public key (256 bytes) as a file which contains just those 256 bytes. Which function in SSL enables me to load this key as an RSA structure so I can convert it to another format? This is in C code using openssl source.

I think it's the DER format, but I'm not 100% certain.

Upvotes: 5

Views: 3307

Answers (1)

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137398

I just put this together and it seems to work correctly:

https://github.com/JonathonReinhart/rawrsa

#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

static const char* appname;

static void print_bn(const char *what, const BIGNUM *bn)
{
#ifdef DEBUG
    char *str = BN_bn2hex(bn);
    printf("%s (hex): %s\n", what, str);
    OPENSSL_free(str);
#endif
}

static void usage(void)
{
    fprintf(stderr, "Usage: %s modulus-file exponent\n", appname);
}

#define err(fmt, ...)   \
    fprintf(stderr, "%s: " fmt, appname, ##__VA_ARGS__)

int main(int argc, char *argv[])
{
    appname = basename(argv[0]);

    if (argc < 3) {
        usage();
        exit(1);
    }

    const char *modfile = argv[1];
    const char *expstr = argv[2];

    /* Read modulus */
    FILE *mf = fopen(modfile, "rb");
    if (!mf) {
        err("Failed to open \"%s\": %m\n", modfile);
        return 1;
    }

    unsigned char buf[256];
    if (fread(buf, sizeof(buf), 1, mf) != 1) {
        err("Failed to read %zu bytes of modulus\n", sizeof(buf));
        return 1;
    }

    fclose(mf);

    BIGNUM *mod = BN_bin2bn(buf, sizeof(buf), NULL);
    if (!mod) {
        err("BN_bin2bn() failed\n");
        return 1;
    }
    print_bn("Modulus", mod);


    /* Parse exponent */
    BIGNUM *exp = NULL;
    if (BN_dec2bn(&exp, expstr) == 0) {
        err("BN_dec2bn() failed\n");
        return 1;
    }
    print_bn("Exponent", exp);

    /* Create RSA key */
    RSA *rsa = RSA_new();
    if (!rsa) {
        err("RSA_new() failed\n");
        return 1;
    }
    rsa->e = exp;
    rsa->n = mod;

    /* Write PEM-encoded RSA public key to stdout */
    if (!PEM_write_RSAPublicKey(stdout, rsa)) {
        err("PEM_write_RSAPublicKey() failed\n");
        return 1;
    }

    return 0;
}

I use BN_bin2bn to create an OpenSSL bignum from raw binary data from a file. This is where we load your 256-byte modulus.

Then, I use BN_dec2bn to create a bignum from the exponent provided on the command line.

Next, I create an RSA object with RSA_new, and set the public exponent (rsa->e) and modulus (rsa->n).

Finally, I write the RSA public key to a PEM file with PEM_write_RSAPublicKey.

Example:

$ scons -Q
gcc -o main.o -c -Wall -Werror -g main.c
gcc -o rawrsa main.o -lcrypto

$ ./rawrsa key.bin 65537
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA9cFHSTQ6h1Ls/vx7B+V/84XVlLxUU1dU1mEr9ROAqWrZtfasvx2E
21lbva+AdJ/B4u6fGVhCEMgekXsRB65CqZfwL3DFL6tqam6GvrOyvZgAlQKrA54w
DaKMT8Kfg2I2K9W/HCkCOHczhuHhjFmeiV9BuQgpmcPcNz6UXBwU05d3g6oM/X4m
lEhEsaH4bqo1qsMX6jp6WnsR13GEfsYoYVmHgEbnKJyGpsoRVW6HQXLHvef9XLEJ
v9n7nLdHToya75svxJ3v9JugD3n6PiC48085/FWb9980o4hmG9iW5rehm4Dlui8c
TDnHkQSrvi9WLlZ+S8hdtwDRN/pVVTjgPAIDAQAB
-----END RSA PUBLIC KEY-----

Upvotes: 5

Related Questions