본문 바로가기
프로그래밍/C++ rest(Casablanca)

C++] cpprestSDK(Casablanca) https(ssl) 적용방법.

by Hwan2 2020. 7. 16.
728x90
반응형

이 글을 읽기 전 boost.asio의 ssl적용법에 대해 궁금하신 분들은 https://hwan-shell.tistory.com/240?category=703822를 참고해주세요.

openssl 설치가 안되신 분들을 설치를 해주세요.


1. http_listener_config

listener 클래스에서는 listener에 대한 설정을 할 수 있도록 도와주는 http_listener_config를 제공해줍니다.

이것에 대한 정보는 https://hwan-shell.tistory.com/237?category=868199에 잘 설명해 놨습니다.

http_listener_config에서 제공하는 함수중에는 set_ssl_context_callback() 함수가 있습니다.


인자로는 boost::asio::ssl::context를 받습니다.


서버의 private.key와 certificate를 만드는 방법은 다음과 같습니다.



2. private.key & certificate

  • root private key

$ openssl genrsa -out rootca.key 2048

※ https 통신에는 일일히 인증서에 대한 암호입력을 하지 않아도 되기 때문에 -'des3'을 추가하지 않습니다.

또한 저렇게 생성된 key에는 public.key와 private.key가 합쳐진 상태입니다.

저 상태에서 public.key만 따로 빼는 명령어도 있지만 boost에선 필요없기 때문에 생략하겠습니다.


  • root certificate based on private key

$ openssl req -x509 -new -nodes -key rootca.key -days 20000 -out rootca.crt

인증서 생성.


  • Diffie-Hellman

$ openssl dhparam -out dh2048.pem 2048

DH암호 알고리즘 생성.



3. server.cpp 에 적용.

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;

int main(){
    http_listener_config listen_config;
    listen_config.set_ssl_context_callback([](boost::asio::ssl::context &ctx)
    {

        ctx.set_options(
            boost::asio::ssl::context::default_workarounds
            | boost::asio::ssl::context::no_sslv2
            | boost::asio::ssl::context::no_tlsv1
            | boost::asio::ssl::context::no_tlsv1_1
            | boost::asio::ssl::context::single_dh_use);
        ctx.set_password_callback([](std::size_t max_length
            boost::asio::ssl::context::password_purpose purpose)
        {
           return "password";
        });
        ctx.use_certificate_chain_file("rootca.crt");
        ctx.use_private_key_file("rootca.key"boost::asio::ssl::context::pem);
        ctx.use_tmp_dh_file("dh2048.pem");
    });


    listen_config.set_timeout(utility::seconds(10));
    http_listener listener(U("https://0.0.0.0:10022"), listen_config);        //Server URL, Port 지정.
        listener.support(methods::GET, [](http_request req){
        auto j = json::value::object();
        j[U("one")] = json::value::string(U("two"));
        req.reply(status_codes::OK, j);                      //Lamda방식으로 간단하게 구현.
        });
    
    listener.open().then([&listener](){std::cout << (U("\n start!!\n"));}).wait();    //Server open
    while(true);
    listener.close();
    return 0;
    
}



set_options()에는 통신방식에 대한 정보가 들어가있습니다. ssl2와 tls1, tls1.1 은 사용하지 않겠다는 뜻입니다.

set_password_callback()은 사용자가 필요로 할 때 인증서에 대한 암호를 제공해주는 함수로 생략하셔도 됩니다.

그 후에 나오는 함수들은 인증서와 key, DH정보를 읽는 용도로 사용됩니다.


3. 결과


제가 만든 인증서가 나오는것을 확인할 수 있습니다.

하지만 공인 CA가 아닌 사설(개인이 만든)CA라 신뢰할 수 없다는 정보가 출력됩니다.



와이어샤크로 패킷을 봤을 때 전송되는 정보가 암호화된 것을 확인할 수 있으며 hello패킷을 주고받는것을 확인할 수 있습니다.


하지만 boost의 ssl한계 때문인지는 모르겠지만 중간에 인증서 교환작업은 이뤄지지 않았습니다.


재 생각엔 클라이언트도 따로 구축해서 공통된 인증서를 교환할 경우에만 인증서 교환을 하는 것 같습니다.


뭔가 좀 아쉽지만 데이터가 암호화 됬다는 사실에 만족해야겠습니다.



참고 레퍼런스




반응형

댓글


스킨편집 -> html 편집에서