Delphi2007,从网上找来的这样两个函数 function TMainForm.LoadPrivateKey(filename:string ): PEVP_PKEY; var bp: PBIO; A, pkey: PEVP_PKEY; begin a:=nil; bp := BIO_new(BIO_s_file()) ; BIO_read_filename(bp, PChar(filename)); pkey := PEM_read_bio_PrivateKey(bp, a, nil,NIL); BIO_free(bp); Result:= pkey; end;
function TMainForm.Sign(filename: string; msg: String): String; var ctx: EVP_MD_CTX; buf_in: PAnsiChar; m_len, outl: cardinal; pkey: PEVP_PKEY; m, buf_out: array [0..1024] of AnsiChar; p: array [0..255] of AnsiChar; i: Integer; begin buf_out := ''; if filename = '' then begin Result := ''; Exit; end; pKey := LoadPrivateKey(filename); buf_in := PAnsiChar(msg); EVP_MD_CTX_init(@ctx); //初始化 EVP_SignInit(@ctx,EVP_sha1()); //将需要使用的摘要算法存入ctxl中 EVP_SignUpdate(@ctx,buf_in,Length(buf_in));//存入编码值 EVP_DigestFinal(@ctx,m,m_len); //求取编码的长度为m_len摘要值存入m中 RSA_sign(EVP_sha1()._type,m,m_len,buf_out,@outl,pkey.pkey.rsa); //64为SHA1的NID EVP_MD_CTX_cleanup(@ctx); Result := EncodeString(StrPas(buf_out)); end; 和对应的libeay32.pas、libeay32.dll和ssleay32.dll,并在libeay32.pas中添加了相应的函数,把Indy升级到10.5.8,现在可以计算签名了,问题是有的字符串能计算对,有的字符串计算不对,对与错的比例在7:3左右,并且错的字符串和对的字符串前边的字符是完全一样的,只是错的字符串比对的字符串要短一些。如: 对的是mmfA7WgjdfS6xy2mJzXydNsrL8Z9cmLXDpV5YkVDl2ZLsWl22qkomrKnLmyP+/du0lyBE034OqgwaXURQ5HWUBl/qa2xafUW1EzFTIK5VXO59fI1gwBnyNS9hbjfUriWPsMGDWEeNyZs57L9nTa7IMmlGjrXwXJWpStl59jrf2w= 错的是mmfA7WgjdfS6xy2mJzXydNsrL8Z9cmLXDpV5YkVDl2ZLsWl22qkomrKnLmyP+/du0lyBE034OqgwaXURQ5HWUBl/qa2xafUW1EzFTIK5VXO59fI1gw== 初步分析应该是编码的问题,可是把要签名的字符串赋值给memo或者写到文件中再取出来都解决不了这种问题,有没有人遇到类似的情况呢
----------------------------------------------
-
keyBlob: record keyHeader: BLOBHEADER; keySize: DWORD; keyData: array[0..KEY_LEN_MAX-1] of Byte; end; keyLen : INTEGER; begin dwHashLen := 32; dwHmacHashLen := 32; {get context for crypt default provider} if CryptAcquireContext(@hCryptProvider, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) then begin {create hash-object MD5} if CryptCreateHash(hCryptProvider, CALG_SHA1, 0, 0, @hHash) then begin
{get hash from password} if CryptHashData(hHash, PByte(Key), Length(Key), 0) then begin
// hHash is now a hash of the provided key, (SHA1) // Now we derive a key for it hPubKey := 0;
if CryptImportKey(hCryptProvider, @keyBlob, SizeOf(KeyBlob), hPubKey, 0, @hKey) then begin
//hkey now holds our key. So we have do the whole thing over again ZeroMemory( @hmac_info, SizeOf(hmac_info) ); hmac_info.HashAlgid := CALG_SHA1; if CryptCreateHash(hCryptProvider, CALG_HMAC, hKey, 0, @hHmacHash) then begin if CryptSetHashParam( hHmacHash, HP_HMAC_INFO, @hmac_info, 0) then begin
if CryptHashData(hHmacHash, @Value[1], Length(Value), 0) then begin if CryptGetHashParam(hHmacHash, HP_HASHVAL, @bHmacHash[0], @dwHmacHashLen, 0) then begin for i := 0 to dwHmacHashLen-1 do Result := Result + IntToHex(bHmacHash[i], 2); end else WriteLn( 'CryptGetHashParam ERROR --> ' + SysErrorMessage(GetLastError)) ; end else WriteLn( 'CryptHashData ERROR --> ' + SysErrorMessage(GetLastError)) ; {destroy hash-object} CryptDestroyHash(hHmacHash); CryptDestroyKey(hKey); end else WriteLn( 'CryptSetHashParam ERROR --> ' + SysErrorMessage(GetLastError)) ;
end else WriteLn( 'CryptCreateHash ERROR --> ' + SysErrorMessage(GetLastError)) ; end else WriteLn( 'CryptDeriveKey ERROR --> ' + SysErrorMessage(GetLastError)) ;
end; {destroy hash-object} CryptDestroyHash(hHash); end; {release the context for crypt default provider} CryptReleaseContext(hCryptProvider, 0); end; Result := AnsiLowerCase(Result); end;
----------------------------------------------