Indy 10和OpenSSL

6
我最近将我的Delphi 7升级到Delphi XE2,对它还不熟悉。我使用Indy 10与OpenSSL一起接收HTTP内容。它完美地运行着,我想分享我的程序给其他人。但是我发现没有OpenSSL库,我的程序在其他电脑上无法运行。没有异常、错误等提示我缺少DLL文件。我以为Indy10要么有本地的SSL支持,要么至少会在编译后使用资源中的DLL,这样就可以移植了。我有两个问题:
1)我该如何让用户知道他/她缺少OpenSSL库?(我的朋友报告说没有OpenSSL DLL时也没有异常、错误等提示。)
2)是否有可能让Indy10从资源中读取OpenSSL库?
2个回答

11

Indy本身不支持SSL。它实现了一个灵活的IOHandler架构,允许任何SSL实现插入到Indy中。Indy自己实现了基于OpenSSL的IOHandler类(计划在未来支持MS CryptoAPI)。例如,SecureBlackbox为其自己的SSL引擎提供了一个Indy IOHandler类。

在大多数平台上,OpenSSL是通过外部DLL使用的,而这些DLL不能从资源中使用。Indy不随OpenSSL DLL一起提供,因为国际进出口法限制了OpenSSL加密,因此出口国家和地区的操作系统供应商必须拥有特殊许可证才能出售OpenSSL DLL,否则最终用户必须本地下载/编译OpenSSL。这就使Indy在使用OpenSSL方面具有“可移植性”,即Indy使用在Indy之外预先安装的任何OpenSSL DLL,无论是操作系统还是您的应用程序自己的安装文件夹中都可以。

唯一与Indy相关的例外情况是在iOS上使用的OpenSSL,因为iOS设备不允许使用第三方动态库,所以必须静态使用OpenSSL。

如果要在其他平台上静态使用OpenSSL并与Indy配合使用,您需要自己编译/获取静态版本的OpenSSL,并将其添加到您的项目中,然后重新编译Indy以启用其STATICLOAD_OPENSSL定义(目前仅为iOS定义),最后在代码的uses子句中包含IdSSLOpenSSLHeaders_static.pas单元以钩接必要的支持代码。请注意,这仅受新发布的Indy 10.6版本支持。

如果您觉得这太麻烦,那么可以使用与Indy兼容的第三方SSL实现,例如SecureBlackbox,或编写自己的IOHandler类以满足您的需要。

1) 如果在套接字操作期间无法正确加载 OpenSSL,则 Indy 会引发异常。因此,很有可能这些异常被捕获并吞没了,而您没有机会向用户报告它们。如果您不想依赖此功能,则可以在开始套接字工作之前手动调用 Indy 的 IdSSLOpenSSLHeaders.pas 单元中的 Load() 函数。如果 OpenSSL 尚未加载到内存中,Load() 将加载它。如果Load() 失败,则可以调用该单元中的 WhichFailedToLoad() 函数以找出失败的原因。

2) 不,不可能从资源中使用 OpenSSL(除非进行一些非常严重的低级技巧)。


1
为什么Indy没有原生实现SSL?由于需要这些外部dll,每个人都受到了影响。 - Mehmet Fide
2
实现本地SSL将是一项重大的工作。既然其他人已经提供了实现,为什么要浪费时间和精力呢?无论如何,我确实提到我们计划创建一个IOHandler包装器来使用CryptoAPI,这样就可以解决Windows上的DLL和导入/导出问题,因为它是内置于操作系统中的。在其他平台上,通常使用OpenSSL。 - Remy Lebeau
2
其他流行的库,如ICS和Synapse,也没有本地实现SSL。它们依赖于像OpenSSL和其他库这样的外部库。 - Remy Lebeau
@Remy,Indy是否已经实现了CryptoAPI的包装器? - Nasreddine Galfout
@NasreddineGalfout,还没有。它仍在待办事项清单上。 - Remy Lebeau

1

这个应该可以工作,但我需要编辑实际的 Indy 源代码,而我不知道从哪里开始。 - Ben
1
为什么要编辑Indy代码?应用程序只会加载dll一次,因此如果在调用indy之前加载它,那么就不会有问题。 - Cesar Romero
我不确定这是否可能,如果Indy在我执行初始化之前已经调用LoadLibrary,那会怎样呢?如果Indy调用GetModuleHandle等方法,它可能会加载库两次或类似的情况。目前还没有进行任何测试,但稍后我会测试一下看看它是否有效。 - Ben
BTMemoryModule中的BTMemoryLoadLibrary函数是否会将模块添加到进程的已加载模块列表中? - Ben
3
Indy在需要时才将OpenSSL DLL加载到内存中。Indy不使用GetModuleHandle(),而是通过LoadLibrary()加载DLL,并在不再需要时关闭它们的句柄以进行跟踪。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接