Reputation: 141
I am learning to use the openssl/cryptolib. Am working to build a simple p2p chat room with encryption.
My intent is to use a Diffie-Hellman key exchange scheme. As I understand it, it is powered by the math behind the discrete logarithm problem. In short, it is secured by computationally heavy operations. The scheme has a few key components; each party has to have a private key and a public key. Diffie-Hellman enables the creation of a shared encrypted key via "signing" with each parties private keys.
As of now, I am interested in generating the Key-Pairs, extracting the public component of each, and transmit it to the other peer. This is what i have so far
#include <openssl/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
// My way of error-handling
typedef struct {
int code;
const char *msg;
} Ret;
#define RET \
(Ret) { .code = 1, .msg = "SUCCESS" }
#define cout(...) printf(__VA_ARGS__)
#define err(...) fprintf(stderr, __VA_ARGS__)
#define RED "\x1B[31m"
#define NORM "\033[0m"
#define PUBLIC_KEY_SIZE 1000
Ret fn3() {
// It is my understanding that if a context, and other such things
// are not explicitly set, ssl will use default values.
Ret ret = RET;
const char *curveName = "secp521r1";
EVP_PKEY *pkey = EVP_EC_gen(curveName);
if (NULL == pkey) {
ret = (Ret){1, "Unable to generate key"};
goto cleanup;
}
EVP_PKEY_print_public_fp(stdout, pkey, 1, NULL);
int keySize = EVP_PKEY_get_size(pkey);
cout("Key size is %d\n", keySize);
size_t publicKeySize = PUBLIC_KEY_SIZE;
unsigned char publicKey[PUBLIC_KEY_SIZE];
// I expected this method to extract the public key without error,
// however this fails. I am not sure why this is failing.
if (EVP_PKEY_get_raw_public_key(pkey, publicKey, &publicKeySize) <= 0) {
unsigned long err = ERR_get_error();
char *errMsg = ERR_error_string(err, NULL);
ret = (Ret){1, errMsg};
goto cleanup;
}
EVP_PKEY_get_raw_public_key(pkey, publicKey, &publicKeySize);
cout("Public key size: %zu bytes\n[%s]\n", publicKeySize, publicKey);
cleanup:
EVP_PKEY_free(pkey);
return ret;
}
int main(void) {
Ret ret = fn3();
if (ret.code) {
err(RED "[%s:%s:%d] Failed\n\t%s\n" NORM, __FILE__, __func__, __LINE__,
ret.msg);
} else {
cout("%s\n", ret.msg);
}
return ret.code;
}
I expected this code to extract the public key from the key pair and print the size along with a string representation of it.
This is the output instead
Compilation command gcc t.c -o main -lssl -lcrypto && ./main
Public-Key: (521 bit)
pub:
04:01:d5:9b:3e:df:c6:87:44:24:0b:46:0d:a8:0c:
f7:b5:40:3b:11:43:39:ca:15:54:03:98:a3:f1:14:
18:07:4e:6c:4c:75:c9:43:98:11:f8:1f:cf:a7:b1:
62:dd:55:f0:43:ab:92:77:79:7e:74:c7:da:55:98:
c5:2e:2f:3d:4a:97:87:00:af:75:63:cb:c0:91:12:
26:8b:fa:ef:6b:a6:96:b3:14:bd:83:54:7b:5a:b1:
e6:e1:91:c3:26:d4:05:0b:24:66:d1:c9:74:73:a2:
4c:09:60:aa:ea:19:5f:6a:29:7e:7b:cb:fa:1c:c3:
10:78:ee:a9:97:94:2a:27:3d:9f:41:17:48
ASN1 OID: secp521r1
NIST CURVE: P-521
Key size is 139
[t.c:main:66] Failed
error:00000000:lib(0)::reason(0)
This makes me think that the public key is correctly generated. The weird thing is that the EVP_PKEY_get_raw_public_key returns an error, but the program does not generate a helpful error.
My intent is that after the receiving peer gets the public key, I will be able to start working on the actual Diffie-Hellman part of the protocol.
Any help is appreciated.
Upvotes: 3
Views: 34