SSL_CTX_new:unable 加载 ssl2 md5 例程
SSL_CTX_new:unable to load ssl2 md5 routines
我们在 运行 使用 OpenSSL 构建的程序时遇到问题。我们遇到的具体错误是:global error: SSL Context init failed error:140A90F1:SSL routines:SSL_CTX_new:unable to load ssl2 md5 routines
.
上下文是 C library which is being wrapped by a Perl library 使用 SWIG。尝试使用 Perl 库连接到 HTTPS 地址时发生错误。
例如,这段代码会导致错误:
#These are just the imports I felt were relevant to this problem
use LWP::UserAgent;
use HTTP::Request;
use LWP::Protocol::https;
use IO::Socket::SSL;
sub test_can_connect_to_bitpay_api {
my $uri = "https://www.google.com";
my $pem = Business::OnlinePayment::BitPay::KeyUtils::bpGeneratePem();
my $sin = Business::OnlinePayment::BitPay::KeyUtils::bpGenerateSinFromPem($pem);
my $request = HTTP::Request->new(POST => $uri);
my $ua = LWP::UserAgent->new;
my $response = $ua->request($request);
ok($response->is_success, "TEST CONNECTION");
}
但如果不调用 bpGenerateSinFromPem()
,同样的代码不会出错。
bpGenerateSinFromPem
是*.i文件中的包装函数
%inline %{
char *bpGenerateSinFromPem(char *pem) {
char *ret = malloc(sizeof(char)*36);
char *err = "ERROR";
int errorCode;
errorCode = generateSinFromPem(pem, &ret);
if (errorCode == NOERROR) {
return ret;
} else {
return err;
}
}
%}
其中调用了C函数:
int GenerateSinFromPem(char *pem, char **sin) {
char *pub = calloc(67, sizeof(char));
u_int8_t *outBytesPub = calloc(SHA256_STRING, sizeof(u_int8_t));
u_int8_t *outBytesOfStep1 = calloc(SHA256_STRING, sizeof(u_int8_t));
u_int8_t *outBytesOfStep3 = calloc(RIPEMD_AND_PADDING_STRING, sizeof(u_int8_t));
u_int8_t *outBytesOfStep4a = calloc(SHA256_STRING, sizeof(u_int8_t));
char *step1 = calloc(SHA256_HEX_STRING, sizeof(char));
char *step2 = calloc(RIPEMD_HEX_STRING, sizeof(char));
char *step3 = calloc(RIPEMD_AND_PADDING_HEX_STRING, sizeof(char));
char *step4a = calloc(SHA256_HEX_STRING, sizeof(char));
char *step4b = calloc(SHA256_HEX_STRING, sizeof(char));
char *step5 = calloc(CHECKSUM_STRING, sizeof(char));
char *step6 = calloc(RIPEMD_AND_PADDING_HEX + CHECKSUM_STRING, sizeof(char));
char *base58OfStep6 = calloc(SIN_STRING, sizeof(char));
getPublicKeyFromPem(pem, &pub);
pub[66] = '[=13=]';
createDataWithHexString(pub, &outBytesPub);
digestOfBytes(outBytesPub, &step1, "sha256", SHA256_STRING);
step1[64] = '[=13=]';
createDataWithHexString(step1, &outBytesOfStep1);
digestOfBytes(outBytesOfStep1, &step2, "ripemd160", SHA256_DIGEST_LENGTH);
step2[40] = '[=13=]';
memcpy(step3, "0F02", 4);
memcpy(step3+4, step2, RIPEMD_HEX);
step3[44] = '[=13=]';
createDataWithHexString(step3, &outBytesOfStep3);
digestOfBytes(outBytesOfStep3, &step4a, "sha256", RIPEMD_AND_PADDING);
step4a[64] = '[=13=]';
createDataWithHexString(step4a, &outBytesOfStep4a);
digestOfBytes(outBytesOfStep4a, &step4b, "sha256", SHA256_DIGEST_LENGTH);
step4b[64] = '[=13=]';
memcpy(step5, step4b, CHECKSUM);
sprintf(step6, "%s%s", step3, step5);
step6[RIPEMD_AND_PADDING_HEX + CHECKSUM] = '[=13=]';
base58encode(step6, base58OfStep6);
base58OfStep6[SIN] = '[=13=]';
memcpy(*sin, base58OfStep6, SIN_STRING);
free(pub);
free(step1);
free(step2);
free(step3);
free(step4a);
free(step4b);
free(step5);
free(step6);
free(base58OfStep6);
free(outBytesPub);
free(outBytesOfStep1);
free(outBytesOfStep3);
free(outBytesOfStep4a);
return NOERROR;
}
最后调用 digestOfBytes() 方法:
static int digestOfBytes(uint8_t *message, char **output, char *type, int inLength) {
EVP_MD_CTX *mdctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len, i;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname(type);
mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, message, inLength);
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
char *digest = calloc((md_len*2) + 1, sizeof(char));
for(i = 0; i < md_len; i++){
sprintf(&digest[2*i], "%02x", md_value[i]);
};
digest[md_len * 2] = '[=14=]';
memcpy(*output, digest, strlen(digest));
free(digest);
/* Call this once before exit. */
EVP_cleanup();
return 0;
}
这似乎有可能是由于我们的 C 库中没有释放某些资源造成的,但看起来我们正在释放所有可以释放的内存。为什么我们会看到这种冲突?
我们对这个问题的临时解决方案(可能非常糟糕)是在 digestOfBytes() 方法中消除对 EVP_Cleanup()
的调用。
显然发生的事情是这样的:我们导入的 Perl 库使用 openSSL,并通过 OpenSSL_add_all_x 之类的方式加载表。因为EVP_Cleanup() is global,Perl库(可能LWP::Protocol::https)去查找算法表时找不到。
虽然这可行,但我真的更愿意做一些更安全的事情……不清理似乎是一个草率的解决方案。
我们在 运行 使用 OpenSSL 构建的程序时遇到问题。我们遇到的具体错误是:global error: SSL Context init failed error:140A90F1:SSL routines:SSL_CTX_new:unable to load ssl2 md5 routines
.
上下文是 C library which is being wrapped by a Perl library 使用 SWIG。尝试使用 Perl 库连接到 HTTPS 地址时发生错误。
例如,这段代码会导致错误:
#These are just the imports I felt were relevant to this problem
use LWP::UserAgent;
use HTTP::Request;
use LWP::Protocol::https;
use IO::Socket::SSL;
sub test_can_connect_to_bitpay_api {
my $uri = "https://www.google.com";
my $pem = Business::OnlinePayment::BitPay::KeyUtils::bpGeneratePem();
my $sin = Business::OnlinePayment::BitPay::KeyUtils::bpGenerateSinFromPem($pem);
my $request = HTTP::Request->new(POST => $uri);
my $ua = LWP::UserAgent->new;
my $response = $ua->request($request);
ok($response->is_success, "TEST CONNECTION");
}
但如果不调用 bpGenerateSinFromPem()
,同样的代码不会出错。
bpGenerateSinFromPem
是*.i文件中的包装函数
%inline %{
char *bpGenerateSinFromPem(char *pem) {
char *ret = malloc(sizeof(char)*36);
char *err = "ERROR";
int errorCode;
errorCode = generateSinFromPem(pem, &ret);
if (errorCode == NOERROR) {
return ret;
} else {
return err;
}
}
%}
其中调用了C函数:
int GenerateSinFromPem(char *pem, char **sin) {
char *pub = calloc(67, sizeof(char));
u_int8_t *outBytesPub = calloc(SHA256_STRING, sizeof(u_int8_t));
u_int8_t *outBytesOfStep1 = calloc(SHA256_STRING, sizeof(u_int8_t));
u_int8_t *outBytesOfStep3 = calloc(RIPEMD_AND_PADDING_STRING, sizeof(u_int8_t));
u_int8_t *outBytesOfStep4a = calloc(SHA256_STRING, sizeof(u_int8_t));
char *step1 = calloc(SHA256_HEX_STRING, sizeof(char));
char *step2 = calloc(RIPEMD_HEX_STRING, sizeof(char));
char *step3 = calloc(RIPEMD_AND_PADDING_HEX_STRING, sizeof(char));
char *step4a = calloc(SHA256_HEX_STRING, sizeof(char));
char *step4b = calloc(SHA256_HEX_STRING, sizeof(char));
char *step5 = calloc(CHECKSUM_STRING, sizeof(char));
char *step6 = calloc(RIPEMD_AND_PADDING_HEX + CHECKSUM_STRING, sizeof(char));
char *base58OfStep6 = calloc(SIN_STRING, sizeof(char));
getPublicKeyFromPem(pem, &pub);
pub[66] = '[=13=]';
createDataWithHexString(pub, &outBytesPub);
digestOfBytes(outBytesPub, &step1, "sha256", SHA256_STRING);
step1[64] = '[=13=]';
createDataWithHexString(step1, &outBytesOfStep1);
digestOfBytes(outBytesOfStep1, &step2, "ripemd160", SHA256_DIGEST_LENGTH);
step2[40] = '[=13=]';
memcpy(step3, "0F02", 4);
memcpy(step3+4, step2, RIPEMD_HEX);
step3[44] = '[=13=]';
createDataWithHexString(step3, &outBytesOfStep3);
digestOfBytes(outBytesOfStep3, &step4a, "sha256", RIPEMD_AND_PADDING);
step4a[64] = '[=13=]';
createDataWithHexString(step4a, &outBytesOfStep4a);
digestOfBytes(outBytesOfStep4a, &step4b, "sha256", SHA256_DIGEST_LENGTH);
step4b[64] = '[=13=]';
memcpy(step5, step4b, CHECKSUM);
sprintf(step6, "%s%s", step3, step5);
step6[RIPEMD_AND_PADDING_HEX + CHECKSUM] = '[=13=]';
base58encode(step6, base58OfStep6);
base58OfStep6[SIN] = '[=13=]';
memcpy(*sin, base58OfStep6, SIN_STRING);
free(pub);
free(step1);
free(step2);
free(step3);
free(step4a);
free(step4b);
free(step5);
free(step6);
free(base58OfStep6);
free(outBytesPub);
free(outBytesOfStep1);
free(outBytesOfStep3);
free(outBytesOfStep4a);
return NOERROR;
}
最后调用 digestOfBytes() 方法:
static int digestOfBytes(uint8_t *message, char **output, char *type, int inLength) {
EVP_MD_CTX *mdctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len, i;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname(type);
mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, message, inLength);
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_destroy(mdctx);
char *digest = calloc((md_len*2) + 1, sizeof(char));
for(i = 0; i < md_len; i++){
sprintf(&digest[2*i], "%02x", md_value[i]);
};
digest[md_len * 2] = '[=14=]';
memcpy(*output, digest, strlen(digest));
free(digest);
/* Call this once before exit. */
EVP_cleanup();
return 0;
}
这似乎有可能是由于我们的 C 库中没有释放某些资源造成的,但看起来我们正在释放所有可以释放的内存。为什么我们会看到这种冲突?
我们对这个问题的临时解决方案(可能非常糟糕)是在 digestOfBytes() 方法中消除对 EVP_Cleanup()
的调用。
显然发生的事情是这样的:我们导入的 Perl 库使用 openSSL,并通过 OpenSSL_add_all_x 之类的方式加载表。因为EVP_Cleanup() is global,Perl库(可能LWP::Protocol::https)去查找算法表时找不到。
虽然这可行,但我真的更愿意做一些更安全的事情……不清理似乎是一个草率的解决方案。