如何验证服务器SSL证书?

时间:2021-09-24 23:02:26

I am a newbie on SSL concept, I am trying to connect to API which has x509 mutual auth using HTTParty.

我是SSL概念的新手,我正在尝试使用HTTParty连接到具有x509相互身份验证的API。

I got client cert, client key and server cert (all are pem files).

我获得了客户端证书,客户端密钥和服务器证书(都是pem文件)。

I got it working with client cert and key and with verify: false.

我使用客户端证书和密钥,并验证:false。

Now next step is how to verify server cert also?

现在下一步是如何验证服务器证书?

HTTParty documentation link https://github.com/jnunemaker/httparty/tree/master/docs#working-with-ssl

HTTParty文档链接https://github.com/jnunemaker/httparty/tree/master/docs#working-with-ssl

class ServiceClient
  include HTTParty
  DEFAULT_HEADERS = {
    'Content-Type' => 'application/json'
  }.freeze
  base_uri 'https://example.com'
  pem File.read("#{File.expand_path('.')}/path/to/certs/cert.pem")

  def self.iframe_url(**payload)
    post(
     '/test/create',
     body: payload.to_json,
     headers: DEFAULT_HEADERS,
     verify: false
    )
  end
end

Call to service client

致电服务客户

payload = {user_id: "100", account_id: "1234"} 
ServiceClient.iframe_url(payload)

Edit:

HTTParty is not a hard requirement so solution with any http client would work for me.

HTTParty不是一个硬性要求,所以任何http客户端的解决方案都适合我。

If I remove verify: false I get below error.

如果我删除验证:false我得到以下错误。

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed

4 个解决方案

#1


2  

By default, the TLS protocol only proves the identity of the server to the client, leaving the authentication of the client to the server to the application layer, e.g., HTTP Basic authentication.

默认情况下,TLS协议仅向客户端证明服务器的身份,将客户端的身份验证留给服务器到应用程序层,例如HTTP基本身份验证。

Mutual TLS authentication refers to the client and server authenticating each other at the same time. It can be used as an alternative to HTTP Basic authentication. It's also often called certificate-based authentication.

相互TLS身份验证是指客户端和服务器同时进行身份验证。它可以用作HTTP基本身份验证的替代方法。它通常也称为基于证书的身份验证。

Looks like you're getting this error (but works with verify: false) because the server certificate isn't trusted. Is it self-signed? Or perhaps the certificate authority (CA) who issued the certificate isn't trusted in your system.

看起来您收到此错误(但与verify:false一起使用),因为服务器证书不受信任。它是自签名的吗?或者,您的系统中可能不信任颁发证书的证书颁发机构(CA)。

HTTParty is built on top of Net::HTTP, which uses OpenSSL, which gets the trusted CA certificates from the system, e.g. /etc/ssl/cert.pem. Although you could override the SSL_CERT_FILE environment variable, I don't think it's a good idea because it might impact other parts of your application. A better solution would be to pass the CA certificates to HTTParty only.

HTTParty构建于Net :: HTTP之上,后者使用OpenSSL,OpenSSL从系统获取可信CA证书,例如: /etc/ssl/cert.pem。虽然您可以覆盖SSL_CERT_FILE环境变量,但我认为这不是一个好主意,因为它可能会影响应用程序的其他部分。更好的解决方案是仅将CA证书传递给HTTParty。

I've never used HTTParty, so bear with me. But taking a quick look at the code and assuming you're using the default ConnectionAdapter, looks like you need to define both pem and ssl_ca_file options, which will define the client and CA certificate files, respectively. Also note that by doing it so, it will turn certificate verification on.

我从未使用过HTTParty,所​​以请耐心等待。但是快速查看代码并假设您正在使用默认的ConnectionAdapter,看起来您需要定义pem和ssl_ca_file选项,它们将分别定义客户端和CA证书文件。另请注意,通过这样做,它将打开证书验证。

class ServiceClient
  include HTTParty
  pem "path/to/client_cert_and_key.pem"
  ssl_ca_file "path/to/ca_certificates.pem"
end

I don't think it's related to your issue, but if your client key has a passphrase, make sure to pass it on pem(pem_contents, password).

我不认为这与您的问题有关,但如果您的客户端密钥有密码,请确保将其传递给pem(pem_contents,密码)。

HTH. Best.

#2


1  

Try as you I suppose you are using ssl certificate that you want to verify. Also it's quite easier in RestClient, I am adding snippet at the end.

试试你我想你正在使用你要验证的ssl证书。在RestClient中它也相当容易,我在最后添加片段。

class ServiceClient
  include HTTParty
  DEFAULT_HEADERS = {
    'Content-Type' => 'application/json'
  }.freeze
  base_uri 'https://example.com'
  ssl_ca_file "#{File.expand_path('.')}/path/to/certs/cert.pem"


  def self.iframe_url(**payload)
    post(
     '/test/create',
     body: payload.to_json,
     headers: DEFAULT_HEADERS,
    )
  end
end

Rest Client solution:

Rest Client解决方案:

client = RestClient::Resource.new('https://example.com/',
                              :ssl_client_cert => p12.certificate,
                              :ssl_client_key => p12.key,
                              :verify_ssl => OpenSSL::SSL::VERIFY_NONE)

#3


1  

This should solve the problem:

这应该解决问题:

RestClient::Resource.new(
  'https://example.com',
  :ssl_client_cert  =>  OpenSSL::X509::Certificate.new(File.read("cert.pem")),
  :ssl_client_key   =>  OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
  :ssl_ca_file      =>  "ca_certificate.pem",
  :verify_ssl       =>  OpenSSL::SSL::VERIFY_PEER
).get

Ref: https://github.com/rest-client/rest-client

#4


-1  

Use " OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE"

使用“OpenSSL :: SSL :: VERIFY_PEER = OpenSSL :: SSL :: VERIFY_NONE”

In your code , maybe look like to:

在您的代码中,可能看起来像:

    class ServiceClient
      include HTTParty
      OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
      {...your code...}
    end

#1


2  

By default, the TLS protocol only proves the identity of the server to the client, leaving the authentication of the client to the server to the application layer, e.g., HTTP Basic authentication.

默认情况下,TLS协议仅向客户端证明服务器的身份,将客户端的身份验证留给服务器到应用程序层,例如HTTP基本身份验证。

Mutual TLS authentication refers to the client and server authenticating each other at the same time. It can be used as an alternative to HTTP Basic authentication. It's also often called certificate-based authentication.

相互TLS身份验证是指客户端和服务器同时进行身份验证。它可以用作HTTP基本身份验证的替代方法。它通常也称为基于证书的身份验证。

Looks like you're getting this error (but works with verify: false) because the server certificate isn't trusted. Is it self-signed? Or perhaps the certificate authority (CA) who issued the certificate isn't trusted in your system.

看起来您收到此错误(但与verify:false一起使用),因为服务器证书不受信任。它是自签名的吗?或者,您的系统中可能不信任颁发证书的证书颁发机构(CA)。

HTTParty is built on top of Net::HTTP, which uses OpenSSL, which gets the trusted CA certificates from the system, e.g. /etc/ssl/cert.pem. Although you could override the SSL_CERT_FILE environment variable, I don't think it's a good idea because it might impact other parts of your application. A better solution would be to pass the CA certificates to HTTParty only.

HTTParty构建于Net :: HTTP之上,后者使用OpenSSL,OpenSSL从系统获取可信CA证书,例如: /etc/ssl/cert.pem。虽然您可以覆盖SSL_CERT_FILE环境变量,但我认为这不是一个好主意,因为它可能会影响应用程序的其他部分。更好的解决方案是仅将CA证书传递给HTTParty。

I've never used HTTParty, so bear with me. But taking a quick look at the code and assuming you're using the default ConnectionAdapter, looks like you need to define both pem and ssl_ca_file options, which will define the client and CA certificate files, respectively. Also note that by doing it so, it will turn certificate verification on.

我从未使用过HTTParty,所​​以请耐心等待。但是快速查看代码并假设您正在使用默认的ConnectionAdapter,看起来您需要定义pem和ssl_ca_file选项,它们将分别定义客户端和CA证书文件。另请注意,通过这样做,它将打开证书验证。

class ServiceClient
  include HTTParty
  pem "path/to/client_cert_and_key.pem"
  ssl_ca_file "path/to/ca_certificates.pem"
end

I don't think it's related to your issue, but if your client key has a passphrase, make sure to pass it on pem(pem_contents, password).

我不认为这与您的问题有关,但如果您的客户端密钥有密码,请确保将其传递给pem(pem_contents,密码)。

HTH. Best.

#2


1  

Try as you I suppose you are using ssl certificate that you want to verify. Also it's quite easier in RestClient, I am adding snippet at the end.

试试你我想你正在使用你要验证的ssl证书。在RestClient中它也相当容易,我在最后添加片段。

class ServiceClient
  include HTTParty
  DEFAULT_HEADERS = {
    'Content-Type' => 'application/json'
  }.freeze
  base_uri 'https://example.com'
  ssl_ca_file "#{File.expand_path('.')}/path/to/certs/cert.pem"


  def self.iframe_url(**payload)
    post(
     '/test/create',
     body: payload.to_json,
     headers: DEFAULT_HEADERS,
    )
  end
end

Rest Client solution:

Rest Client解决方案:

client = RestClient::Resource.new('https://example.com/',
                              :ssl_client_cert => p12.certificate,
                              :ssl_client_key => p12.key,
                              :verify_ssl => OpenSSL::SSL::VERIFY_NONE)

#3


1  

This should solve the problem:

这应该解决问题:

RestClient::Resource.new(
  'https://example.com',
  :ssl_client_cert  =>  OpenSSL::X509::Certificate.new(File.read("cert.pem")),
  :ssl_client_key   =>  OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
  :ssl_ca_file      =>  "ca_certificate.pem",
  :verify_ssl       =>  OpenSSL::SSL::VERIFY_PEER
).get

Ref: https://github.com/rest-client/rest-client

#4


-1  

Use " OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE"

使用“OpenSSL :: SSL :: VERIFY_PEER = OpenSSL :: SSL :: VERIFY_NONE”

In your code , maybe look like to:

在您的代码中,可能看起来像:

    class ServiceClient
      include HTTParty
      OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
      {...your code...}
    end