2013-06-10 3 views
6

나는 클라이언트 인증서 문제로 어려움을 겪고 있으며 누군가가 나를 도울 수 있기를 바랍니다. 부스트 asio를 사용하여 클라이언트/서버 쌍을 개발하고 있지만 비특이적이되도록 노력할 것입니다. 나는 창문에 있고 openssl 1.0.1e를 사용하고있다.OpenSSL 클라이언트가 클라이언트 인증서를 보내지 않음

기본적으로 나는 클라이언트 인증서를 사용하여 클라이언트 인증을 원한다. 서버는 내 CA가 서명 한 인증서가있는 클라이언트 만 수락해야합니다. 그래서 저는 자체 서명 된 CA를 설정했습니다. 이 인증서는 두 개 더 발급되었습니다. 하나는 클라이언트 용이고 다른 하나는 서버 용입니다. 둘 다 CA에서 서명했습니다. 나는 지금까지 꽤 많은 시간을 보냈으며 나는 그것을 얻었다고 확신한다.

내 서버 쪽도 문제가 없습니다. 그것은 클라이언트 인증서를 요청하고 s_client를 사용하고 있다면 그 인증서를 모두 제공합니다. 또한 브라우저를 사용하고 루트 CA를 트러스트 된 것으로 설치 한 다음 클라이언트 인증서를 가져 오는 경우에도 마찬가지입니다.

내가 일할 수없는 유일한 점은 libssl 클라이언트입니다. 내가 디버깅 도구로하지만 같은 일이 발생 내 실제 서버에 대해이 s_server을 사용하고

$ openssl.exe s_server -servername localhost -bugs -CAfile myca.crt -cert server.crt 
-cert2 server.crt -key private/server.key -key2 private/server.key -accept 8887 -www 
-state -Verify 5 
verify depth is 5, must return a certificate 
Setting secondary ctx parameters 
Using default temp DH parameters 
Using default temp ECDH parameters 
ACCEPT 
SSL_accept:before/accept initialization 
SSL_accept:SSLv3 read client hello A 
SSL_accept:SSLv3 write server hello A 
SSL_accept:SSLv3 write certificate A 
SSL_accept:SSLv3 write key exchange A 
SSL_accept:SSLv3 write certificate request A 
SSL_accept:SSLv3 flush data 
SSL3 alert read:warning:no certificate 
SSL3 alert write:fatal:handshake failure 
SSL_accept:error in SSLv3 read client certificate B 
SSL_accept:error in SSLv3 read client certificate B 
2675716:error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a 
certificate:s3_srvr.c:3193: 
ACCEPT 

: 나는 그것이 클라이언트있는 Certficate를 전송하지 않습니다 볼 수 있듯이 그것은 항상 악수까지하는 동안 실패합니다. s_client는 동일한 인증서로 정상적으로 작동합니다. 또한 서버에서 "-Verify"를 비활성화하면 연결이 작동합니다. 따라서 클라이언트가 인증서를 보내지 않으려 고하는 것 같습니다. 그 이유가 무엇일까요?

내가 코드를 래퍼가 SSL로 부스트 ASIO를 사용하고 있기 때문에는 다음과 같습니다

SSL_CTX *ctx = m_ssl_context.impl(); 
SSL *ssl = m_ssl_socket.impl()->ssl; 
int res = 0; 
res = SSL_CTX_use_certificate_chain_file(ctx, "myca.crt"); 
if (res <= 0) { 
    // handle error 
} 
res = SSL_CTX_use_certificate_file(ctx, "testclient.crt", SSL_FILETYPE_PEM); 
if (res <= 0) { 
    // handle error 
} 
res = SSL_CTX_use_PrivateKey_file(ctx, "testclient.key", SSL_FILETYPE_PEM); 
if (res <= 0) { 
    // handle error 
} 
을 :

m_ssl_context.set_verify_mode(asio::ssl::context::verify_peer); 
m_ssl_context.load_verify_file("myca.crt"); 
m_ssl_context.use_certificate_file("testclient.crt", asio::ssl::context::pem); 
m_ssl_context.use_private_key_file("testclient.key", asio::ssl::context::pem); 

나는 또한 ASIO 무시하고 말하여 SSL 컨텍스트를 직접 액세스하는 것을 시도했다

나는 행동의 차이를 볼 수 없다. 내가 업데이트 할 수없는 매우 오래된 부스트 1.43 asio를 사용하고 있다고 언급해야한다.하지만 모든 관련 호출이 OpenSSL에 직접 또는 간접적으로 적용된다고 가정하고 서버는 그 버전으로 잘 작동하므로 내가 배제 할 수 있다고 생각한다.

클라이언트와 서버를 특정 버전으로 강제 시작하면 오류 메시지가 변경되지만 작동하지 않으며 항상 s_client 테스트와 함께 작동합니다. 나는에 게시 된 이전 버그 항목을 발견

... 
SSL_accept:SSLv3 read client key exchange A 
<<< TLS 1.0 ChangeCipherSpec [length 0001] 
    01 
<<< TLS 1.0 Handshake [length 0010], Finished 
    14 00 00 0c f4 71 28 4d ab e3 dd f2 46 e8 8b ed 
>>> TLS 1.0 Alert [length 0002], fatal unexpected_message 
    02 0a 
SSL3 alert write:fatal:unexpected_message 
SSL_accept:failed in SSLv3 read certificate verify B 
2675716:error:140880AE:SSL routines:SSL3_GET_CERT_VERIFY:missing verify 
message:s3_srvr.c:2951: 
2675716:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure:s3_pkt.c:989: 
ACCEPT 

: 내가 거기에 클라이언트와 서버 결국 사이 더 수다가 나는 오류가 예를 들어 TLSv1의로 전환하면 현재 그것은 TLSv1의

로 설정 이것에 대해 언급 한 openssl 메일 링리스트. 2 년 전에 해결 된 핸드 셰이크의 틀린 CRLF가 분명히 있습니다. 또는 그것을 가지고 있습니까?

나는 거의 일주일 동안 이것을 디버깅 해왔다. 그리고 나는 정말로 붙어있다. 누구든지 시도 할 것을 제안합니까? 여기에 위의 s_server 디버그 아웃 s_client가 같은있는 Certficate 함께 할 것 인 것이다 : 나는 ... 아이디어에서

건배, 스테판

PS 해요

$ openssl s_client -CAfile ca.crt -cert testclient.crt -key private/testclient.key -verify 2 -connect myhost:8887 

ACCEPT 
SSL_accept:before/accept initialization 
SSL_accept:SSLv3 read client hello A 
SSL_accept:SSLv3 write server hello A 
SSL_accept:SSLv3 write certificate A 
SSL_accept:SSLv3 write key exchange A 
SSL_accept:SSLv3 write certificate request A 
SSL_accept:SSLv3 flush data 
depth=1 C = DE, // further info 
verify return:1 
depth=0 C = DE, // further info 
verify return:1 
SSL_accept:SSLv3 read client certificate A 
SSL_accept:SSLv3 read client key exchange A 
SSL_accept:SSLv3 read certificate verify A 
SSL_accept:SSLv3 read finished A 
SSL_accept:SSLv3 write session ticket A 
SSL_accept:SSLv3 write change cipher spec A 
SSL_accept:SSLv3 write finished A 
SSL_accept:SSLv3 flush data 
ACCEPT 

을 ... 핸드 셰이크가 완료되고 데이터가 전송됩니다.

답변

2

많은 고통을 겪은 후에 대답은 OpenSSL의 Dave Thompson에 의해 발견되었습니다.

그 이유는 내 SSL 코드가 소켓 객체 (SSL *)를 만든 후에 OpenSSL 컨텍스트에서이 모든 함수를 호출했기 때문입니다. 즉, 모든 기능이 사실상 아무 것도 아니거나 잘못된 것을 의미합니다.

내가해야 할 일을했을 모든이었다 중 하나

1. 전화 SSL_use_certificate_file

res = SSL_use_certificate_file(ssl, "testclient.crt", SSL_FILETYPE_PEM); 
if (res <= 0) { 
    // handle error 
} 
res = SSL_use_PrivateKey_file(ssl, "testclient.key", SSL_FILETYPE_PEM); 
if (res <= 0) { 
    // handle error 
} 

(2)를 호출 CTX (누락 된 CTX를 통지) 함수

소켓을 만들기 전에 컨텍스트에 따라 CTX 함수를 호출하십시오. asio는 겉으로보기에 컨텍스트와 소켓을 나중에 생성하도록 권장했기 때문에 (이니셜 라이저 목록에서했던 것처럼) 호출은 모두 쓸모가 없었습니다.

SSL 컨텍스트 (lib OpenSSL 또는 asio에서)는 SSL 사용을 캡슐화하고 이로부터 생성 된 각 소켓은 해당 속성을 공유합니다.

의견을 보내 주셔서 감사합니다.

1

SSL_CTX_use_certificate_chain_file()은 CA 체인뿐만 아니라 클라이언트 인증서를 포함한 체인을로드하려고하므로 SSL_CTX_use_certificate_chain_file()과 SSL_CTX_use_certificate_file()을 모두 사용하지 않아야합니다. SSL_CTX_use_certificate(3)에서 :

SSL_CTX_use_certificate_chain_file() loads a certificate chain from file into ctx. The certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA.

난 당신이 사용 괜찮을해야한다고 생각에만 SSL_CTX_use_certificate_file()와 SSL_CTX_use_PrivateKey_file(), 클라이언트가 어쨌든 CA 체인에 대한 많은 걱정하지 않는.

+0

불행히도 나는 이미 생각해 낼 수있는 모든 조합을 시도해 보았습니다. 이것 하나 포함. 아무 소용이 없다. 클라이언트가 자신의 클라이언트 인증서를 신뢰하지 않고 보내지 않는 것처럼 보입니다. 이 조합을 사용하면 클라이언트는 전혀 인증서를 보내지 않습니다. 체인 파일을 사용하면 자신의 루트 CA 대신 루트 CA를 보내는 것처럼 보입니다. –

+0

루트 CA를 보내는 경우에는 CA 인증서 만있는 SSL_CTX_use_certificate_chain_file()을 호출하기 때문입니다. 클라이언트 인증서 만 포함 된 파일을 SSL_CTX_use_certificate_chain_file()에 전달할 수 있습니까? –

+0

모든 의견을 보내 주셔서 감사합니다! 매우 감사! @Remi : 이렇게하면 클라이언트가 인증서를 보내지 않습니다. 그것이 제가 설명한 첫 번째 사례입니다. 체인 파일에 CA 인증서 만 포함되어있는 경우도 마찬가지입니다. 나는 그것이 합리적이지는 않지만 어쨌든 시도하고 싶었다. –

1

서버 쪽에서 SSL_CTX_set_client_CA_list으로 전화해야한다고 생각합니다. 이렇게하면 클라이언트 인증 요청과 함께 전송 될 인증 기관 목록이 설정됩니다.

클라이언트가 요청한 경우에도 인증서가 전송되지 않습니다. 인 경우 인증서가 서버에서 보낸 CA 목록과 일치하지 않습니다.

+0

예. 이것은 완료되었습니다. 그리고 보내집니다. 불행히도 내 문제는 클라이언트에 있습니다. 내 클라이언트를 디버깅하기 위해 openssl의 s_server를 사용합니다. 그래서 제 자신의 서버는 여기 중요하지 않습니다. 그냥 괜찮다고 가정하고 단순히 s_server 테스트 도구에 연결할 수 없습니다.내가 가정해야만하는 것은 프로토콜을 올바르게 말하는 것입니다. –

+0

미안하지만, 나는 그것을 간과했다. 열쇠 파일이 정확한 것 같아요. 귀하의 s_client 명령 줄에서 그것은 private/testclient.key입니다. 코드는 단지 "testclient.key"입니다. SSL_CTX_check_private_key를 사용하여 인증서와 일치하는지 확인하고 비공개 키를 "잠금 해제"하기 위해 암호 콜백을 설치하는 것 외에는 (작동하는) 코드가 꽤 정확하게 수행합니다 : SSL_CTX_set_default_passwd_cb. – Tannin

+0

걱정할 필요가 없습니다. 입력 해 주셔서 감사합니다. 나는 여기서 완전히 망했다. certs에 관해서는, 슬프게도, 나는 그랬다. 그것들을 계속 확인하고, 파일을 diffed하고, 계속합니다. 그 커맨드 라인 차이의 이유는 단지 내가 여기에 게시 할 수있는 '의심스러운 비밀'인증서 이름을 바꿨다는 것입니다 ;-) 나는 그들이 옳다고 확신합니다. SSL_CTX_check_private_key는 true를 반환합니다. 빈 암호 키에 해당 암호 콜백이 필요합니까? –

관련 문제