2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * Example showing how to generate an RSA key pair.
13 * When generating an RSA key, you must specify the number of bits in the key. A
14 * reasonable value would be 4096. Avoid using values below 2048. These values
15 * are reasonable as of 2022.
20 #include <openssl/err.h>
21 #include <openssl/evp.h>
22 #include <openssl/rsa.h>
23 #include <openssl/core_names.h>
24 #include <openssl/pem.h>
26 /* A property query used for selecting algorithm implementations. */
27 static const char *propq
= NULL
;
30 * Generates an RSA public-private key pair and returns it.
31 * The number of bits is specified by the bits argument.
33 * This uses the long way of generating an RSA key.
35 static EVP_PKEY
*generate_rsa_key_long(OSSL_LIB_CTX
*libctx
, unsigned int bits
)
37 EVP_PKEY_CTX
*genctx
= NULL
;
38 EVP_PKEY
*pkey
= NULL
;
39 unsigned int primes
= 2;
41 /* Create context using RSA algorithm. "RSA-PSS" could also be used here. */
42 genctx
= EVP_PKEY_CTX_new_from_name(libctx
, "RSA", propq
);
44 fprintf(stderr
, "EVP_PKEY_CTX_new_from_name() failed\n");
48 /* Initialize context for key generation purposes. */
49 if (EVP_PKEY_keygen_init(genctx
) <= 0) {
50 fprintf(stderr
, "EVP_PKEY_keygen_init() failed\n");
55 * Here we set the number of bits to use in the RSA key.
56 * See comment at top of file for information on appropriate values.
58 if (EVP_PKEY_CTX_set_rsa_keygen_bits(genctx
, bits
) <= 0) {
59 fprintf(stderr
, "EVP_PKEY_CTX_set_rsa_keygen_bits() failed\n");
64 * It is possible to create an RSA key using more than two primes.
65 * Do not do this unless you know why you need this.
66 * You ordinarily do not need to specify this, as the default is two.
68 * Both of these parameters can also be set via EVP_PKEY_CTX_set_params, but
69 * these functions provide a more concise way to do so.
71 if (EVP_PKEY_CTX_set_rsa_keygen_primes(genctx
, primes
) <= 0) {
72 fprintf(stderr
, "EVP_PKEY_CTX_set_rsa_keygen_primes() failed\n");
77 * Generating an RSA key with a number of bits large enough to be secure for
78 * modern applications can take a fairly substantial amount of time (e.g.
79 * one second). If you require fast key generation, consider using an EC key
82 * If you require progress information during the key generation process,
83 * you can set a progress callback using EVP_PKEY_set_cb; see the example in
84 * EVP_PKEY_generate(3).
86 fprintf(stderr
, "Generating RSA key, this may take some time...\n");
87 if (EVP_PKEY_generate(genctx
, &pkey
) <= 0) {
88 fprintf(stderr
, "EVP_PKEY_generate() failed\n");
92 /* pkey is now set to an object representing the generated key pair. */
95 EVP_PKEY_CTX_free(genctx
);
100 * Generates an RSA public-private key pair and returns it.
101 * The number of bits is specified by the bits argument.
103 * This uses a more concise way of generating an RSA key, which is suitable for
104 * simple cases. It is used if -s is passed on the command line, otherwise the
105 * long method above is used. The ability to choose between these two methods is
106 * shown here only for demonstration; the results are equivalent.
108 static EVP_PKEY
*generate_rsa_key_short(OSSL_LIB_CTX
*libctx
, unsigned int bits
)
110 EVP_PKEY
*pkey
= NULL
;
112 fprintf(stderr
, "Generating RSA key, this may take some time...\n");
113 pkey
= EVP_PKEY_Q_keygen(libctx
, propq
, "RSA", (size_t)bits
);
116 fprintf(stderr
, "EVP_PKEY_Q_keygen() failed\n");
122 * Prints information on an EVP_PKEY object representing an RSA key pair.
124 static int dump_key(const EVP_PKEY
*pkey
)
128 BIGNUM
*n
= NULL
, *e
= NULL
, *d
= NULL
, *p
= NULL
, *q
= NULL
;
131 * Retrieve value of n. This value is not secret and forms part of the
134 * Calling EVP_PKEY_get_bn_param with a NULL BIGNUM pointer causes
135 * a new BIGNUM to be allocated, so these must be freed subsequently.
137 if (EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_N
, &n
) == 0) {
138 fprintf(stderr
, "Failed to retrieve n\n");
143 * Retrieve value of e. This value is not secret and forms part of the
144 * public key. It is typically 65537 and need not be changed.
146 if (EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_E
, &e
) == 0) {
147 fprintf(stderr
, "Failed to retrieve e\n");
152 * Retrieve value of d. This value is secret and forms part of the private
153 * key. It must not be published.
155 if (EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_D
, &d
) == 0) {
156 fprintf(stderr
, "Failed to retrieve d\n");
161 * Retrieve value of the first prime factor, commonly known as p. This value
162 * is secret and forms part of the private key. It must not be published.
164 if (EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_FACTOR1
, &p
) == 0) {
165 fprintf(stderr
, "Failed to retrieve p\n");
170 * Retrieve value of the second prime factor, commonly known as q. This value
171 * is secret and forms part of the private key. It must not be published.
173 * If you are creating an RSA key with more than two primes for special
174 * applications, you can retrieve these primes with
175 * OSSL_PKEY_PARAM_RSA_FACTOR3, etc.
177 if (EVP_PKEY_get_bn_param(pkey
, OSSL_PKEY_PARAM_RSA_FACTOR2
, &q
) == 0) {
178 fprintf(stderr
, "Failed to retrieve q\n");
183 * We can also retrieve the key size in bits for informational purposes.
185 if (EVP_PKEY_get_int_param(pkey
, OSSL_PKEY_PARAM_BITS
, &bits
) == 0) {
186 fprintf(stderr
, "Failed to retrieve bits\n");
190 /* Output hexadecimal representations of the BIGNUM objects. */
191 fprintf(stdout
, "\nNumber of bits: %d\n\n", bits
);
192 fprintf(stderr
, "Public values:\n");
193 fprintf(stdout
, " n = 0x");
194 BN_print_fp(stdout
, n
);
195 fprintf(stdout
, "\n");
197 fprintf(stdout
, " e = 0x");
198 BN_print_fp(stdout
, e
);
199 fprintf(stdout
, "\n\n");
201 fprintf(stdout
, "Private values:\n");
202 fprintf(stdout
, " d = 0x");
203 BN_print_fp(stdout
, d
);
204 fprintf(stdout
, "\n");
206 fprintf(stdout
, " p = 0x");
207 BN_print_fp(stdout
, p
);
208 fprintf(stdout
, "\n");
210 fprintf(stdout
, " q = 0x");
211 BN_print_fp(stdout
, q
);
212 fprintf(stdout
, "\n\n");
214 /* Output a PEM encoding of the public key. */
215 if (PEM_write_PUBKEY(stdout
, pkey
) == 0) {
216 fprintf(stderr
, "Failed to output PEM-encoded public key\n");
221 * Output a PEM encoding of the private key. Please note that this output is
222 * not encrypted. You may wish to use the arguments to specify encryption of
223 * the key if you are storing it on disk. See PEM_write_PrivateKey(3).
225 if (PEM_write_PrivateKey(stdout
, pkey
, NULL
, NULL
, 0, NULL
, NULL
) == 0) {
226 fprintf(stderr
, "Failed to output PEM-encoded private key\n");
232 BN_free(n
); /* not secret */
233 BN_free(e
); /* not secret */
234 BN_clear_free(d
); /* secret - scrub before freeing */
235 BN_clear_free(p
); /* secret - scrub before freeing */
236 BN_clear_free(q
); /* secret - scrub before freeing */
240 int main(int argc
, char **argv
)
243 OSSL_LIB_CTX
*libctx
= NULL
;
244 EVP_PKEY
*pkey
= NULL
;
245 unsigned int bits
= 4096;
246 int bits_i
, use_short
= 0;
248 /* usage: [-s] [<bits>] */
249 if (argc
> 1 && strcmp(argv
[1], "-s") == 0) {
256 bits_i
= atoi(argv
[1]);
258 fprintf(stderr
, "Invalid RSA key size\n");
262 bits
= (unsigned int)bits_i
;
265 /* Avoid using key sizes less than 2048 bits; see comment at top of file. */
267 fprintf(stderr
, "Warning: very weak key size\n\n");
269 /* Generate RSA key. */
271 pkey
= generate_rsa_key_short(libctx
, bits
);
273 pkey
= generate_rsa_key_long(libctx
, bits
);
278 /* Dump the integers comprising the key. */
279 if (dump_key(pkey
) == 0) {
280 fprintf(stderr
, "Failed to dump key\n");
287 OSSL_LIB_CTX_free(libctx
);