Last active
November 2, 2022 21:44
-
-
Save justanotherminh/91b26ecaa13110b877dcc4f21fd4e3f8 to your computer and use it in GitHub Desktop.
OpenSSL examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <openssl/evp.h> | |
#include <openssl/kdf.h> | |
#include <openssl/objects.h> | |
#include <openssl/crypto.h> | |
#include <openssl/core_names.h> | |
#include <openssl/obj_mac.h> | |
#include <openssl/bio.h> | |
#include <openssl/err.h> | |
#include <openssl/ec.h> | |
#include <openssl/rsa.h> | |
#include <openssl/pem.h> | |
#include <openssl/bn.h> | |
#include <openssl/sha.h> | |
#include <openssl/hmac.h> | |
// Helper functions | |
void print_bn(BIGNUM* bn) { | |
int size = BN_num_bytes(bn); | |
uint8_t buffer[size]; | |
BN_bn2bin(bn, buffer); | |
for (int i = 0; i < size; i++) { | |
printf("%02X ", buffer[i]); | |
} | |
printf("\n"); | |
printf("%d bytes written\n", size); | |
} | |
// Toy code | |
void foo1() { | |
uint8_t x_data[32]; | |
uint8_t y_data[32]; | |
for (int i = 0; i < 32; i++) { | |
x_data[i] = 0x01; | |
y_data[i] = 0x02; | |
} | |
uint8_t pub_data[65]; | |
pub_data[0] = (uint8_t) POINT_CONVERSION_UNCOMPRESSED; | |
memcpy(&pub_data[1], &x_data[0], 32); | |
memcpy(&pub_data[33], &y_data[0], 32); | |
for (int i = 0; i < 65; i++) { | |
printf("%X ", pub_data[i]); | |
} | |
printf("\n"); | |
// BN_CTX * ctx = BN_CTX_new(); | |
BIGNUM * x = BN_new(); | |
BIGNUM * y = BN_new(); | |
BN_bin2bn(x_data, 32, x); | |
BN_bin2bn(y_data, 32, y); | |
const EC_GROUP * group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); | |
const EC_POINT * point = EC_POINT_new(group); | |
EC_POINT_set_affine_coordinates(group, point, x, y, NULL); | |
size_t bufsize = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); | |
printf("Buffer size: %d\n", bufsize); | |
unsigned char buffer[22]; | |
size_t bytes_written = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, &buffer[0], bufsize, NULL); | |
for (int i = 0; i < 65; i++) { | |
printf("%02X ", buffer[i]); | |
} | |
printf("%d\n", bytes_written); | |
} | |
void foo2() { | |
EC_KEY* key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); | |
EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE); | |
if (!EC_KEY_generate_key(key)) { | |
fprintf(stderr, "Error generating key\n"); | |
} | |
EVP_PKEY* pkey = EVP_PKEY_new(); | |
if (!EVP_PKEY_assign_EC_KEY(pkey, key)) { | |
fprintf(stderr, "Error assigning pkey\n"); | |
} | |
printf("pkey size: %d bits\n", EVP_PKEY_bits(pkey)); | |
EC_GROUP* group = EC_KEY_get0_group(key); | |
EC_POINT* point = EC_POINT_new(group); | |
point = EC_KEY_get0_public_key(key); | |
BIGNUM* priv = BN_new(); | |
priv = EC_KEY_get0_private_key(key); | |
int priv_size = BN_num_bytes(priv); | |
uint8_t priv_data[priv_size]; | |
BN_bn2bin(priv, priv_data); | |
printf("Private key:\n"); | |
for (int i = 0; i < priv_size; i++) { | |
printf("%02X ", priv_data[i]); | |
} | |
printf("\n"); | |
BIGNUM* x = BN_new(); | |
BIGNUM* y = BN_new(); | |
EC_POINT_get_affine_coordinates(group, point, x, y, NULL); | |
int x_size = BN_num_bytes(x); | |
int y_size = BN_num_bytes(y); | |
uint8_t x_data[x_size]; | |
uint8_t y_data[y_size]; | |
BN_bn2bin(x, x_data); | |
BN_bn2bin(y, y_data); | |
printf("Public key x:\n"); | |
for (int i = 0; i < x_size; i++) { | |
printf("%02X ", x_data[i]); | |
} | |
printf("\n"); | |
printf("Public key y:\n"); | |
for (int i = 0; i < y_size; i++) { | |
printf("%02X ", y_data[i]); | |
} | |
printf("\n"); | |
BN_free(x); | |
BN_free(y); | |
BN_free(priv); | |
EC_POINT_free(point); | |
EC_GROUP_free(group); | |
// EC_KEY_free(key); | |
// EVP_PKEY_free(pkey); | |
} | |
void foo3() { | |
EC_KEY* key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); | |
EC_GROUP* group = EC_KEY_get0_group(key); | |
EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE); | |
const unsigned char priv_data[] = { | |
0xb9, 0x2f, 0x3c, 0xe6, 0x2f, 0xfb, 0x45, 0x68, | |
0x39, 0x96, 0xf0, 0x2a, 0xaf, 0x6c, 0xda, 0xf2, | |
0x89, 0x8a, 0x27, 0xbf, 0x39, 0x9b, 0x7e, 0x54, | |
0x21, 0xc2, 0xa1, 0xe5, 0x36, 0x12, 0x48, 0x5d | |
}; | |
BIGNUM* priv_bn = BN_bin2bn(priv_data, 32, NULL); | |
if (EC_KEY_set_private_key(key, priv_bn) == 0) | |
fprintf(stderr, "Error setting private key\n"); | |
// Allocate memory for public key | |
EC_POINT* public_point = EC_POINT_new(EC_KEY_get0_group(key)); | |
// Performs multiplication | |
EC_POINT_mul(group, public_point, priv_bn, NULL, NULL, NULL); | |
BIGNUM* x = BN_new(); | |
BIGNUM* y = BN_new(); | |
EC_POINT_get_affine_coordinates(group, public_point, x, y, NULL); | |
int x_size = BN_num_bytes(x); | |
int y_size = BN_num_bytes(y); | |
uint8_t x_data[x_size]; | |
uint8_t y_data[y_size]; | |
BN_bn2bin(x, x_data); | |
BN_bn2bin(y, y_data); | |
printf("Public key x:\n"); | |
for (int i = 0; i < x_size; i++) { | |
printf("%02X ", x_data[i]); | |
} | |
printf("\n"); | |
printf("Public key y:\n"); | |
for (int i = 0; i < y_size; i++) { | |
printf("%02X ", y_data[i]); | |
} | |
printf("\n"); | |
} | |
void foo4() { | |
EVP_PKEY* pkey = EVP_EC_gen(SN_X9_62_prime256v1); | |
// EVP_PKEY* pkey = EVP_RSA_gen(1024); | |
if (!pkey) { | |
fprintf(stderr, "pkey creation failed\n"); | |
abort(); | |
} | |
EC_KEY* key = EVP_PKEY_get1_EC_KEY(pkey); | |
if (!key) { | |
fprintf(stderr, "failed to get key type from EVP_PKEY\n"); | |
abort(); | |
} | |
BIGNUM* priv = EC_KEY_get0_private_key(key); | |
if (!priv) { | |
fprintf(stderr, "failed to obtain private key from pkey\n"); | |
abort(); | |
} | |
int size = BN_num_bytes(priv); | |
uint8_t priv_data[size]; | |
printf("Private key:\n"); | |
for (int i = 0; i < size; i++) { | |
printf("%02X ", priv_data[i]); | |
} | |
printf("\n"); | |
EC_POINT* pub = EC_KEY_get0_public_key(key); | |
EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); | |
if (!pub) { | |
fprintf(stderr, "failed to obtain public key from pkey\n"); | |
abort(); | |
} | |
BIGNUM* x = BN_new(); | |
BIGNUM* y = BN_new(); | |
EC_POINT_get_affine_coordinates(group, pub, x, y, NULL); | |
int x_size = BN_num_bytes(x); | |
int y_size = BN_num_bytes(y); | |
uint8_t x_data[x_size]; | |
uint8_t y_data[y_size]; | |
BN_bn2bin(x, x_data); | |
BN_bn2bin(y, y_data); | |
printf("Public key x:\n"); | |
for (int i = 0; i < x_size; i++) { | |
printf("%02X ", x_data[i]); | |
} | |
printf("\n"); | |
printf("Public key y:\n"); | |
for (int i = 0; i < y_size; i++) { | |
printf("%02X ", y_data[i]); | |
} | |
printf("\n"); | |
BIO* bio = BIO_new(BIO_s_file()); | |
bio = BIO_new_fp(stdout, BIO_NOCLOSE); | |
PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, 0, NULL); | |
unsigned char* buffer = NULL; | |
size_t bytes_written = 0; | |
OSSL_ENCODER_CTX* ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, EVP_PKEY_KEYPAIR, "PEM", NULL, NULL); | |
if (!ctx) { | |
fprintf(stderr, "Failed to create context\n"); | |
abort(); | |
} | |
if (!OSSL_ENCODER_to_data(ctx, &buffer, &bytes_written)) { | |
fprintf(stderr, "Writing to buffer failed\n"); | |
abort(); | |
} | |
// BIO_dump_fp(stdout, buffer, bytes_written); | |
// BIO* bio = BIO_new_file("keypair.pem", "wb"); | |
BIO_write(bio, buffer, bytes_written); | |
BN_free(priv); | |
BN_free(x); | |
BN_free(y); | |
EC_GROUP_free(group); | |
EC_POINT_free(pub); | |
// EC_KEY_free(key); | |
EVP_PKEY_free(pkey); | |
// OSSL_ENCODER_CTX_free(ctx); | |
BIO_free_all(bio); | |
} | |
void foo5() { | |
EVP_PKEY* pkey = EVP_RSA_gen(1024); | |
RSA* key = EVP_PKEY_get1_RSA(pkey); | |
BIO* bio = BIO_new(BIO_s_file()); | |
bio = BIO_new_fp(stdout, BIO_NOCLOSE); | |
PEM_write_bio_RSAPrivateKey(bio, key, NULL, NULL, 0, 0, NULL); | |
unsigned char *buffer = NULL; | |
size_t bytes_written; | |
OSSL_ENCODER_CTX* ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, EVP_PKEY_KEYPAIR, "PEM", NULL, NULL); | |
OSSL_ENCODER_to_data(ctx, &buffer, &bytes_written); | |
BIO_write(bio, buffer, (int) bytes_written); | |
} | |
void foo6() { | |
EVP_PKEY* pkey = EVP_RSA_gen(1024); | |
const BIGNUM* n = NULL; | |
const BIGNUM* e = NULL; | |
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &n); | |
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &e); | |
printf("n:\n"); | |
print_bn(n); | |
printf("e:\n"); | |
print_bn(e); | |
// EVP_PKEY* pkey = EVP_EC_gen(SN_X9_62_prime256v1); | |
// const BIGNUM* x = BN_new(); | |
// const BIGNUM* y = BN_new(); | |
// EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x); | |
// EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y); | |
// printf("X:\n"); | |
// print_bn(x); | |
// printf("Y:\n"); | |
// print_bn(y); | |
BN_free(n); | |
BN_free(e); | |
// BN_free(x); | |
// BN_free(y); | |
EVP_PKEY_free(pkey); | |
} | |
void foo7() { | |
// Create content buffer | |
char buffer[128]; | |
for (int i = 0; i < 128; i++) { | |
buffer[i] = (5*i+13)%128; | |
} | |
// Deprecated code | |
unsigned char hash1[SHA256_DIGEST_LENGTH]; | |
SHA256_CTX ctx; | |
SHA256_Init(&ctx); | |
SHA256_Update(&ctx, buffer, 128); | |
SHA256_Final(hash1, &ctx); | |
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { | |
printf("%02X ", hash1[i]); | |
} | |
printf("\n"); | |
// Migrated code | |
unsigned char hash2[SHA256_DIGEST_LENGTH]; | |
EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); | |
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); | |
EVP_DigestUpdate(mdctx, buffer, 128); | |
EVP_DigestFinal_ex(mdctx, hash2, NULL); | |
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { | |
printf("%02X ", hash2[i]); | |
} | |
printf("\n"); | |
EVP_MD_CTX_free(mdctx); | |
} | |
void foo8() { | |
unsigned char key[128]; | |
for (int i = 0; i < 128; i++) { | |
key[i] = (13*i + 101)%256; | |
} | |
unsigned char data[128]; | |
for (int i = 0; i < 128; i++) { | |
data[i] = (i*i + 5*i + 13)%256; | |
} | |
printf("Key:\n"); | |
for (int i = 0; i < 128; i++) { | |
printf("%02X", key[i]); | |
} | |
printf("\nData:\n"); | |
for (int i = 0; i < 128; i++) { | |
printf("%02X", data[i]); | |
} | |
printf("\n"); | |
unsigned char buffer[32] = {0}; | |
unsigned int hmac_size; | |
HMAC_CTX* ctx; | |
if (!(ctx = HMAC_CTX_new())) | |
printf("441\n"); | |
if (!HMAC_Init_ex(ctx, (const void *)&key[0], 128, EVP_sha256(), NULL)) | |
printf("443\n"); | |
if (!HMAC_Update(ctx, (const unsigned char *)&data[0], 128)) | |
printf("445\n"); | |
if (!HMAC_Final(ctx, &buffer[0], &hmac_size)) | |
printf("447\n"); | |
printf("Bytes written: %d\n", hmac_size); | |
for (int i=0; i < hmac_size; i++) { | |
printf("%02X", buffer[i]); | |
} | |
printf("\n"); | |
unsigned char buffer2[32] = {0}; | |
unsigned int hmac_size2; | |
EVP_MAC* mac; | |
if (!(mac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL))) | |
printf("458\n"); | |
EVP_MAC_CTX* ctx2; | |
if (!(ctx2 = EVP_MAC_CTX_new(mac))) | |
printf("461\n"); | |
OSSL_PARAM params[3]; | |
params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, (const void *)&key[0], 128); | |
params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, OSSL_DIGEST_NAME_SHA2_256, 0); | |
params[2] = OSSL_PARAM_construct_end(); | |
if (!EVP_MAC_init(ctx2, NULL, 0, params)) | |
printf("463\n"); | |
if (!EVP_MAC_update(ctx2, (const unsigned char *)&data[0], 128)) | |
printf("465\n"); | |
if (!EVP_MAC_final(ctx2, &buffer2[0], &hmac_size2, 32)) | |
printf("467\n"); | |
printf("Bytes written: %d\n", hmac_size2); | |
for (int i=0; i < hmac_size2; i++) { | |
printf("%02X", buffer2[i]); | |
} | |
printf("\n"); | |
} | |
int main() { | |
printf("OpenSSL version %x\n", OPENSSL_VERSION_NUMBER); | |
foo8(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment