2 Star 2 Fork 1

supermay / MD5WithRSA_for_Delphi

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
URsaKeyHelper.pas 7.55 KB
一键复制 编辑 原始数据 按行查看 历史
unit URsaKeyHelper;
interface
uses
libeay32, System.SysUtils, System.classes, System.NetEncoding,
System.StrUtils, System.Math;
type
(*
libeay32中的
//有一些libeay32.dll中没有这个函数
function EVP_md2: pEVP_MD; cdecl;
function EVP_md5: pEVP_MD; cdecl;
function EVP_sha: pEVP_MD; cdecl;
function EVP_sha1: pEVP_MD; cdecl;
function EVP_sha256: pEVP_MD; cdecl;
function EVP_dss: pEVP_MD; cdecl;
function EVP_dss1: pEVP_MD; cdecl;
*)
KEY_ALGORITHM = (MD5, SHA, SHA1, SHA256, DSS, DSS1);
EOpenSSLError = Exception;
EOpenSSLLibError = class(EOpenSSLError)
private
FErrorCode: Integer;
public
constructor Create(Code: Integer; const Msg: string);
property ErrorCode: Integer read FErrorCode;
end;
function Sign(priKey, Msg: String; _type: KEY_ALGORITHM): String;
function regulatePrivateKey(priKey: String): String;
implementation
const
C_RSA_KEY_BEGIN: String = '-----BEGIN RSA PRIVATE KEY-----';
C_RSA_KEY_END: String = '-----END RSA PRIVATE KEY-----';
// Private key 文件是一行64个字符的。
C_MAX_BY_LINE: Integer = 64;
procedure RaiseOpenSSLError(const AMessage: string = '');
var
ErrCode: Integer;
ErrMsg, FullMsg: string;
begin
ErrCode := ERR_get_error;
ErrMsg := string(ERR_error_string(ErrCode, nil));
if AMessage = '' then
FullMsg := ErrMsg
else
FullMsg := AMessage + ': ' + ErrMsg;
raise EOpenSSLLibError.Create(ErrCode, FullMsg);
end;
function regulatePrivateKey(priKey: String): String;
var
priKeyStrings: TStrings;
str_len: Integer;
lines: Integer;
l: String;
i: Integer;
begin
Result := '';
priKey := Trim(priKey);
if (priKey = '') then
Exit;
// 删除标志
priKey := StringReplace(priKey, C_RSA_KEY_BEGIN, '',
[rfReplaceAll, rfIgnoreCase]);
priKey := StringReplace(priKey, C_RSA_KEY_END, '',
[rfReplaceAll, rfIgnoreCase]);
// 删除换行 #13,#10
priKey := StringReplace(priKey, #13, '', [rfReplaceAll, rfIgnoreCase]);
priKey := StringReplace(priKey, #10, '', [rfReplaceAll, rfIgnoreCase]);
str_len := Length(priKey);
lines := ceil(str_len / C_MAX_BY_LINE);
priKeyStrings := TStringList.Create;
try
priKeyStrings.Add(C_RSA_KEY_BEGIN);
for i := 0 to lines - 1 do
begin
l := Copy(priKey, 1 + i * C_MAX_BY_LINE, C_MAX_BY_LINE);
priKeyStrings.Add(l);
end;
priKeyStrings.Add(C_RSA_KEY_END);
Result := priKeyStrings.Text;
finally
priKeyStrings.Free;
end;
end;
function getAlgorithm(_type: KEY_ALGORITHM): pEVP_MD;
begin
Result := nil;
case _type of
// KEY_ALGORITHM.MD2:
// begin
// Result := EVP_md2();
// end;
KEY_ALGORITHM.MD5:
begin
Result := EVP_md5();
end;
KEY_ALGORITHM.SHA:
begin
Result := EVP_sha();
end;
KEY_ALGORITHM.SHA1:
begin
Result := EVP_sha1();
end;
KEY_ALGORITHM.SHA256:
begin
Result := EVP_sha256();
end;
KEY_ALGORITHM.DSS:
begin
Result := EVP_dss();
end;
KEY_ALGORITHM.DSS1:
begin
Result := EVP_dss1();
end;
end;
end;
function LoadPrivateKey(priKey: String): pEVP_PKEY;
var
PriKeyStream: TStream;
Buffer: TBytes;
keybio: PBIO;
begin
Result := nil;
priKey := regulatePrivateKey(priKey);
if (priKey = '') then
begin
RaiseOpenSSLError('RSA PRIVATE KEY error');
Exit;
end;
PriKeyStream := TStringStream.Create(priKey);
try
SetLength(Buffer, PriKeyStream.Size);
PriKeyStream.ReadBuffer(Buffer[0], PriKeyStream.Size);
keybio := BIO_new_mem_buf(Buffer, Length(Buffer));
try
if keybio = nil then
begin
RaiseOpenSSLError('RSA load stream error');
Exit;
end;
// 此处有三种方法
// 1, 读取内存里生成的密钥对,再从内存生成rsa
// 2, 读取磁盘里生成的密钥对文本文件,在从内存生成rsa
// 3,直接从读取文件指针生成rsa
Result := PEM_read_bio_PrivateKey(keybio, Result, nil, nil);
finally
BIO_free(keybio);
end;
finally
PriKeyStream.Free;
end;
end;
// unsigned char * GetSign(char* keyFile,char* plainText,unsigned char* cipherText,unsigned int *cipherTextLen)
// {
// FILE* fp = fopen (keyFile, "r");
// if (fp == NULL)
// return NULL;
//
// /* Read private key */
// EVP_PKEY* pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
// fclose (fp);
//
// if (pkey == NULL) {
// ERR_print_errors_fp (stderr);
// return NULL;
// }
//
// /* Do the signature */
// EVP_MD_CTX md_ctx;
// EVP_SignInit (&md_ctx, EVP_sha1());
// EVP_SignUpdate (&md_ctx, plainText, strlen(plainText));
// int err = EVP_SignFinal (&md_ctx, cipherText, cipherTextLen, pkey);
//
// if (err != 1) {
// ERR_print_errors_fp(stderr);
// return NULL;
// }
//
// EVP_PKEY_free(pkey);
//
// return cipherText;
// }
function Sign(priKey, Msg: String; _type: KEY_ALGORITHM): String;
var
ctx: EVP_MD_CTX;
pkey: pEVP_PKEY;
key_type: pEVP_MD;
SigBuf: array [0 .. 4095] of Byte;
SigLen: Cardinal;
Buf: TStringStream;
buf_len: Integer;
err: Integer;
begin
Result := '';
pkey := LoadPrivateKey(priKey);
if pkey = nil then
begin
RaiseOpenSSLError('RSA load stream error');
Exit;
end;
try
Buf := TStringStream.Create(Trim(Msg), TEncoding.UTF8);
try
buf_len := Buf.Size;
try
key_type := getAlgorithm(_type);
if Assigned(key_type) then
begin
try
EVP_SignInit(@ctx, key_type); // 将需要使用的摘要算法存入ctxl中
EVP_SignUpdate(@ctx, Buf.Memory, buf_len);
err := EVP_SignFinal(@ctx, @SigBuf, SigLen, pkey);
if (err <> 1) then
begin
RaiseOpenSSLError('Sign error');
Result := '';
end;
Result := TNetEncoding.base64.EncodeBytesToString(@SigBuf, SigLen);
finally
EVP_MD_CTX_cleanup(@ctx);
{ TODO -o YBChao -c : 这里可能还存在内存泄漏,但不知如何解决 2021-12-27 9:45:32 }
{$IFNDEF CHROMIUM}
// CRYPTO_free(key_type);
// OPENSSL_free(key_type);
EVP_cleanup;
ERR_free_strings;
{$ENDIF}
end;
end;
except
RaiseOpenSSLError('Sign error');
end;
finally
Buf.Free;
end;
finally
EVP_PKEY_free(pkey);
end;
end;
// bool VerifySign(char* certFile,unsigned char* cipherText,unsigned int cipherTextLen,char* plainText)
// {
// /* Get X509 */
// FILE* fp = fopen (certFile, "r");
// if (fp == NULL)
// return false;
// X509* x509 = PEM_read_X509(fp, NULL, NULL, NULL);
// fclose (fp);
//
// if (x509 == NULL) {
// ERR_print_errors_fp (stderr);
// return false;
// }
//
// /* Get public key - eay */
// EVP_PKEY *pkey=X509_get_pubkey(x509);
// if (pkey == NULL) {
// ERR_print_errors_fp (stderr);
// return false;
// }
//
// /* Verify the signature */
// EVP_MD_CTX md_ctx;
// EVP_VerifyInit (&md_ctx, EVP_sha1());
// EVP_VerifyUpdate (&md_ctx, plainText, strlen((char*)plainText));
// int err = EVP_VerifyFinal (&md_ctx, cipherText, cipherTextLen, pkey);
// EVP_PKEY_free (pkey);
//
// if (err != 1) {
// ERR_print_errors_fp (stderr);
// return false;
// }
// return true;
// }
{ EOpenSSLLibError }
constructor EOpenSSLLibError.Create(Code: Integer; const Msg: string);
begin
FErrorCode := Code;
inherited Create(Msg);
end;
initialization
finalization
EVP_cleanup();
end.
Delphi
1
https://gitee.com/supermay/md5withrsa-for-delphi.git
git@gitee.com:supermay/md5withrsa-for-delphi.git
supermay
md5withrsa-for-delphi
MD5WithRSA_for_Delphi
master

搜索帮助