Fenying

Angus’ Home.


02 Dec 2015

Visual Studio 2015 中使用 OpenSSL

该文章迁移自作者的旧博客站点。
源地址:http://fenying.blog.163.com/blog/static/102055993201511182659120

在 Visual Studio 2015 中使用 OpenSSL 的记录。

1. 编译

编译 OpenSSL 没什么难度,直接命令行就可以搞定。不过要注意一点细节。

  1. 官网下载 OpenSSL-1.0.0s.tar.gz

  2. 安装 Perl For Windows,用于生产 mak 脚本,安装一个 ActivePerl 即可。

  3. 在开始菜单打开 VS2015 x86 本机工具命令提示符。(64位的也差不多,参考 INSTALL.w64)

  4. 先把 PERL 安装目录写入 PATH。

    SET PATH=%PATH%;PERL安装目录\site\bin;PERL安装目录\bin
    
  5. 执行configure,注意 –prefix 是输出目录。

    perl Configure VC-WIN32 no-asm --prefix=x:/openssl
    
  6. 接下来先不要急着编译,最重要的是先修改生成的 .mak 文件。因为 .mak 脚本强制把 C 编译警告当成错误处理,这会导致编译失败。

    方法是打开 ms/ntdll.mak,修改第 20 行,把 /WX 去掉。

    如果你要编译静态库,那么则应该修改 ms/nt.mak,修改方法一样。

    注意,如果要编译 DEBUG 版本,那么在 ms/ntdll.mak (或 ms/nt.mak)的第 20 行处,给 /MD(或/MT)后面加一个d,变成 /MDd(或 /MTd),即可。

  7. 打开 e_os.h,跳到 319 行,把这一行

    #    if _MSC_VER>=1300
    

    替换成如下内容并保存。否则会导致链接错误,因为 VC2015 中标准IO流的定义被修改了。

    #    if _MSC_VER>=1400
    _ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
    #        define stdin  (__acrt_iob_func(0))
    #        define stdout (__acrt_iob_func(1))
    #        define stderr (__acrt_iob_func(2))
    #    elif _MSC_VER>=1300
    
  8. 现在,开始编译。

    编译静态链接库

    nmake -f ms\nt.mak
    nmake -f ms\nt.mak install
    nmake -f ms\nt.mak clean
    

    编译动态链接库

    nmake -f ms\ntdll.mak
    nmake -f ms\ntdll.mak install
    nmake -f ms\ntdll.mak clean
    
  9. 测试代码,如果遇到报错

    OPENSSL_Uplink(006E9000,08): no OPENSSL_Applink
    

    则包含文件

    #include <openssl/applink.c>
    

2. 测试

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/applink.c>
#include <openssl/md5.h>
#include <openssl/sha.h>

#define OPENSSLKEY	"test.key"
#define PUBLICKEY	"test_pub.key"

typedef unsigned char			byte_t;

byte_t *rsaEncrypt(byte_t *inputData, size_t *inputLength, byte_t *pBuffer, size_t bufLength, char *priKeyPath) {

    RSA *pRSA;
    FILE *hFile;
    size_t lenRSA;

    if ((hFile = fopen(priKeyPath, "r")) == NULL)
        return NULL;

    if ((pRSA = PEM_read_RSA_PUBKEY(hFile, NULL, NULL, NULL)) == NULL)
        return NULL;

    lenRSA = RSA_size(pRSA);

    if (*inputLength > lenRSA - RSA_PKCS1_PADDING_SIZE || bufLength < lenRSA)
        return NULL;

    memset(pBuffer, 0, lenRSA);

    if ((lenRSA = RSA_public_encrypt(*inputLength, inputData, pBuffer, pRSA, RSA_PKCS1_PADDING)) == -1) {
        return NULL;
    }

    *inputLength = lenRSA;

    RSA_free(pRSA);
    fclose(hFile);
    return pBuffer;
}

byte_t *rsaDecrypt(byte_t *inputData, size_t inputLength, byte_t *pBuffer, size_t bufLength, char *path_key) {

    RSA *pRSA;
    FILE *hFile;
    int lenRSA;

    if ((hFile = fopen(path_key, "r")) == NULL)
        return NULL;

    if ((pRSA = PEM_read_RSAPrivateKey(hFile, NULL, NULL, NULL)) == NULL)
        return NULL;

    lenRSA = RSA_size(pRSA);

    if (inputLength != lenRSA)
        return NULL;

    memset(pBuffer, 0, lenRSA);

    if (RSA_private_decrypt(lenRSA, inputData, pBuffer, pRSA, RSA_PKCS1_PADDING) < 0)
        return NULL;

    RSA_free(pRSA);
    fclose(hFile);
    return pBuffer;
}

int main(int argc, char** argv) {
    char *pData = "Hello RSA, This is a test.";
    MD5_CTX md5Data;
    SHA_CTX sha1Data;
    byte_t encBuf[512], decBuf[512];
    size_t lenInput;
    int i;
    printf("Input Data:%s\n", pData);

    /* RSA */

    lenInput = strlen(pData);

    rsaEncrypt((byte_t*)pData, &lenInput, encBuf, sizeof(encBuf), PUBLICKEY);
    printf("after encrypt[%lu]:%s\n", lenInput, encBuf);

    rsaDecrypt(encBuf, lenInput, decBuf, sizeof(decBuf), OPENSSLKEY);
    printf("after decrypt:%s\n", decBuf);

    /* MD5 */

    lenInput = strlen(pData);

    MD5_Init(&md5Data);

    MD5_Update(&md5Data, pData, lenInput);
    MD5_Final(encBuf, &md5Data);

    printf("MD5: ");
    for (i = 0; i < 16; i++)
        printf("%02x", encBuf[i]);
    putchar('\n');

    /* SHA-1 */

    lenInput = strlen(pData);

    SHA1_Init(&sha1Data);

    SHA1_Update(&sha1Data, pData, lenInput);
    SHA1_Final(encBuf, &sha1Data);

    printf("SHA-1: ");
    for (i = 0; i < 20; i++)
        printf("%02x", encBuf[i]);
    putchar('\n');

    return 0;
}

3. 参考文献

该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/post/2015/12/02/using-openssl-with-vs2015/

comments powered by Disqus