[C/C++] SSL 인증서

Alexandria·2024년 3월 4일
0

C lang

목록 보기
7/14
post-thumbnail

1. 환경

OpenSSL 라이브러리를 사용하기 위해 libssl-dev를 설치한다.

$ sudo apt -y install libssl-dev

컴파일 시 libcrypto.so, libssl.so을 링킹하여 컴파일한다.

2. 개인 키

2048길이의 RSA 키를 생성한다.

이후 32byte의 키값을 통해서 개인키를 암호화하여 저장한다.

#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>

int main(void) {
    BIGNUM *bignum = NULL;
    ERR_clear_error();
    if ((bignum  = BN_new()) == NULL) {
        printf("BN_new error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        return EXIT_FAILURE;
    }
    if(BN_set_word(bignum, RSA_F4) != 1) {
        printf("BN_set_word error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        BN_clear_free(bignum);
        return EXIT_FAILURE;
    }

    RSA *rsa = NULL;
    if ((rsa = RSA_new()) == NULL) {
        printf("RSA_new error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        BN_clear_free(bignum);
        return EXIT_FAILURE;
    }
    if (RSA_generate_key_ex(rsa, 2048, bignum, NULL) != 1) {
        printf("RSA_generate_key_ex error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        BN_clear_free(bignum);
        return EXIT_FAILURE;
    }
    BN_clear_free(bignum);
    
    FILE *PrivateFilePointer = fopen("./private.key", "wb");
    if (PrivateFilePointer == NULL) {
        perror("private.key open fail");
        RSA_free(rsa);
        rsa     = NULL;
        return EXIT_FAILURE;
    }
    
    unsigned char KEY[32] = { 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08 };
    if(PEM_write_RSAPrivateKey(PrivateFilePointer, rsa, EVP_aes_256_cbc(), KEY, sizeof(KEY), NULL, NULL) != 1)
    {
        printf("PEM_write_RSAPrivateKey error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        fclose(PrivateFilePointer);
        PrivateFilePointer = NULL;
        RSA_free(rsa);
        rsa = NULL;
        return EXIT_FAILURE;
    }
    fclose(PrivateFilePointer);
    PrivateFilePointer = NULL;
    RSA_free(rsa);
    return 0;
}

3. 인증서

암호화된 개인키를 로드한 뒤 인증서생성하기 위해 사용한다.

이후 인증서 정보를 생성하고 자체 서명을 통해 생성한 인증서를

파일로 저장해본다.

#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <string.h>

int password_cb(char *pcszBuff,int size,int rwflag, void *pPass)
{
    size_t unPass = strlen((char*)pPass);
    if(unPass > (size_t)size) unPass = (size_t)size;
    memcpy(pcszBuff, pPass, unPass);
    return (int)unPass;
}

int main(void) {
    unsigned char key[32] = { 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08 };

    FILE *fp = fopen("private.key", "r");
    if (!fp) {
        printf("File Open Error\n");
        return EXIT_FAILURE;
    }

    EVP_PKEY* pkey = PEM_read_PrivateKey(fp, NULL, password_cb, (void *)key);
    if (!pkey) {
        printf("BN_new error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        return EXIT_FAILURE;
    }

    X509 *x509 = NULL;
    if ((x509 = X509_new()) == NULL) {
        printf("X509_new error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        EVP_PKEY_free(pkey);
        return EXIT_FAILURE;
    }
    X509_set_version(x509, 2);
    ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)time(NULL));
    X509_gmtime_adj(X509_get_notBefore(x509), 0);
    X509_gmtime_adj(X509_get_notAfter(x509), (long)(60 * 60 * 24 * 365));
    X509_set_pubkey(x509, pkey);

    X509_NAME *name = NULL;
    if ((name = X509_NAME_new()) == NULL) {
        printf("X509_NAME_new error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        EVP_PKEY_free(pkey);
        X509_free(x509);
        return EXIT_FAILURE;
    }
    X509_NAME_add_entry_by_txt(name, "C", 	MBSTRING_ASC, (unsigned char *)"KR",	-1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "O", 	MBSTRING_ASC, (unsigned char *)"World",	-1, -1, 0);
	X509_NAME_add_entry_by_txt(name, "OU",	MBSTRING_ASC, (unsigned char *)"X509",	-1, -1, 0);
	X509_NAME_add_entry_by_txt(name, "CN",	MBSTRING_ASC, (unsigned char *)"2jinu", -1, -1, 0);
    X509_set_issuer_name(x509, name);

    if(X509_sign(x509, pkey, EVP_sha256()) == 0) {
        printf("X509_sign error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        EVP_PKEY_free(pkey);
        X509_free(x509);
        return EXIT_FAILURE;
    }
    EVP_PKEY_free(pkey);

    FILE *CertificateFilePointer = fopen("./certificate.crt", "wb");
    if (CertificateFilePointer == NULL) {
        perror("certificate.crt open fail");
        X509_free(x509);
        return EXIT_FAILURE;
    }
    if(PEM_write_X509(CertificateFilePointer, x509) != 1) {
        printf("PEM_write_X509 error : %s\n", ERR_error_string(ERR_get_error(), NULL));
        X509_free(x509);
        fclose(CertificateFilePointer);
        return EXIT_FAILURE;
    }
    CRYPTO_cleanup_all_ex_data();
    ERR_free_strings();
    EVP_cleanup();
    return 0;
}
profile
IT 도서관

0개의 댓글

관련 채용 정보