使用indy的IdSSLOpenSSLHeaders完成支付宝RSA2签名
前段时间做银行的支付接口,其中用到和支付宝新的RSA2一样的签名方法,网上的文章大多数都是用libeay32.pas封装的openssl函数去实现的,在测试的时候无意发现里面的函数和IdSSLOpenSSLHeaders里面的基本是一致的,想到应该是新的indy也封装了这些东西,研究了下,折腾了一天终于搞定了…
直接上代码吧,这样写的代码比以前要少很多
uses
IdGlobal, IdSSLOpenSSL, IdSSLOpenSSLHeaders, EncdDecd;
function Sign(msg, keyfile: ansistring; zfj, jmfs: integer;
var signstr: ansistring): integer;
//zfj:字符集 0 utf8 1 gbk jmfs:加密方式 0RSA 1RSA2 2MD5
var
Path: ansistring;
pkey: PEVP_PKEY;
bp, mbp: PBIO;
md_ctx: EVP_MD_CTX;
Buf: ansistring;
len: integer;
SigBuf: Array [0 .. 4095] of AnsiChar;
SigLen: integer;
InBuf: Array [0 .. 1023] of AnsiChar;
begin
result := -1;
try
if (not FileExists(keyfile)) then
begin
result := -2;
exit;
end;
// 签名 sign_type=RSA2 或RSA
Buf := Trim(msg);
if zfj = 0 then // 如果用UTF-8请UTF8编码
Buf := utf8encode(Buf);
len := length(Buf);
bp := BIO_new_file(PansiChar(keyfile), 'r'); // 加载私钥
try
pkey := PEM_read_bio_PrivateKey(bp, nil, nil, nil);
finally
BIO_free(bp);
end;
case jmfs of
0:
EVP_SignInit(@md_ctx, EVP_sha1); // 如果用RSA用 EVP_sha1
1:
EVP_SignInit(@md_ctx, EVP_sha256); // 如果是RSA2用 EVP_sha256
2:
EVP_SignInit(@md_ctx, EVP_md5); // 如果用MD5用 EVP_md5
end;
EVP_SignUpdate(@md_ctx, PansiChar(Buf), len);
EVP_SignFinal(@md_ctx, @SigBuf, @SigLen, pkey);
signstr := EncodeBase64(@SigBuf, SigLen);
result := 0;
except
on E: Exception do
result := -3;
end;
end;