EIdOSSLUnderlyingCryptoError and "Error connecting with SSL. error:14094410..."
EIdOSSLUnderlyingCryptoError and "Error connecting with SSL. error:14094410..."
我在 Delphi 10.1 Berlin on OS X 上的 Indy 组件有问题。我正在使用 TIdHTTP
通过 HTTPS 连接到网络服务。问题是从 OS X 客户端连接到服务器。当 运行ning 在 OS X 上时,我总是得到同样的错误:
Project raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting
with SSL. error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'.
我将 TIdHTTP.IOHandler
属性 设置为使用 OpenSSL:
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
在 OS X 上,当我在终端中 运行 这个命令时:
openssl version
它returnsOpenSSL 0.9,这是OSX.
默认自带的版本
即使我使用 Homebrew 或 MacPort 安装最新版本的 OpenSSL,也无济于事。每次都给我同样的错误。
我在 VMWare 中安装了 OS X,如果有帮助的话。我还尝试了 OS X 的两个版本:Yosemite 和 El Capitan。同样的问题。
这是我使用的代码:
unit uApiClient1;
interface
uses
IdHTTP, System.JSON, IdSSLOpenSSLHeaders, System.Classes, IdCTypes,
System.SysUtils, IdSSLOpenSSL;
const
API_URL = 'https://www.myserver.com/ws.php';
WS_METHOD = 'validate_status';
type
TAPIClient = class(TObject)
function ValidateStatus(userId, deviceId: string): TJSONObject;
private
procedure PrepareHTTPObject(var IdHTTP: TIdHTTP);
end;
implementation
{ APIClient }
procedure TAPIClient.PrepareHTTPObject(var IdHTTP: TIdHTTP);
begin
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
TIdSSLIOHandlerSocketOpenSSL(IdHTTP.IOHandler).SSLOptions.Method := sslvTLSv1_2;
//
IdHTTP.Request.Accept := 'text/javascript';
IdHTTP.Request.ContentType := 'application/json';
IdHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
end;
function TAPIClient.ValidateStatus(userId, deviceId: string): TJSONObject;
var
IdHTTP: TIdHTTP;
LJSONObject: TJSONObject;
dataResult: string;
begin
LJSONObject := nil;
IdHTTP := TIdHTTP.Create(nil);
try
try
PrepareHTTPObject(IdHTTP);
dataResult := IdHTTP.Get(API_URL + format('?action=%s&user_id=%s&device_id=%s', [WS_METHOD, userId, deviceid]));
LJSONObject := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(dataResult), 0) as TJSONObject;
except
end;
finally
IdHTTP.Free;
end;
Result := LJSONObject;
end;
end.
我尝试比较由我的应用程序和 Safari 生成的 WireShark 的数据包,这是我得到的:
我的申请:
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 114
Version: TLS 1.0 (0x0301)
Random
GMT Unix Time: Aug 24, 2016 20:26:07.000000000 EEST
Random Bytes: 49c48ba758048a2429dd01ee2e390ed06eb320e5248d016d...
Session ID Length: 0
Cipher Suites Length: 46
Cipher Suites (23 suites)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016)
Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013)
Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_DHE_RSA_WITH_SEED_CBC_SHA (0x009a)
Cipher Suite: TLS_DHE_DSS_WITH_SEED_CBC_SHA (0x0099)
Cipher Suite: TLS_RSA_WITH_SEED_CBC_SHA (0x0096)
Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)
Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004)
Cipher Suite: TLS_DHE_RSA_WITH_DES_CBC_SHA (0x0015)
Cipher Suite: TLS_DHE_DSS_WITH_DES_CBC_SHA (0x0012)
Cipher Suite: TLS_RSA_WITH_DES_CBC_SHA (0x0009)
Cipher Suite: TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014)
Cipher Suite: TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011)
Cipher Suite: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008)
Cipher Suite: TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006)
Cipher Suite: TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 27
Extension: server_name
Extension: SessionTicket TLS
Type: SessionTicket TLS (0x0023)
Length: 0
Data (0 bytes)
Safari 浏览器:
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 229
Version: TLS 1.2 (0x0303)
Random
GMT Unix Time: Aug 24, 2016 20:35:07.000000000 EEST
Random Bytes: d0f0bc116fd51dff15c739bb76f7e6032a931d07e2e56a56...
Session ID Length: 0
Cipher Suites Length: 44
Cipher Suites (22 suites)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc008)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
Cipher Suite: TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (0xc012)
Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 144
Extension: server_name
Extension: elliptic_curves
Extension: ec_point_formats
Extension: signature_algorithms
Type: signature_algorithms (0x000d)
Length: 14
Signature Hash Algorithms Length: 12
Signature Hash Algorithms (6 algorithms)
Extension: next_protocol_negotiation
Type: next_protocol_negotiation (0x3374)
Length: 0
Extension: Application Layer Protocol Negotiation
Type: Application Layer Protocol Negotiation (0x0010)
Length: 48
ALPN Extension Length: 46
ALPN Protocol
Extension: status_request
Type: status_request (0x0005)
Length: 5
Certificate Status Type: OCSP (1)
Responder ID list Length: 0
Request Extensions Length: 0
Extension: signed_certificate_timestamp
Type: signed_certificate_timestamp (0x0012)
Length: 0
Data (0 bytes)
在WireShark的协议栏中,Savari的是TLSv1.2
,我的应用是TLSv1
,甚至我在代码中设置方法为sslvTLSv1_2
。
两个 SNI 都设置正确。
这是来自 WireShark 的 TLS 警报:
Secure Sockets Layer
TLSv1 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
Content Type: Alert (21)
Version: TLS 1.0 (0x0301)
Length: 2
Alert Message
Level: Fatal (2)
Description: Handshake Failure (40)
经过多日的研究,我终于找到了解决问题的方法。
为了确保应用程序使用最新版本的 OpenSSL 库,而不依赖于安装在 OS X 中,我发现我可以在应用程序包中包含已编译的 OpenSSL 库。
在我的例子中,我需要 openSSL 库的 x86 编译版本。
Homebrew 和 Macport 安装最后一个 openssl 时,编译库的 x64 版本,这就是为什么使用这个 link:
Compilation and Installation of OpenSSL libraries
我编译了 x86 版本的 openSSL 库。
接下来感谢Marco Cantu tech Blog,我发现我可以使用IdOpenSSLSetLibPath
方法来设置openssl库路径。
最后,将已编译的库与应用程序包含在同一个包中并使用此代码:
IdOpenSSLSetLibPath(ExtractFilePath(ParamStr(0)));
我得到正确版本的 openssl 库,支持 TLSv1.2
我在 Delphi 10.1 Berlin on OS X 上的 Indy 组件有问题。我正在使用 TIdHTTP
通过 HTTPS 连接到网络服务。问题是从 OS X 客户端连接到服务器。当 运行ning 在 OS X 上时,我总是得到同样的错误:
Project raised exception class EIdOSSLUnderlyingCryptoError with message 'Error connecting
with SSL. error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'.
我将 TIdHTTP.IOHandler
属性 设置为使用 OpenSSL:
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
在 OS X 上,当我在终端中 运行 这个命令时:
openssl version
它returnsOpenSSL 0.9,这是OSX.
默认自带的版本即使我使用 Homebrew 或 MacPort 安装最新版本的 OpenSSL,也无济于事。每次都给我同样的错误。
我在 VMWare 中安装了 OS X,如果有帮助的话。我还尝试了 OS X 的两个版本:Yosemite 和 El Capitan。同样的问题。
这是我使用的代码:
unit uApiClient1;
interface
uses
IdHTTP, System.JSON, IdSSLOpenSSLHeaders, System.Classes, IdCTypes,
System.SysUtils, IdSSLOpenSSL;
const
API_URL = 'https://www.myserver.com/ws.php';
WS_METHOD = 'validate_status';
type
TAPIClient = class(TObject)
function ValidateStatus(userId, deviceId: string): TJSONObject;
private
procedure PrepareHTTPObject(var IdHTTP: TIdHTTP);
end;
implementation
{ APIClient }
procedure TAPIClient.PrepareHTTPObject(var IdHTTP: TIdHTTP);
begin
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
TIdSSLIOHandlerSocketOpenSSL(IdHTTP.IOHandler).SSLOptions.Method := sslvTLSv1_2;
//
IdHTTP.Request.Accept := 'text/javascript';
IdHTTP.Request.ContentType := 'application/json';
IdHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
end;
function TAPIClient.ValidateStatus(userId, deviceId: string): TJSONObject;
var
IdHTTP: TIdHTTP;
LJSONObject: TJSONObject;
dataResult: string;
begin
LJSONObject := nil;
IdHTTP := TIdHTTP.Create(nil);
try
try
PrepareHTTPObject(IdHTTP);
dataResult := IdHTTP.Get(API_URL + format('?action=%s&user_id=%s&device_id=%s', [WS_METHOD, userId, deviceid]));
LJSONObject := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(dataResult), 0) as TJSONObject;
except
end;
finally
IdHTTP.Free;
end;
Result := LJSONObject;
end;
end.
我尝试比较由我的应用程序和 Safari 生成的 WireShark 的数据包,这是我得到的:
我的申请:
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 114
Version: TLS 1.0 (0x0301)
Random
GMT Unix Time: Aug 24, 2016 20:26:07.000000000 EEST
Random Bytes: 49c48ba758048a2429dd01ee2e390ed06eb320e5248d016d...
Session ID Length: 0
Cipher Suites Length: 46
Cipher Suites (23 suites)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016)
Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013)
Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_DHE_RSA_WITH_SEED_CBC_SHA (0x009a)
Cipher Suite: TLS_DHE_DSS_WITH_SEED_CBC_SHA (0x0099)
Cipher Suite: TLS_RSA_WITH_SEED_CBC_SHA (0x0096)
Cipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)
Cipher Suite: TLS_RSA_WITH_RC4_128_MD5 (0x0004)
Cipher Suite: TLS_DHE_RSA_WITH_DES_CBC_SHA (0x0015)
Cipher Suite: TLS_DHE_DSS_WITH_DES_CBC_SHA (0x0012)
Cipher Suite: TLS_RSA_WITH_DES_CBC_SHA (0x0009)
Cipher Suite: TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014)
Cipher Suite: TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011)
Cipher Suite: TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008)
Cipher Suite: TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006)
Cipher Suite: TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 27
Extension: server_name
Extension: SessionTicket TLS
Type: SessionTicket TLS (0x0023)
Length: 0
Data (0 bytes)
Safari 浏览器:
Handshake Protocol: Client Hello
Handshake Type: Client Hello (1)
Length: 229
Version: TLS 1.2 (0x0303)
Random
GMT Unix Time: Aug 24, 2016 20:35:07.000000000 EEST
Random Bytes: d0f0bc116fd51dff15c739bb76f7e6032a931d07e2e56a56...
Session ID Length: 0
Cipher Suites Length: 44
Cipher Suites (22 suites)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc008)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
Cipher Suite: TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (0xc012)
Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
Compression Methods Length: 1
Compression Methods (1 method)
Extensions Length: 144
Extension: server_name
Extension: elliptic_curves
Extension: ec_point_formats
Extension: signature_algorithms
Type: signature_algorithms (0x000d)
Length: 14
Signature Hash Algorithms Length: 12
Signature Hash Algorithms (6 algorithms)
Extension: next_protocol_negotiation
Type: next_protocol_negotiation (0x3374)
Length: 0
Extension: Application Layer Protocol Negotiation
Type: Application Layer Protocol Negotiation (0x0010)
Length: 48
ALPN Extension Length: 46
ALPN Protocol
Extension: status_request
Type: status_request (0x0005)
Length: 5
Certificate Status Type: OCSP (1)
Responder ID list Length: 0
Request Extensions Length: 0
Extension: signed_certificate_timestamp
Type: signed_certificate_timestamp (0x0012)
Length: 0
Data (0 bytes)
在WireShark的协议栏中,Savari的是TLSv1.2
,我的应用是TLSv1
,甚至我在代码中设置方法为sslvTLSv1_2
。
两个 SNI 都设置正确。
这是来自 WireShark 的 TLS 警报:
Secure Sockets Layer
TLSv1 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
Content Type: Alert (21)
Version: TLS 1.0 (0x0301)
Length: 2
Alert Message
Level: Fatal (2)
Description: Handshake Failure (40)
经过多日的研究,我终于找到了解决问题的方法。
为了确保应用程序使用最新版本的 OpenSSL 库,而不依赖于安装在 OS X 中,我发现我可以在应用程序包中包含已编译的 OpenSSL 库。
在我的例子中,我需要 openSSL 库的 x86 编译版本。 Homebrew 和 Macport 安装最后一个 openssl 时,编译库的 x64 版本,这就是为什么使用这个 link:
Compilation and Installation of OpenSSL libraries
我编译了 x86 版本的 openSSL 库。
接下来感谢Marco Cantu tech Blog,我发现我可以使用IdOpenSSLSetLibPath
方法来设置openssl库路径。
最后,将已编译的库与应用程序包含在同一个包中并使用此代码:
IdOpenSSLSetLibPath(ExtractFilePath(ParamStr(0)));
我得到正确版本的 openssl 库,支持 TLSv1.2