
{******************************************************************************}
{                                                                              }
{  Este trabajo fue desarrollado en Mexico en Febrero del 2010                 }
{  Puedes usar partes de este codigo siempre y cuando proporciones los         }
{  creditos correspondientes, te agradeceria poner una nota como la siguiente: }
{  "Este software contiene partes escritas por Andres Jasqui"                  }
{                                                                              }
{******************************************************************************}

unit Sello;

interface

uses Windows, SysUtils, StrUtils, libeay32, utils;

function CalculaSello(llaveprivada,cadenaoriginal: string; Hash : THash): string;

implementation

function BinToBase64(const PDat: PBYTE; const DatLen: DWORD): string;
const BaseTable: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var s, s1: string;
	i, p, len, n, Addnum: DWORD;
	PBin: PBYTE;
begin
	result := '';
	S := '';
	addnum := 0;
	PBin := PDat;
	for i := 1 to DatLen do
	begin
		S := S + IntToHex(PBin^, 2);
		PBin := PBYTE(DWORD(PDat) + i);
	end;
	case (length(s) mod 3) of
		0: addnum := 0;
		1: begin
				s := s + '00';
				addnum := 2;
			end;
		2: begin
				s := s + '0';
				addnum := 1;
			end;
	end;
	len := length(s) div 3;
	for i := 1 to len do
	begin
		s1 := midstr(S, i * 3 - 2, 3);
		p := strtoint('$' + s1);
		n := p div 64;
		result := result + basetable[n + 1];
		n := p mod 64;
		result := result + basetable[n + 1];
	end;
	if addnum = 1 then result := result + '==';
	if addnum = 2 then result[length(result)] := '=';
end;

function ReadPrivateKey(AFileName: ansistring ): pEVP_PKEY; //string): pEVP_PKEY;
var keyfile: pBIO;
	mx : pEVP_PKey;
begin
	keyfile := BIO_new(BIO_s_file());
	BIO_read_filename(keyfile,PChar(AFilename));
	mx := nil;
	result := PEM_read_bio_PrivateKey(keyfile,mx,nil,nil);
end;

function CalculaSello(llaveprivada,cadenaoriginal: string; Hash : THash): string;
var inbuf: array [0..8192] of ansichar;
	outbuf: array [0..1024] of ansichar;
	key: pEVP_PKEY;
	mdctx: EVP_MD_CTX;	
	Len: cardinal;
begin
	cadenaoriginal := RemplazaCad(' ',#8,cadenaoriginal);
	cadenaoriginal := RemplazaCad(' ',#10,cadenaoriginal);
	cadenaoriginal := RemplazaCad(' ',#13,cadenaoriginal);
	cadenaoriginal := RemplazaCad('|',' |',cadenaoriginal);
	cadenaoriginal := RemplazaCad('|','| ',cadenaoriginal);
	cadenaoriginal := RemplazaCad(' ','  ',cadenaoriginal);

	StrPCopy(inbuf,UTF8Encode(cadenaoriginal));
	key := ReadPrivateKey(llaveprivada);
	if Hash = MD5 then EVP_SignInit(@mdctx,EVP_md5());
	if Hash = SHA1 then EVP_SignInit(@mdctx,EVP_sha1());
	EVP_SignUpdate(@mdctx,@inbuf,StrLen(inbuf));
	EVP_SignFinal(@mdctx,@outbuf,Len,key);

	result := BinToBase64(@outbuf,Len);
end;

end.
