function ca_chain!(context::SSLContext, crt_file, key_file) res = ccall((:SSL_CTX_use_certificate_file, libssl), Cint, (Ptr{Cvoid}, Cstring, Cint), context.ptr, crt_file, SSL_FILETYPE_PEM) if res <= 0 @error res end res = ccall((:SSL_CTX_use_PrivateKey_file, libssl), Cint, (Ptr{Cvoid}, Cstring, Cint), context.ptr, key_file, SSL_FILETYPE_PEM) if res <= 0 @error res end if ccall((:SSL_CTX_check_private_key, libssl), Cint, (Ptr{Cvoid}, ), context.ptr) != 1 @error "Private and certificate is not matching" end return nothing end get_peer_certificate(client::SSLClient) = ccall((:SSL_get_peer_certificate, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), client.ssl) verify_certificate(client::SSLClient) = ccall((:SSL_get_verify_result, libssl), Clong, (Ptr{Cvoid},), client.ssl) function X509_get_serialNumber(X509) asn_ptr = ccall((:X509_get_serialNumber, libssl), Ptr{Cvoid}, (Ptr{Cvoid},), X509) res = Ref{Clong}(0) # TODO: check return value (1:ok) # TODO: Move to own func and call it n = ccall((:ASN1_INTEGER_get_int64, libssl), Cint, (Ref{Clong},Ptr{Cvoid}), res, asn_ptr) res[] end function X509_digest(X509; md_type = EVP_sha1()) len = Ref{Cint}(0) md = zeros(UInt8, EVP_MAX_MD_SIZE) res = ccall((:X509_digest, libssl), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ref{Cuchar}, Ref{Cint}), X509, md_type, md, len) == 1 !res && throw("Error") md[1:len[]] end digest_to_string(d::Array{UInt8}) = join(string.(d, base = 16), ":") digest_to_string_62(d::Vector{T}) where T = join(string.(reinterpret(UInt32, d), base = 62), ":")