Visual Studio 2015 中使用 OpenSSL
该文章迁移自作者的旧博客站点。
源地址:http://fenying.blog.163.com/blog/static/102055993201511182659120。
源地址:http://fenying.blog.163.com/blog/static/102055993201511182659120。
在 Visual Studio 2015 中使用 OpenSSL 的记录。
1. 编译
编译 OpenSSL 没什么难度,直接命令行就可以搞定。不过要注意一点细节。
-
官网下载 OpenSSL-1.0.0s.tar.gz。
-
安装 Perl For Windows,用于生产 mak 脚本,安装一个 ActivePerl 即可。
-
在开始菜单打开 VS2015 x86 本机工具命令提示符。(64位的也差不多,参考 INSTALL.w64)
-
先把 PERL 安装目录写入 PATH。
SET PATH=%PATH%;PERL安装目录\site\bin;PERL安装目录\bin
-
执行configure,注意 –prefix 是输出目录。
perl Configure VC-WIN32 no-asm --prefix=x:/openssl
-
接下来先不要急着编译,最重要的是先修改生成的 .mak 文件。因为 .mak 脚本强制把 C 编译警告当成错误处理,这会导致编译失败。
方法是打开 ms/ntdll.mak,修改第 20 行,把 /WX 去掉。
如果你要编译静态库,那么则应该修改 ms/nt.mak,修改方法一样。
注意,如果要编译 DEBUG 版本,那么在 ms/ntdll.mak (或 ms/nt.mak)的第 20 行处,给 /MD(或/MT)后面加一个d,变成 /MDd(或 /MTd),即可。
-
打开 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
-
现在,开始编译。
编译静态链接库
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
-
测试代码,如果遇到报错
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. 参考文献
comments powered by Disqus