문제

C/C ++ 응용 프로그램이 있으며 공개 및 개인 키가 포함 된 X509 PEM 인증서를 만들어야합니다. 인증서는 자체 서명하거나 서명되지 않은 것은 중요하지 않습니다.

명령 줄이 아니라 앱 내부 에서이 작업을 수행하고 싶습니다.

어떤 OpenSSL 기능이 저를 위해이 작업을 수행합니까? 모든 샘플 코드는 보너스입니다!

도움이 되었습니까?

해결책

먼저 용어와 메커니즘에 익숙해 져야합니다.

x.509 자격증, 정의상 개인 키는 포함되지 않습니다. 대신, 그것은 CA가 공개 키의 CA에 서명 한 버전입니다 (CA가 서명에 넣는 모든 속성과 함께). PEM 형식은 실제로 키와 인증서의 별도의 스토리지 만 지원하지만 두 가지를 연결할 수는 있지만 두 가지를 연결할 수 있습니다.

어쨌든 Key 및 자체 서명 된 인증서를 만들려면 OpenSSL API의 20 개 이상의 다른 기능을 호출해야합니다. 예를 들어 OpenSSL 소스 자체에 있습니다. 데모/x509/mkcert.c

더 자세한 답변은 참조하십시오 Nathan Osman의 설명 아래에.

다른 팁

나는 이것이 매우 늦고 긴 대답이라는 것을 알고 있습니다. 그러나이 질문이 검색 엔진 결과에서 얼마나 잘 순위를 매겼는지 고려할 때, 나는 괜찮은 답을 쓸 가치가 있다고 생각했습니다.

아래에서 읽을 많은 것들이 빌려요 이 데모 그리고 OpenSSL 문서. 아래 코드는 C와 C ++ 모두에 적용됩니다.


실제로 인증서를 만들기 전에 개인 키를 만들어야합니다. OpenSSL 제공을 제공합니다 EVP_PKEY 알고리즘 독립적 개인 키를 메모리에 저장하기위한 구조. 이 구조는 선언됩니다 openssl/evp.h 그러나 포함되어 있습니다 openssl/x509.h (나중에 필요로하는 것) 따라서 실제로 헤더를 명시 적으로 포함시킬 필요는 없습니다.

할당하기 위해 EVP_PKEY 구조, 우리는 사용합니다 EVP_PKEY_new:

EVP_PKEY * pkey;
pkey = EVP_PKEY_new();

구조를 제거하기위한 해당 기능도 있습니다. EVP_PKEY_free - 단일 인수를 받아들입니다 EVP_PKEY 위에서 초기화 된 구조.

이제 키를 생성해야합니다. 이 예에서는 RSA 키를 생성합니다. 이것은 이루어집니다 RSA_generate_key 선언 된 기능 openssl/rsa.h. 이 함수는 포인터를 반환합니다 RSA 구조.

함수의 간단한 호출은 다음과 같습니다.

RSA * rsa;
rsa = RSA_generate_key(
    2048,   /* number of bits for the key - 2048 is a sensible value */
    RSA_F4, /* exponent - RSA_F4 is defined as 0x10001L */
    NULL,   /* callback - can be NULL if we aren't displaying progress */
    NULL    /* callback argument - not needed in this case */
);

반환 값의 경우 RSA_generate_key ~이다 NULL, 그럼 뭔가 잘못되었습니다. 그렇지 않다면 이제 우리는 RSA 키를 가지고 있으며, 우리는 그것을 우리에게 할당 할 수 있습니다. EVP_PKEY 이전의 구조 :

EVP_PKEY_assign_RSA(pkey, rsa);

그만큼 RSA 구조는 자동으로 해제됩니다 EVP_PKEY 구조가 해제됩니다.


이제 인증서 자체를 위해.

OpenSSL을 사용합니다 X509 메모리에서 X509 인증서를 나타내는 구조. 이 구조물에 대한 정의가 있습니다 openssl/x509.h. 우리가 필요로하는 첫 번째 기능은입니다 X509_new. 그것의 사용은 비교적 간단합니다.

X509 * x509;
x509 = X509_new();

그렇듯이 EVP_PKEY, 구조를 제거하기위한 해당 기능이 있습니다. X509_free.

이제 일부를 사용하여 인증서의 몇 가지 속성을 설정해야합니다. X509_* 기능 :

ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);

이것은 인증서의 일련 번호를 '1'로 설정합니다. 일부 오픈 소스 HTTP 서버는 기본값 인 '0'의 일련 번호가있는 인증서를 수락하지 않습니다. 다음 단계는 인증서가 실제로 유효한 시간 범위를 지정하는 것입니다. 다음 두 가지 기능 호출로 다음을 수행합니다.

X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);

첫 번째 줄은 인증서를 설정합니다 notBefore 현재 시간에 속성. (그만큼 X509_gmtime_adj 함수는 현재 시간에 지정된 초를 추가합니다 -이 경우 없음) 두 번째 줄은 인증서를 설정합니다. notAfter 지금부터 365 일까지 (60 초 * 60 분 * 24 시간 * 365 일).

이제 이전에 생성 한 키를 사용하여 인증서의 공개 키를 설정해야합니다.

X509_set_pubkey(x509, pkey);

이것은 자체 서명 된 인증서이므로 발행자의 이름을 주제의 이름으로 설정합니다. 이 과정의 첫 번째 단계는 주제 이름을 얻는 것입니다.

X509_NAME * name;
name = X509_get_subject_name(x509);

이전에 명령 줄에 자체 서명 된 인증서를 만든 적이 있다면 아마도 국가 코드를 요청받은 것을 기억할 것입니다. 여기 우리가 조직 ( 'o') 및 공통 이름 ( 'CN')과 함께 제공하는 곳입니다.

X509_NAME_add_entry_by_txt(name, "C",  MBSTRING_ASC,
                           (unsigned char *)"CA", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O",  MBSTRING_ASC,
                           (unsigned char *)"MyCompany Inc.", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                           (unsigned char *)"localhost", -1, -1, 0);

(저는 캐나다인이고 우리 국가 코드이기 때문에 여기에서 'CA'값을 사용하고 있습니다. 또한 매개 변수 #4는 명시 적으로 캐스트되어야합니다. unsigned char *.)

이제 실제로 발행자 이름을 설정할 수 있습니다.

X509_set_issuer_name(x509, name);

그리고 마지막으로 우리는 서명 과정을 수행 할 준비가되었습니다. 우리는 전화합니다 X509_sign 우리가 일찍 생성 한 열쇠로. 이를위한 코드는 고통스럽게 간단합니다.

X509_sign(x509, pkey, EVP_sha1());

우리는 사용 중입니다 SHA-1 키에 서명하는 해싱 알고리즘. 이것은 다음과 같습니다 mkcert.c 데모 MD5를 사용하는이 답변의 시작 부분에서 언급했습니다.


이제 자체 서명 된 인증서가 있습니다! 그러나 우리는 아직 완료되지 않았습니다.이 파일을 디스크에 작성해야합니다. 고맙게도 Openssl은 우리도 그곳을 덮었습니다 PEM_* 선언 된 기능 openssl/pem.h. 우리가 필요로하는 첫 번째 것은입니다 PEM_write_PrivateKey 개인 키를 저장했습니다.

FILE * f;
f = fopen("key.pem", "wb");
PEM_write_PrivateKey(
    f,                  /* write the key to the file we've opened */
    pkey,               /* our key from earlier */
    EVP_des_ede3_cbc(), /* default cipher for encrypting the key on disk */
    "replace_me",       /* passphrase required for decrypting the key on disk */
    10,                 /* length of the passphrase string */
    NULL,               /* callback for requesting a password */
    NULL                /* data to pass to the callback */
);

개인 키를 암호화하고 싶지 않다면 간단히 통과하십시오. NULL 위의 세 번째 및 네 번째 매개 변수의 경우. 어느 쪽이든, 당신은 파일을 세계적으로 읽을 수 없는지 확인하고 싶을 것입니다. (UNIX 사용자의 경우 이는 의미합니다 chmod 600 key.pem.)

아휴! 이제 우리는 하나의 기능으로 다운되었습니다. 인증서를 디스크에 작성해야합니다. 이것에 필요한 기능은입니다 PEM_write_X509:

FILE * f;
f = fopen("cert.pem", "wb");
PEM_write_X509(
    f,   /* write the certificate to the file we've opened */
    x509 /* our certificate */
);

그리고 우리는 끝났습니다! 이 답변의 정보가 OpenSSL의 표면을 간신히 긁지 않았지만이 답변의 정보가 모든 것이 어떻게 작동하는지에 대한 대략적인 아이디어를 제공하기에 충분합니다.

실제 응용 프로그램에서 위의 모든 코드가 어떻게 보이는지 보는 데 관심이있는 사람들을 위해, 나는 당신이 볼 수있는 요점 (C ++로 작성)을 함께 버렸습니다. 여기.

a system 앱 내에서 호출 하시겠습니까? 이것을하는 몇 가지 좋은 이유 :

  • 라이센스 : 전화 openssl 실행 파일은이를 응용 프로그램에서 분리하고 특정 장점을 제공 할 수 있습니다. 면책 조항 : 이에 대한 변호사와 상담하십시오.

  • 문서 : OpenSSL은 함께 제공됩니다 경이로운 잠재적으로 복잡한 도구를 크게 단순화하는 명령 줄 문서.

  • 테스트 가능성 : 명령 줄에서 OpenSSL을 연습 할 수 있습니다. A가 있습니다 많은 옵션; 모든 세부 사항을 올바르게 얻을 때까지 하루에 하루를 보내십시오. 그 후, 명령을 앱에 통합하는 것은 사소한 일입니다.

API를 사용하기로 선택한 경우 openssl-dev www.openssl.org의 개발자 목록.

행운을 빕니다!

디지털 인증서를 만들기위한 매우 간단한 튜토리얼 http://publib.boulder.ibm.com/infocenter/rsthelp/v8r0m0/index.jsp?topic=/com.ibm.rational.lt.doc/topics/tcreatecertopenssl.html

코드에서 이러한 명령을 실행하는 것에 대해 확실하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top