我们使用 SWIG 为 Perl 提供了一个 C 加密实用程序库。我们能够生成密钥、创建摘要,但签名代码会导致分段错误,我们认为这可能在 OpenSSL 代码本身中,但很难确定。
此问题仅在使用 SWIG 运行代码时出现,本机 C 代码有效。
在 Perl 中,我们称之为:
$signature = key_utils::mysignMessageWithPem($pem, $message);
在 .i 文件中调用此代码:
%newobject mysignMessageWithPem;
%inline %{
char *mysignMessageWithPem(char *pem, char *message) {
char *ret = malloc(145);
char *err = malloc(5);
int errorCode;
memcpy(err, "ERROR", 5);
errorCode = signMessageWithPem(pem, message, &ret);
char *signature = ret;
if (errorCode == NOERROR) {
return signature;
} else {
return err;
}
}
%}
调用此 C 代码:
int signMessageWithPem(char *message, char *pem, char **signature) {
unsigned int meslen = strlen(message);
unsigned char *messagebytes = calloc(meslen, sizeof(unsigned char));
ECDSA_SIG *sig = NULL;
memcpy(messagebytes, message, meslen);
EC_KEY *key = NULL;
BIO *in = NULL;
unsigned char *buffer = NULL;
char *sha256ofMsg = calloc(SHA256_HEX_STRING, sizeof(char));
unsigned char *outBytesOfsha256ofMsg = calloc(SHA256_STRING, sizeof(unsigned char));
digestOfBytes(messagebytes, &sha256ofMsg, "sha256", meslen);
sha256ofMsg[64] = '\0';
createDataWithHexString(sha256ofMsg, &outBytesOfsha256ofMsg);
in = BIO_new(BIO_s_mem());
BIO_puts(in, pem);
PEM_read_bio_ECPrivateKey(in, &key, NULL, NULL);
sig = ECDSA_do_sign((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, key);
int verify = ECDSA_do_verify((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, sig, key);
if(verify != 1) {
return ERROR;
}
int buflen = ECDSA_size(key);
buffer = OPENSSL_malloc(buflen);
int derSigLen = i2d_ECDSA_SIG(sig, &buffer);
char *hexData = calloc(derSigLen, sizeof(char));
memcpy(hexData, buffer-derSigLen, derSigLen);
char *hexString = calloc(derSigLen*2+1, sizeof(char));
hexString[derSigLen * 2] = '\0';
toHexString(hexData, derSigLen, hexString);
memcpy(*signature, hexString, derSigLen*2);
signature[derSigLen * 2] = '\0';
EC_KEY_free(key);
BIO_free_all(in);
free(sha256ofMsg);
free(outBytesOfsha256ofMsg);
free(hexData);
free(hexString);
return NOERROR;
}
并返回Segmentation Fault
。我们得到的信息最多的错误是perl crashed with SIGSEGV in EC_KEY_get_key_method_data()
完整代码在这里:https ://github.com/aleitner/bitpay-perl/tree/stack-overflow-question
这是 SSL 的错误,还是我们做错了?