在OS X上的Xcode中使用AES/GCM时编译错误

Compile error when using AES/GCM in Xcode on OS X

本文关键字:AES GCM 错误 编译 OS 上的 Xcode      更新时间:2023-10-16

我使用OS X 10.10与Xcode 7 beta 2。我想使用OpenSSL的AES/GCM。我想从一个例子开始,所以我从OpenSSL wiki上取了一个。代码如下:

代码无法编译。看起来编译器找不到以下内容:

  • EVP_aes_256_gcm
  • EVP_CTRL_GCM_SET_IVLEN
  • EVP_CTRL_GCM_GET_TAG

我认为缺少涉及GCM模式的项目。我该怎么办?有没有办法更新我的库或我没有导入的东西?


下面是我的代码:
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/aes.h>
void handleErrors()
{
}
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
            int aad_len, unsigned char *key, unsigned char *iv,
            unsigned char *ciphertext, unsigned char *tag)
{
    EVP_CIPHER_CTX *ctx;
    int len;
    int ciphertext_len;

    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
    /* Initialise the encryption operation. */
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
        handleErrors();
    /* Set IV length if default 12 bytes (96 bits) is not appropriate */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
        handleErrors();
    /* Initialise key and IV */
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
    /* Provide any AAD data. This can be called zero or more times as
     * required
     */
    if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
        handleErrors();
    /* Provide the message to be encrypted, and obtain the encrypted output.
     * EVP_EncryptUpdate can be called multiple times if necessary
     */
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;
    /* Finalise the encryption. Normally ciphertext bytes may be written at
     * this stage, but this does not occur in GCM mode
     */
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
    ciphertext_len += len;
    /* Get the tag */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
        handleErrors();
    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);
    return ciphertext_len;
}
int main()
{
}

我认为缺少涉及GCM模式的项目。我该怎么办?有没有办法更新我的库或我没有导入的东西?

OS X提供OpenSSL 0.9.8。它现在非常贫乏,缺乏大多数EC的东西,TLS 1.1, TLS 1.2,对客户端证书的良好支持等等。2015年12月,它将进入生命终结期。

你应该做的是下载并安装OpenSSL 1.0.2。从OpenSSL Sources和Tarballs下载。解压缩它,然后(大部分来自OpenSSL的编译和安装):

cd openssl-1.0.2
export KERNEL_BITS=64
./config no-ssl2 no-ssl3 enable-ec_nistp_64_gcc_128 --openssldir=/usr/local/ssl/macosx-x64/
make
make test
sudo make install

您必须手动添加64位体系结构的enable-ec_nistp_64_gcc_128,因为Configure不能自己确定它。

然后,执行dclean,并可选地构建32位:

export KERNEL_BITS=32
make clean && make dclean
./config no-ssl2 no-ssl3 --openssldir=/usr/local/ssl/macosx-x86/
make
make test
sudo make install

上面省略了shared。这是因为Apple链接器总是使用共享对象,即使您尝试指定静态存档。共享库也会给你带来麻烦,因为苹果版本的dylib会在你的版本之前被找到(除非你使用DYLD_LIBRARY_PATH或RPATHs之类的技巧)。

您还应该考虑添加no-comp,因为我们知道压缩在某些上下文中会泄漏信息。CRIME和BREACH是信息泄露的两种表现形式。

最后,您应该而不是构建fat库。事实上,构建系统不允许添加-arch i386 -arch x86_64(需要手动修改Makefile.org)。它破坏了ar命令IIRC。如果您可以构建一个fat库,或者使用lipo来创建一个,那么opensslconf.h对于其中一个平台来说是不正确的。

使用Xcode Build Settings设置x86_64:

  • 始终搜索用户路径:NO
  • 标题搜索路径:/usr/local/ssl/macosx-x64/include
  • 库搜索路径:/usr/local/ssl/macosx-x64/lib

并使用这些Xcode Build Settings设置i386:

  • 始终搜索用户路径:NO
  • 标题搜索路径:/usr/local/ssl/macosx-x86/include
  • 库搜索路径:/usr/local/ssl/macosx-x86/lib

一定要指定libcrypto.a库,否则会得到链接器错误。这在Xcode下并不容易/直观。关于这一点,请参阅如何在Xcode中"添加现有框架"?