
ããæ°
ãã·ã¢èªã話ãã€ã³ã¿ãŒãããã§ã¯ãOpenSSL APIã©ã€ãã©ãªã«é¢ããæ
å ±ãèŠã€ããããšã¯å°é£ã§ãã WebãµãŒããŒãŸãã¯OpenVPNãµãŒããŒã®èªå·±çœ²åèšŒææžãæäœããããã®ã³ã³ãœãŒã«ã³ãã³ãã®äœ¿çšã«ã¯ãå€ãã®æ³šæãæãããŸãã
ãã®ã¢ãããŒãã¯ã1æéã«2ã3ã®èšŒææžãäœæããå¿
èŠãããå Žåã«é©ããŠããŸãã ãŸããæ¯åæ°çŸãããã«äœæããå¿
èŠãããå Žåã¯ã©ããªããŸããïŒ ãŸãã¯ãã¹ã¯ãªãããèšè¿°ããŠãã³ã³ãœãŒã«ããã®åºåãè§£æããŸããïŒ ãããŠãããã»ã¹ã§ãšã©ãŒãçºçããå Žåã¯ã©ããªããŸããïŒ
APIã䜿çšãããšãèšŒææžã®çæãæ€èšŒãããã³çœ²åãã¯ããã«ç°¡åã«ãªããŸãã ãã¹ãŠã®äœæ¥æ®µéã§ãšã©ãŒãå¶åŸ¡ããã³åŠçãã远å ã®èšŒææžãã©ã¡ãŒã¿ãŒïŒã³ã³ãœãŒã«ãããã¹ãŠã®ãã©ã¡ãŒã¿ãŒãèšå®ã§ããããã§ã¯ãªãããïŒãæå®ããŠåŸ®èª¿æŽããæ©äŒããããŸãã
ãããšã¯å¥ã«ããããã¯ãŒã¯ã³ã³ããŒãã³ãã«æ³šç®ãã䟡å€ããããŸãã èšŒææžãããããã£ã¹ã¯äžã«ããå Žåãããã¯åœ¹ã«ç«ã¡ãŸããã
æ®å¿µãªãããSSLãµãŒããŒã®æ§æãããŒã¿ãåä¿¡ããããã®SSLã¯ã©ã€ã¢ã³ãã®æ§ææ¹æ³ã«é¢ãããã·ã¢èªã®ããã¥ã¡ã³ãã¯ã»ãšãã©ãããŸããã å
¬åŒããã¥ã¡ã³ãã¯å®å
šã§ã¯ãªããããã«ã©ã€ãã©ãªã®æäœã«é¢äžã§ããã»ã©åªããŠããŸããã ãã¹ãŠã®æ©èœã詳现ã«èª¬æãããŠããããã§ã¯ãããŸããããã©ã¡ãŒã¿ãŒãã¯ãªãŒã³ã¢ããããå¿
èŠãããã·ãŒã±ã³ã¹ãããã³æ£ç¢ºã«äœããã©ã€ãã©ãªãŒãããèªäœã§åé€ããããå®éšããå¿
èŠããããŸãã
ãã®èšäºã¯ãã¯ã©ã€ã¢ã³ã/ãµãŒããŒã¢ããªã±ãŒã·ã§ã³ãå®è£
ããéã®OpenSSLã©ã€ãã©ãªã«é¢ããç§ã®çµéšããŸãšãããã®ã§ãã ããã§èª¬æãããŠããæ©èœã¯ããã¹ã¯ããããšAndroidããã€ã¹ã®äž¡æ¹ã§æ©èœããŸãã C / C ++ã³ãŒããå«ããªããžããªãèšäºã«æ·»ä»ãããŠããããã説æãããŠããæ©èœã®åäœã確èªã§ããŸãã
ç®ç
æ°ããã©ã€ãã©ãªããã¯ãããžãŒãå匷ãããšããç§ã¯æ°ããæ©èœã®å©ããåããŠåé¡ã解決ããããšããŸãã ãã®å Žåã MITMãå®è¡ããŠã¿ãŠãã ãã
HTTPSãµãŒããŒãžã®ãã©ãã£ãã¯ãã€ã³ã¿ãŒã»ããããŸãã
ããã°ã©ã ã®èŠä»¶ãçå®ããŸãã
ããŒãæ¥ç¶ãåŸ
ã€ïŒSSLãµãŒããŒïŒ
çä¿¡æ¥ç¶ã衚瀺ããããïŒ
- HTTPSãµãŒããŒã«æ¥ç¶ãã
- ãµãŒããŒãžã®ã¯ã©ã€ã¢ã³ããªã¯ãšã¹ãã®èªã¿åã
- ã¯ã©ã€ã¢ã³ãããèªã¿åã£ãããŒã¿ããµãŒããŒã«è»¢éãã
- ãµãŒããŒå¿çã®èªã¿åã
- ãµãŒããŒãžã®å¿çãã¯ã©ã€ã¢ã³ãã«éä¿¡
- æ¥ç¶ããªã»ãã
SSLãµãŒããŒããããããèªèšŒå±ã®èšŒææžãšãµãŒããŒã®èšŒææžãå¿
èŠã«ãªããŸãã
ãã®ããŒã¿ãããã°ã©ã ã§çæãããšãCAèšŒææžãããã°ã©ã ã®äœæ¥ãã©ã«ããŒå
ã®ãã¡ã€ã«ã«ã¢ããããŒããããŸãã
éçºã¯ãUbuntuãä»ã®ããŒã«ã§è¡ãããŸãïŒGCC 5.4.0ã³ã³ãã€ã©ãŒãOpenSSL 1.0.2ãcurl 7.52.1ãCMake 3.8.1ïŒããã±ãŒãžã«å«ãŸããŠããªããã®ã®ã¿ïŒã
ã¢ããªã±ãŒã·ã§ã³ã«ãªã¯ãšã¹ããéä¿¡ããã«ã¯ãã³ã³ãœãŒã«ããcurlã䜿çšããŸãã CAèšŒææžãæå®ããå¿
èŠããããããã³ãã³ãã¯æ¬¡ã®ããã«ãªããŸãã
curl --cacert ca.crt -v https://127.0.0.1:5566 -H "Host: taigasystem.com"
curlãHTTPèŠæ±ãæ£ããæ§æããã«ã¯ã HostããããŒãå¿
èŠã§ãã ããããªããšããµãŒããŒã¯ãšã©ãŒã§å¿çããŸãã
äœæ¥ã®éå§ãšçµäº
OpenSSLã©ã€ãã©ãªã䜿çšããã«ã¯ãåæåããå¿
èŠããããŸãã æ¬¡ã®ã³ãŒãã䜿çšããŸãã
#include <openssl/bio.h> #include <openssl/ssl.h> #include <openssl/err.h> ... void InitOpenSSL() { OpenSSL_add_all_algorithms(); ERR_load_BIO_strings(); ERR_load_crypto_strings(); SSL_load_error_strings(); SSL_library_init(); }
ã¢ããªã±ãŒã·ã§ã³ãå®äºããåã«ãã©ã€ãã©ãªãæ¶å»ããå¿
èŠããããŸããããã«ã¯ã次ã®ã³ãŒãã䜿çšã§ããŸãã
void ClearOpenSSL() { EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); ERR_free_strings(); }
ã³ã³ããã¹ã
ã»ãšãã©ã®OpenSSLã©ã€ãã©ãªæäœã«ã¯ã³ã³ããã¹ããå¿
èŠã§ãã ãã®æ§é ã«ã¯ã䜿çšãããã¢ã«ãŽãªãºã ããã©ã¡ãŒã¿ãŒããã®ä»ã®ããŒã¿ãæ ŒçŽãããŸãã 颿°ã䜿çšããŠäœæãããŸãïŒ
SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
ãã®é¢æ°ã«æž¡ãããšãã§ããã¡ãœããã®ãªã¹ãã¯éåžžã«åºç¯å²ã«æž¡ããŸããã ããã¥ã¡ã³ãã«ã¯ããµãŒããŒã«ã¯SSLv23_client_method()
ããã¯ã©ã€ã¢ã³ãã«ã¯SSLv23_server_method()
ã䜿çšããå¿
èŠããããšSSLv23_client_method()
ããŠããŸãã
ã©ã€ãã©ãªã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒããµããŒãããæãå®å
šãªãããã³ã«ãèªåçã«éžæããŸãã
ã¯ã©ã€ã¢ã³ãã®ã³ã³ããã¹ããäœæããäŸã次ã«ç€ºããŸãã
SSL_CTX *ctx = NULL; ctx = SSL_CTX_new(SSLv23_client_method()); if (ctx == NULL) {
ã³ã³ããã¹ããæ£ããåé€ããã«ã¯ã SSL_CTX_free
颿°ã䜿çšããŸãã
ã³ã³ããã¹ããåé€ããå¿
èŠããããã³ã«SSL_CTX_free
ã䜿çšããããšã¯ããŸã奜ãã§ã¯ãããŸããã delete颿°ã§ã¹ããŒããã€ã³ã¿ãŒã䜿çšãããã RAIIã¯ã©ã¹ã§æ§é ãã©ããããããšãã§ããŸãã
std::shared_ptr<SSL_CTX> m_ctx(ctx, SSL_CTX_free);
ãšã©ãŒåŠç
ã»ãšãã©ã®OpenSSLã©ã€ãã©ãªé¢æ°ã¯ãæåã®å
åãšããŠ1ãè¿ããŸãã éåžžã®ãšã©ãŒãã§ãã¯ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
if (SSL_CTX_load_verify_locations(ctx, fileName, NULL) != 1) {
ãã ããããã§ã¯äžååãªå Žåããããåé¡ã®ãã詳现ãªèª¬æãå¿
èŠãªå ŽåããããŸãã ãããè¡ãããã«ã OpenSSLã¯åã¹ã¬ããã§åå¥ã®ã¡ãã»ãŒãžãã¥ãŒã䜿çšããŸãã ãã¥ãŒãããšã©ãŒã³ãŒããååŸããã«ã¯ã ERR_get_error()
颿°ã䜿çšããŸãã
ãšã©ãŒã³ãŒãèªäœã¯ãŠãŒã¶ãŒã«ã¯ããŸãæç¢ºã§ã¯ãªãããã ERR_error_string
颿°ã䜿çšããŠãšã©ãŒã³ãŒãã®æåå衚çŸãååŸã§ããŸãã 颿°ã0ãè¿ãå Žåããšã©ãŒããªãããšãæå³ããŸãã
ãšã©ãŒã³ãŒãã«ãã£ãŠãšã©ãŒã説æããæååãååŸããäŸã次ã«ç€ºããŸãã
#include <openssl/err.h> ... // - OpenSSL std::cerr << ERR_error_string(ERR_get_error(), NULL) << std::endl; ...
ERR_error_string
颿°ã®2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯ãå°ãªããšã120æåã®é·ãã®ãããã¡ãŒãžã®ãã€ã³ã¿ãŒã§ãã æå®ããªãå Žåãéçãããã¡ã䜿çšããããã®é¢æ°ãåŒã³åºããããã³ã«äžæžããããŸãã
åã
ã®ã¹ã¬ããããšã«åå¥ã®ãšã©ãŒã¡ãã»ãŒãžãã¥ãŒãäœæãããããšã«æ³šæããŠãã ããã
ããŒ
次ã«ãOpenSSLãµãŒããŒãæŽçããããã«ãèšŒææ©é¢ã®èšŒææžãšãµãŒããŒèšŒææžãäœæããå¿
èŠããããŸãã ããããã«ã€ããŠã眲åçšã®ããŒãäœæããå¿
èŠããããŸãã
äœæ
OpenSSLã¯EVP_PKEY
æ§é äœã䜿çšããŠãç§å¯/å
¬éããŒãã¢ãæ ŒçŽããŸãã ãã®æ§é ã¯æ¬¡ã®ããã«äœæãããŸãã
EVP_PKEY *pkey = NULL; pkey = EVP_PKEY_new(); if (pkey == NULL) {
EVPã®è©³çްã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã
EVP_PKEY_new
颿°EVP_PKEY_new
颿°EVP_PKEY_free
ã¯ã¡ã¢ãªãè§£æŸããæ§é EVP_PKEY
ãåé€ããŸãã
次ã«ã RSAãçæããããã«BIGNUM
æ§é ãæºåããå¿
èŠããããŸãïŒãã®æ§é ã®è©³çްã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ïŒ
BIGNUM *big = NULL; big = BN_new(); if (big == NULL) {
BN_set_word
颿°ã¯ã BIGNUM
æ§é ã®ãµã€ãºãèšå®ããŸãã æå¹ãªå€ã¯RSA_3
ãšRSA_F4
ã§ãåŸè
ãæãŸããã§ãã
ä»ããéµçæã®çªã§ãã ãããè¡ãã«ã¯ã RSA
æ§é ãäœæããŸãã
RSA *rsa = NULL; rsa = RSA_new(); if (rsa == NULL) {
ããŒçæèªäœïŒ
if (RSA_generate_key_ex(rsa, 4096, big, NULL) != 1) {
4096ã¯ãåãåãããããŒã®ãµã€ãºã§ãã
EVP_PKEY
æ§é ã«æ°ããããŒãæžã蟌ãããšã§ãããŒã®çæãçµäºããŸãã
if (EVP_PKEY_assign_RSA(pkey, rsa) !=1) {
PEMã¯ãããŒãšèšŒææžãä¿åããããã®ããªãåçŽãªåœ¢åŒã§ãã ãã©ãŒã ã®ã¬ã³ãŒããé çªã«ä¿åãããããã¹ããã¡ã€ã«ã§ãã
-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAvNwgYmIyfvY6IsVZwRCkAHTOhwE3Rp/uNcUoTcPl5atOwPVW JLY3odYmILsa8se7B/aNNzO7AlvXwlzxinQ3AF7l37LqGzf8v16TFVN4kit8vrq0 V9bBXHpiWH+YQT4gBVmSkwqEMZ/wQlUOIxz4Q2M7cXRu4fRe3rt3kGHCPJ66Ybax yEp6nfdK8IKsyxqAXjBkqfC5rkdw2n7UAd/OnPRCDowyvythDb8jR1LkbJjlIatK .... yajhmBDpS11hzuWHhDmpjbrV79OMRzKQAWBKRubObtGIsFB2CzbabusV+oq/Y78y OxriZYqoRv3WB5GH/pPO9w1ptveddLU33NVBSRfFS1jyqyj/1CqXlE4gcQ== -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIFkTCCA3mgAwIBAgIJAMPIqA2oVd/SMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV BAYTAlJVMQ8wDQYDVQQIDAZNb3Njb3cxDzANBgNVBAcMBk1vc2NvdzEUMBIGA1UE ... bt9NHGnCxYcParG+YqU5UTUrCUGUfnZhJAX+qkgsVSC5c81Tk0VXTQx3EiEvdzV+ wUX9LMRLIxjy1D5AO6a29LkzNAvw+iFm36VO+ssdkJW4Q6MAYA== -----END CERTIFICATE-----
ããããŒã®å
é ãšæ«å°Ÿãããã³çµäºè¡ã®æåæ°-----ãåãã§ãªããã°ãªããªãããšã«æ³šæããŠãã ããã
ãã®åœ¢åŒã«ã€ããŠã¯ãããã§è©³ãã説æããŸãã
-RFC1421ããŒãIïŒã¡ãã»ãŒãžã®æå·åãšèªèšŒã®æé
-RFC1422ããŒãIIïŒèšŒææžããŒã¹ã®ããŒç®¡ç
-RFC1423ããŒãIIIïŒã¢ã«ãŽãªãºã ãã¢ãŒããããã³èå¥å
-RFC1424ããŒãIVïŒäž»èŠãªèªèšŒãšé¢é£ãµãŒãã¹
EVP_PKEYæ§é ã«å
¬éããŒãšç§å¯ããŒã®ãã¢ãããããããããã¡ã€ã«ã«æžã蟌ãã«ã¯ã PEM_write_PrivateKey
ããã³PEM_write_PUBKEY
䜿çšãããšãPEM_write_PUBKEY
ã
ãããã®é¢æ°ã®äœ¿çšäŸã次ã«ç€ºããŸãã
FILE *f = fopen("server.pem", "wb"); if (!PEM_write_PrivateKey(f, key, NULL, NULL, 0, 0, NULL)) {
æ©èœã«ã€ããŠèª¬æãã䟡å€ããããŸãã
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, void *u);
ããã§ã const EVP_CIPHER *enc
ã¯ãç§å¯ããŒãä¿åããåã«æå·åããããã®æå·åã¢ã«ãŽãªãºã ãžã®ãã€ã³ã¿ãŒã§ãã
ããšãã°ã EVP_aes_256_cbc()
ã¯ããCBCã«256ãããããŒãæã€AESããæå³ããŸãã
æå·åã¢ã«ãŽãªãºã ã¯ãããããã ããã€ã§ãã§ãã
ã奜ã¿ã«åãããŠéžæããŠãã ããã é¢é£ããå®çŸ©ã¯openssl/evp.h
unsigned char *kstr
ã¯ãããŒã®æå·åã®ããã®ãã¹ã¯ãŒããå«ãè¡ãžã®ãã€ã³ã¿ãŒãããã³int klen
ãã®è¡ã®é·ããåãåãããšãæ³å®ããŠããŸãã
kstr
ãšklen
å Žåããã©ã¡ãŒã¿ãŒcb
ãšu
ç¡èŠãããŸããããã§ã klen
ã®åœ¢åŒã®é¢æ°ãžã®ãã€ã³ã¿ãŒã§ãã
int cb(char *buf, int size, int rwflag, void *u);
-buf-ãã¹ã¯ãŒããæžã蟌ãããã®ãããã¡ãžã®ãã€ã³ã¿
-ãµã€ãº-æå€§ãã¹ã¯ãŒããµã€ãºïŒã€ãŸãããããã¡ãŒãµã€ãºïŒ
-rwflagã¯èªã¿åãæã¯0ãæžãèŸŒã¿æã¯1
颿°ã®å®è¡çµæã¯ããã¹ã¯ãŒãã®é·ãããŸãã¯ãšã©ãŒã®å Žåã¯0ã§ãã
äž¡æ¹ã®é¢æ°ã®void *u
ãã©ã¡ãŒã¿ãŒã¯ã远å ããŒã¿ãéä¿¡ããããã«äœ¿çšãããŸãã ããšãã°ã GUIã¢ããªã±ãŒã·ã§ã³ã®ãŠã£ã³ããŠãžã®ãã€ã³ã¿ãšããŠã
.pemãã¡ã€ã«ããããŒãããŒããã
ããŒã¯ã PEM_read_PrivateKey
ããã³PEM_read_PUBKEY
ã䜿çšããŠPEM_read_PrivateKey
PEM_read_PUBKEY
ã äž¡æ¹ã®é¢æ°ã«ã¯åããã©ã¡ãŒã¿ãŒãšæ»ãå€ããããŸãã
EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u); EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u);
ããã§ïŒ
FILE *fp
ãã¡ã€ã«èšè¿°åãéã
EVP_PKEY **x
äžæžããããæ§é
pem_password_cb *cb
ããŒåŸ©å·åãã¹ã¯ãŒããååŸãã颿°
void *u
\0
çµããããŒãã¹ã¯ãŒãã®æåå
ããŒãè§£èªããããã®ãã¹ã¯ãŒããååŸãã颿°ã®äŸã次ã«ç€ºããŸãã
int pass_cb(char *buf, int size, int rwflag, void *u) { int len; char *tmp; if (rwflag == 1) std::cout << " " << (char*)u << ": "; else std::cout << " : "; std::string pass; std::cin >> pass; if (pass.empty() || pass.length() <=0) return 0; len = pass.length(); if (len > size) len = size; memcpy(buf, pass.c_str(), len); return len; }
以äžã¯ããã¡ã€ã«ããæå·åãããŠããªãç§å¯éµãããŒãããæ¹æ³ã®äŸã§ãã
FILE *f = NULL; f = fopen(fileName.c_str(), "rb"); if (f == NULL) {
ã¡ã¢ãªããããŒãããŒããã
ããŒãŸãã¯èšŒææžã宿°ãšããŠããã°ã©ã ã«ä¿åãããšäŸ¿å©ãªå ŽåããããŸãã ãã®ãããªå Žåãã¿ã€ãBIOã®æ§é ã䜿çšã§ããŸãã ãã®æ§é ãšãã®é¢é£æ©èœã¯ã FILE
I / Oæ©èœãç¹°ãè¿ããŸãã
ããã¯ãã¡ã¢ãªããããŒãããŒãããæ¹æ³ã§ãã
const char *key = "-----BEGIN RSA PRIVATE KEY-----\n" "MIIJKAIBAAKCAgEA40vjOGzVpuJv+wIfNBQSr9U/EeRyvSy/L6Idwh799LOPIwjF\n" ..... "zkxvkGMPBY3BcSPjipuydWTt8xE8MOe0SmEcytHZ/DifwF9qyToDlTFOUN8=\n" "-----END RSA PRIVATE KEY-----"; BIO *buf = NULL; buf = BIO_new_mem_buf(key, -1); if (buf == NULL) {
èšŒææžãªã¯ãšã¹ã
ããŒãäœæã§ããããã«ãªã£ãã®ã§ãèšŒææžãäœæããæ¹æ³ãèŠãŠã¿ãŸãããã èšŒææžã¯ãèªå·±çœ²åããããèšŒææ©é¢ã«ãã£ãŠçœ²åããããšãã§ããŸãã èšŒææ©é¢ã«ãã£ãŠçœ²åãããèšŒææžãååŸããã«ã¯ãèšŒææžèŠæ±ïŒ CSR ïŒãäœæãããããèšŒææ©é¢ã«éä¿¡ããå¿
èŠããããŸãã å¿çã§ã圌ã¯çœ²åãããèšŒææžãéä¿¡ããŸãã
èªå·±çœ²åèšŒææžãŸãã¯ç¬èªã®èšŒææ©é¢ã®èšŒææžãäœæããå Žåã¯ã CSRãäœæããå¿
èŠã¯ãããŸããã èšŒææžã»ã¯ã·ã§ã³ã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸãã
äœæ
èšŒææžçœ²åèŠæ± ïŒCSRïŒã¯ãèšŒææžã®äœæè
ãèšŒææ©é¢ïŒCAïŒã«éä¿¡ããã¡ãã»ãŒãžãŸãã¯èŠæ±ã§ãããå
¬éããŒãçºè¡åœãããã³äœæè
ã®ããžã¿ã«çœ²åã«é¢ããæ
å ±ãå«ãŸããŠããŸãã
CSRãäœæããã«ã¯ã以åã«äœæããEVP_PKEY
ããŒãå¿
èŠã§ãã ããã¯ãã¹ãŠã CSRæ§é ã«ã¡ã¢ãªãå²ãåœãŠãããšããå§ãŸããŸãã
X509_REQ *req = NULL; req = X509_REQ_new(); if (req == NULL) {
X509_REQ_new
ã®é颿°ã¯X509_REQ_free
ã§ãã
次ã«ãèšŒææžã®ããŒãžã§ã³ãèšå®ããå¿
èŠããããŸãã ãã®å ŽåãããŒãžã§ã³ã¯2ã§ãã
if (X509_REQ_set_version(req, 2) != 1) {
X.509æšæºã«ããã°ããã®ããŒãžã§ã³ã¯èšŒææžããŒãžã§ã³ããã1ã€å°ããå¿
èŠããããŸãã ããªãã¡ èšŒææžããŒãžã§ã³3ã«ã¯ãçªå·2ã䜿çšããŸãã
ããã§ããªã¯ãšã¹ãäœæè
ããŒã¿ãèšå®ããŸãã æ¬¡ã®ãã£ãŒã«ãã䜿çšããŸãã
-C -2æåã®åœã³ãŒããããšãã°RU
-ST-å°åããã®å Žåã¯ã¢ã¹ã¯ã¯
-L-éœåžãåã³ã¢ã¹ã¯ã¯
-O-çµç¹ãäŸïŒ Taigasystem
-CNã¯ãã¡ã€ã³åã§ããtaigasystem.comãç§ãã¡ã®ããã«ãããŸã
ããã¯ããããã®ãã£ãŒã«ãããªã¯ãšã¹ãã§èšå®ãããæ¹æ³ã§ãã
X509_NAME *name = X509_REQ_get_subject_name(req); if (X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char *)"RU", -1, -1, 0) != 1) {
æåã«ãCSRèŠæ±æ§é ããX509_NAME
æ§é ãååŸãããã®å€ãèšå®ããããšã«æ³šæããŠãã ããã
次ã«ããã®ãªã¯ãšã¹ãã®å
¬ééµãèšå®ããå¿
èŠããããŸãã
if (X509_REQ_set_pubkey(req, key) != 1) {
æåŸã®ä»äžãã¯ããªã¯ãšã¹ãã®çœ²åã§ãã
if (X509_REQ_sign(req, key, EVP_sha256()) <= 0) {
ä»ã®OpenSSL颿°ãšã¯ç°ãªãã X509_REQ_sign
ã¯
æåããå Žåã¯1ã§ã¯ãªãããã€ãåäœã§ã®çœ²åã®ãµã€ãºããšã©ãŒã®å Žåã¯0ã
ããã§èšŒææžèŠæ±ã®æºåãã§ããŸããã
CSRããã¡ã€ã«ã«ä¿å
CSRããã¡ã€ã«ã«ä¿åããã®ã¯éåžžã«ç°¡åã§ãã ãã¡ã€ã«ãéããŠããã PEM_write_X509_REQ
颿°ãåŒã³åºãå¿
èŠããããŸãã
FILE *f = NULL; f = fopen("server.csr", "wb"); if (PEM_write_X509_REQ(f, csr) != 1) {
ãã®çµæã server.csrãã¡ã€ã«ã§æ¬¡ã®ããã¹ããååŸããŸãã
-----BEGIN CERTIFICATE REQUEST----- MIICnzCCAYcCAQEwWjELMAkGA1UEBhMCUlUxDzANBgNVBAgMBlJ1c3NpYTEPMA0G ... fbzFJ6EM00mbyr472lEXZpvdZgBCfxpkNDyp9nsiIQf0EyC05MgufOAKDT/fGQfa 4gWK -----END CERTIFICATE REQUEST-----
ãã¡ã€ã«ããCSRãããŠã³ããŒã
CSRãããŒãããã«ã¯ãæ¬¡ã®æ©èœã䜿çšããå¿
èŠããããŸãã
X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **x, pem_password_cb *cb, void *u); X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x, pem_password_cb *cb, void *u);
æåã¯ãã¡ã€ã«ããCSRãããŒããã2çªç®ã¯ã¡ã¢ãªããCSRãããŒãã§ããŸãã
颿°ããŒã¿ãã©ã¡ãŒã¿ã¯ãPEMãã¡ã€ã«ããããŒãããŒãããã®ãšäŒŒãŠããŸã ã
ãã ãã pem_password_cb
ãšu
ã¯äŸå€ãšããŠç¡èŠãããŸãã
èªèšŒ
X.509èšŒææž
X.509ã¯ã rfc2459ã§æšæºåãããASN.1èšèªã®ããªãšãŒã·ã§ã³ã®1ã€ã§ãã
X.509圢åŒã®è©³çްã«ã€ããŠã¯ã ãã¡ããšãã¡ããã芧ãã ãã ã
CSRã䜿çšããªãèšŒææžã®çæ
CSRã䜿çšããã«èšŒææžãçæã§ããŸãã ããã¯ã CAã®äœæã«åœ¹ç«ã¡ãŸãã
CSRãªãã§èšŒææžãçæããã«ã¯ã EVP_PKEY
æ§é å
ã«å
¬éããŒãšç§å¯ããŒã®ãã¢ãå¿
èŠã§ãã èšŒææžæ§é ã«ã¡ã¢ãªãå²ãåœãŠãããšããå§ããŸãã
X509 *x509 = X509_new(); if (!x509)
X509_new
ã®éã¯X509_free
ã§ãã
èšŒææžã¯CSRãªã¯ãšã¹ããšåãæ¹æ³ã§äœæãããŸããã1ã€ã ãéãããããŸããããŒãžã§ã³ãšçºè¡è
ã®ããŒã¿ã«å ããŠãèšŒææžã®ã·ãªã¢ã«çªå·ãæå®ããå¿
èŠããããŸãã
èšŒææžããŒã¿ã«ã¢ã¯ã»ã¹ããã«ã¯ãä»ã®æ©èœã䜿çšããå¿
èŠããããŸãã
X509_set_version
ã§ã¯ãªãX509_REQ_set_version
X509_get_subject_name
代ããã«X509_REQ_get_subject_name
X509_set_pubkey
代ããã«X509_REQ_set_pubkey
X509_sign
代ããã«X509_REQ_sign
ãããã£ãŠããããã®ãªããžã§ã¯ããŸãã¯ãããã®é¢æ°ã察象ãšãããªããžã§ã¯ãã®ååã§åºå¥ããããšã¯éåžžã«ç°¡åã«ãªããŸãã
ããã§ãèšŒææžã®ã·ãªã¢ã«çªå·ãèšå®ã§ããŸãã
ASN1_INTEGER *aserial = NULL; aserial = M_ASN1_INTEGER_new(); ASN1_INTEGER_set(aserial, 1); if (X509_set_serialNumber(x509, aserial) != 1) {
æ°ããèšŒææžããšã«ãæ°ããã·ãªã¢ã«çªå·ãäœæããå¿
èŠããããŸãã
次ã«ãèšŒææžã®æå¹æéãèšå®ããŸãã ããã«ã¯2ã€ã®ãã©ã¡ãŒã¿ãŒãèšå®ãããŸã-èšŒææžã®æå¹æéã®éå§ãšçµäºïŒ
if (!(X509_gmtime_adj(X509_get_notBefore(cert), 0))) {
èšŒææžã®X509_get_notBefore
ã¯ãçºè¡ãããç¬éã«ãªããŸãX509_get_notBefore
颿°ã®å€ã¯0ã§ãã èšŒææžã®å¯¿åœã¯X509_get_notAfter
颿°ã«ãã£ãŠèšå®ãããŸãã
æåŸã®ä»äžãã¯ãç§å¯éµã䜿çšããèšŒææžã®çœ²åã§ãã
EVP_PKEY *key;
ããã«ã¯è峿·±ãæ©èœããããŸãïŒ X509_sign
颿°ã¯ããã¹ãŠãããŸããã£ãå Žåã¯ãã€ãåäœã§çœ²åã®ãµã€ãºãè¿ãããšã©ãŒã®å Žåã¯0ãè¿ããŸãã ãšã©ãŒããªãå Žåã§ãã颿°ã¯ãŒããè¿ãããšããããŸãã ãããã£ãŠãããã§ã¯è¿œå ã®ãšã©ãŒãã§ãã¯ãå°å
¥ããå¿
èŠããããŸãã
CSRã䜿çšããèšŒææžã®çæ
CSRèšŒææžãçæããã«ã¯ãèšŒææžã«çœ²åããããã®CAç§å¯éµãçºè¡è
ããŒã¿ãæå®ããããã®CAèšŒææžãããã³CSRãªã¯ãšã¹ãèªäœãå¿
èŠã§ãã
èšŒææžèªäœã®äœæãšããŒãžã§ã³ãšçªå·ã®ã€ã³ã¹ããŒã«ã¯ãCSRãªãã®èšŒææžã®å Žåãšåãã§ãã CSRãªã¯ãšã¹ããããããªãã·ã£ãŒããŒã¿ãæœåºããèšŒææžã«ã€ã³ã¹ããŒã«ããå¿
èŠãããå Žåã«éããçŸããŸãã
X509_REQ *csr;
ãã®åŸãèšŒææžçºè¡è
ã®ããŒã¿ãèšå®ããå¿
èŠããããŸãã ããã«ã¯CAèšŒææžãå¿
èŠã§ãã
X509 *CAcert;
X509_set_subject_name
ã䜿çšããŠCSRããããŒã¿ãèšå®ãã X509_set_subject_name
ã䜿çšããŠCAããŒã¿ãX509_set_issuer_name
ããŠããããšãX509_set_issuer_name
ãŸãã
次ã®ã¹ãããã¯ã CSRããå
¬éããŒãååŸããŠãæ°ããèšŒææžã«ã€ã³ã¹ããŒã«ããããšã§ãã
ããŒãèšå®ããããšã«å ããŠã CSRããã®ããŒã§çœ²åããããã©ãããããã«ç¢ºèªã§ããŸãã
ããã§ãèšŒææžã®ã·ãªã¢ã«çªå·ãèšå®ã§ããŸãã
ASN1_INTEGER *aserial = NULL; aserial = M_ASN1_INTEGER_new(); ASN1_INTEGER_set(aserial, 1); if (X509_set_serialNumber(cert, aserial) != 1) {
æåŸã®ä»äžãã¯ã CAç§å¯éµã䜿çšããŠèšŒææžã«çœ²åããããšã§ãã
EVP_PKEY *CAkey;
æ°ããèšŒææžã«çœ²åãããšãæºåãæŽããŸãã
X.509èšŒææžã®ä¿å
ä¿åã¯éåžžã«ç°¡åã§ãã
X509 *cert; ... FILE *f = NULL; f = fopen("server.crt", "wb"); if (!PEM_write_X509(f, cert)) {
X.509èšŒææžãããŠã³ããŒããã
ããŠã³ããŒãã¯2ã€ã®æ©èœã䜿çšããŠè¡ãããŸãã
X509 *PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u); X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
ãã©ã¡ãŒã¿ã¯äžã§èª¬æãããŸã ã
ãããã¯ãŒã¯éš
ã客æ§
SSLãœã±ããã䜿çšãããã¹ããžã®æ¥ç¶ã¯ãéåžžã®TCPæ¥ç¶ãšå€§å·®ãããŸããã
ãŸãããµãŒããŒãžã®TCPæ¥ç¶ãäœæããå¿
èŠããããŸãã
次ã«ãã¯ã©ã€ã¢ã³ãSSLã³ã³ããã¹ããäœæããå¿
èŠããããŸãã
const SSL_METHOD *method = SSLv23_client_method(); SSL_CTX *ctx = NULL; ctx = SSL_CTX_new(method); if (ctx == NULL)
次ã«ãåä¿¡ãããœã±ãããSSLæ§é ã«ã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã ã³ã³ããã¹ãããååŸãããŸãã
SSL *ssl = SSL_new(ctx); if (ssl == NULL) {
æåŸã®ä»äžãã¯æ¥ç¶ãã®ãã®ã§ãã
if (SSL_connect(ssl) != 1) {
ããŒã¿ã®èªã¿åã
SSLãœã±ããããããŒã¿ãèªã¿åãã«ã¯ã次ã®é¢æ°ã䜿çšããå¿
èŠããããŸãã
int SSL_read(SSL *ssl, void *buf, int num);
SSLæ§é ã«ãã€ã³ãããããœã±ããããããŒã¿ããããã¡ã«èªã¿èŸŒã¿ãŸãã ãœã±ãããããã¡ãŒã«èªã¿èŸŒãããŒã¿ããããã©ããã調ã¹ãå¿
èŠãããå Žåã¯ã颿°ã䜿çšã§ããŸãã
int SSL_pending(const SSL *ssl);
ããªãã¡ èªã¿åãã«ã¯ãæ¬¡ã®æ§æã䜿çšã§ããŸãã
const int size = SSL_pending(ssl); char *buf = new char[size]; memset(buf, 0, size); if (SSL_read(ssl, buf, size) <= 0) {
ãã®çµæããã§ã«ãã³ãŒããããããŒã¿ããããã¡ã«æ ŒçŽãããŸãã
ããŒã¿èšé²
èšé²ããã«ã¯ã次ã®é¢æ°ã䜿çšããŸãã
int SSL_write(SSL *ssl, const void *buf, int num);
å
¥åæã«ã圌女ã¯èšé²ããSSLæ§é äœãžã®ãã€ã³ã¿ãŒãããŒã¿èªäœãããã³ãã®ãµã€ãºãåãåããŸãã
ãã®ãããªã¬ã³ãŒãã®äŸã次ã«ç€ºããŸãã
char buf[] = "12345678" if (SSL_write(ssl, buf, strlen(buf)) <= 0) {
ãµãŒããŒ
ãµãŒããŒéšåã¯ã¯ã©ã€ã¢ã³ãéšåã«äŒŒãŠããŸã-SSLã³ã³ããã¹ããå¿
èŠã§ãããã¬ã³ãŒããèªã¿åãããã®åãæ©èœãåããŠããŸãã éãã¯ããµãŒããŒãã¯ã©ã€ã¢ã³ãã«èšŒææžãæäŸããããã«ã³ã³ããã¹ããæºåããã¯ã©ã€ã¢ã³ããšã®ãã³ãã·ã§ã€ã¯ãæŽçããå¿
èŠãããããšã§ãã
ã³ã³ããã¹ããæºåããããšããå§ããŸãããã
const SSL_METHOD *method = SSLv23_server_method(); SSL_CTX *ctx = NULL; ctx = SSL_CTX_new(method); if (ctx == NULL) {
ãã®ããã¥ã¡ã³ãã§ã¯ã SSLv23_server_method
ãéžæãããšãã¯ã©ã€ã¢ã³ãããµããŒããããããã³ã«ã®æãå®å
šãªããŒãžã§ã³ãã©ã€ãã©ãªãåå¥ã«æ±ºå®ã§ããããšãSSLv23_server_method
ãŸãã
ç¹å®ã®ããŒãžã§ã³ãæå¹ãŸãã¯ç¡å¹ã«ããããŸãã¯ä»ã®èšå®ã倿Žããå Žåã¯ã SSL_set_options
颿°ã䜿çšã§ããŸãã ãã®ããã®ããã¥ã¡ã³ãã¯ããã«ãããŸã ã
X.509èšŒææžã® ããŠã³ããŒããšããŒã®èªã¿èŸŒã¿ã«ã€ããŠå°ãåã«ç¢ºèªããããããããã®æ§é ãæ¢ã«ããã€ããããšèããŠããŸãã
ãµãŒããŒã³ã³ããã¹ãã®èšŒææžãšèšŒææžããŒãã€ã³ã¹ããŒã«ããŸãã
X509 *serverCert;
ãµãŒããŒã¯çä¿¡æ¥ç¶ãåãå
¥ããæºåãã§ããŠããŸãã éåžžã®accept
ã ãã®é¢æ°ããåãåã£ããœã±ããã«èå³ããããŸãã
ãŸãããã®ãããªãœã±ããããšã«ãæ°ããSSLæ§é ãå¿
èŠã§ãã
SSL *ssl = NULL; ssl = SSL_new(ctx); if (ssl == NULL) {
次ã«ããã®æ§é ã«ãœã±ãããã€ã³ã¹ããŒã«ããŸãã
int sock;
ãã³ãã·ã§ã€ã¯ã¡ã«ããºã èªäœïŒ
if (SSL_accept(ssl) != 1) {
次ã®ç¹ã«æ³šæãã䟡å€ããããŸãã䜿çšããŠãããœã±ãããéãããã¯ã¢ãŒãã®å Žåããã³ãã·ã§ã€ã¯ã¯æåã¯æ©èœããŸããã ãã®å Žåãæ»ãå€ã ãã§ãªããšã©ãŒã³ãŒãã確èªããå¿
èŠããããŸãã
int ret = SSL_accept(ssl); if (ret == 0) {
- .
äœæ¥äŸ
:
mkdir build cd build cmake .. make
æã¡äžã
(build) :
./openssl_api
ca.crt â
.
,
cppurl --cacert ca.crt -v https://127.0.0.1:5566 -H "Host: taigasystem.com"
CA , -v . -H "Host: taigasystem.com" , GET - Host. , 404- .
curl
curl ( ):
$ curl --cacert ca.crt -v https://127.0.0.1:5566 -H "Host: taigasystem.com" * Rebuilt URL to: https://127.0.0.1:5566/ * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 5566 (#0) * found 1 certificates in ca.crt * found 700 certificates in /etc/ssl/certs * ALPN, offering http/1.1 * SSL connection using TLS1.2 / RSA_AES_128_GCM_SHA256 * server certificate verification OK * server certificate status verification SKIPPED * common name: 127.0.0.1 (matched) * server certificate expiration date OK * server certificate activation date OK * certificate public key: RSA * certificate version: #3 * subject: C=RU,CN=127.0.0.1,L=Moscow,O=Taigasystem,ST=Moscow * start date: Mon, 28 Aug 2017 07:36:42 GMT * expire date: Thu, 27 Aug 2020 07:36:42 GMT * issuer: C=RU,CN=127.0.0.1,L=Moscow,O=Taigasystem,ST=Moscow * compression: NULL * ALPN, server did not agree to a protocol > GET / HTTP/1.1 > Host: taigasystem.com > User-Agent: curl/7.47.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.4.6 (Ubuntu) < Date: Mon, 28 Aug 2017 07:39:18 GMT < Content-Type: text/html; charset=utf-8 < Transfer-Encoding: chunked < Connection: keep-alive < Vary: Accept-Language, Cookie < X-Frame-Options: SAMEORIGIN < Content-Language: ru < Strict-Transport-Security: max-age=604800 < ....
: -, ; -, .
curl () :
$ ./openssl_api OpenSSL 'curl --cacert ca.crt -v https://127.0.0.1:5566 -H "Host: taigasystem.com" ' BIGNUM BIGNUM RSA EVP . : 512 BIGNUM BIGNUM RSA EVP CSR . : 512 . : 512 ca.crt SSL 5566 taigasystem.com 443 taigasystem.com[188.225.73.237]:443 SSL SSL taigasystem.com:443 / GET / HTTP/1.1 Host: taigasystem.com User-Agent: curl/7.47.0 Accept: */* HTTP/1.1 200 OK Server: nginx/1.4.6 (Ubuntu) Date: Mon, 28 Aug 2017 07:39:18 GMT Content-Type: text/html; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Vary: Accept-Language, Cookie X-Frame-Options: SAMEORIGIN Content-Language: ru Strict-Transport-Security: max-age=604800 ...
ããªãã¡ , GET - (curl) .
åç
§è³æ
tomasloh