delphi

Oct 23, 2012 at 9:23 AM

Dečki ja se bum ubit kak da se je...o spojim na webservice iz delphi-a probao sam sve moguće kombinacije i više nemam ideja?  .o(((

Ako mi neko pošalje rješenje častim ga.

 

Oct 23, 2012 at 9:35 AM

Povezivanje na webservis iz Delphi-a je izvedivo kroz Indy komponente idHTTP i isServerIOHandlerSSLOpenSLL komponente i uredno se odrađuje Echo sa povratnim XMl-om. Problem je pronaći kvalitetni library za ispravno potpisivanje, momci na forum.hr ti mogu pomoći oko toga. Mada je jednostavnije sa ovih stranica koristiti  EXE datoteku kojoj proslijediš XML (ima primjera XML-a koji radi), koju pozoveš sa Shellexecutom. EXE je brz i još k tome vraća datoteku sa JIR-om! Odlično i brzo.

Oct 23, 2012 at 9:59 AM

daj mi please pošalji samo dio koda za spajanje na service i p.s. jesi možda probao kreko wsdl-a

Coordinator
Oct 23, 2012 at 10:46 AM

Ne znam kako se radi u Delphi-u, mi smo iz .NET svijeta, ali - probaj iskoristiti COM DLL ili EXE za rad sa svime ovime :)

Oct 23, 2012 at 11:18 AM
Edited Oct 23, 2012 at 11:19 AM

Ovo je kod koji šalje echo xml datoteku i kupi response:

procedure TForm4.Button1Click(Sender: TObject);
var
    resStream: TStringStream;

begin
    cisUrl := 'https://cistest.apis-it.hr:8449/FiskalizacijaServiceTest';
    resStream := TStringStream.Create;

    idHttp1.Request.Method := 'POST';
    IdHTTP1.Post(cisurl,'d:\demo_echo.xml',resstream);

    XMLDocument1.LoadFromStream( resstream);
    XMLDocument1.SaveToFile('d:\echo_request_result.xml');
end;

Ovo su postavke idHttp i TIdSSLIOHandlerSocketOpenSSL kontrole

  object IdHTTP1: TIdHTTP
    Intercept = IdLogFile1
    IOHandler = IdSSLIOHandlerSocketOpenSSL1
    AllowCookies = True
    ProxyParams.BasicAuthentication = False
    ProxyParams.ProxyPort = 0
    Request.CharSet = 'utf-8'
    Request.ContentLength = -1
    Request.ContentRangeEnd = -1
    Request.ContentRangeStart = -1
    Request.ContentRangeInstanceLength = -1
    Request.ContentType = 'text/xml'
    Request.Accept = 'text/html, */*'
    Request.BasicAuthentication = False
    Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
    Request.Ranges.Units = 'bytes'
    Request.Ranges = <>
    HTTPOptions = [hoForceEncodeParams]
    Left = 312
    Top = 132
  end
  object IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL
    Intercept = IdLogFile1
    MaxLineAction = maException
    Port = 0
    DefaultPort = 0
    SSLOptions.Method = sslvSSLv3
    SSLOptions.SSLVersions = [sslvSSLv3]
    SSLOptions.Mode = sslmClient
    SSLOptions.VerifyMode = []
    SSLOptions.VerifyDepth = 0
    Left = 360
    Top = 152
  end

 

Oct 24, 2012 at 3:56 PM

ovo ispod je jednostavni FiskalizacijaTest.dpr za testiranje slanja računa, samo upisi pravi oib...

radi i potpis i slanje.

download:

delphi: ftp://ftp.zlatkovic.com/pub/libxml/Delphi/

dllovi su ti tu ftp://ftp.zlatkovic.com/pub/libxml/oldreleases/ (pazi na verzije)

a libeay32.dll i libssl32.dll koristim od OpenVPN 2.0.9

samo slanje i prijem je u GetJir (THTTPReqResp komponenta)

--------------------------

program FiskalizacijaTest;

uses
  libxml2,
  libxslt,
  libxmlsec,
  SysUtils,
  Classes,
  Dialogs,
  SOAPHTTPTrans,
  XMLDoc,
  XMLIntf,
  Variants,
  Forms;

{$R *.res}
var
  dsigCtx: xmlSecDSigCtxPtr;
  xmlData:TStrings;
  signed_xmlData:TStrings;
  keyname,oib:string;

procedure appInit;
begin
   oib := '???';  //oib iz certifikata
   keyname := 'demo.pfx';

   dsigCtx := xmlSecDSigCtxCreate(nil);
   if dsigCtx=nil then raise exception.Create('Failed to create signature context');

   dsigCtx.signKey := xmlSecCryptoAppKeyLoad(pchar(keyname), xmlSecKeyDataFormatPkcs12, 'zaporka', nil, nil);
   if dsigCtx.signKey = nil then raise exception.Create('Failed to load private key');

end;

procedure xmlInit;
begin
   xmlData:=TStringList.Create;
   signed_xmlData:=TStringList.Create;

   xmlData.Text :='<?xml version="1.0"?>';

   xmlData.Add('<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">');
   xmlData.Add('    <soapenv:Body>');
   xmlData.Add('        <tns:RacunZahtjev xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.apis-it.hr/fin/2012/types/f73" xsi:schemaLocation="http://www.apis-it.hr/fin/2012/types/f73 ../schema/FiskalizacijaSchema.xsd" Id="racunId">');
   xmlData.Add('            <tns:Zaglavlje>');
   xmlData.Add('                <tns:IdPoruke>f81d4fae-7dec-11d0-a765-00a0c91e6bf6</tns:IdPoruke>');
   xmlData.Add('                <tns:DatumVrijeme>'+FormatDateTime('dd.mm.yyyy',now)+'T'+FormatDateTime('hh:mm:ss',now)+'</tns:DatumVrijeme>');
   xmlData.Add('            </tns:Zaglavlje>');
   xmlData.Add('            <tns:Racun>');
   xmlData.Add('                  <tns:Oib>'+oib+'</tns:Oib>');
   xmlData.Add('              <tns:USustPdv>true</tns:USustPdv>');
   xmlData.Add('                <tns:DatVrijeme>01.09.2012T21:10:34</tns:DatVrijeme>');
   xmlData.Add('                <tns:OznSlijed>P</tns:OznSlijed>');
   xmlData.Add('                <tns:BrRac>');
   xmlData.Add('                    <tns:BrOznRac>123456789</tns:BrOznRac>');
   xmlData.Add('                    <tns:OznPosPr>POSL1</tns:OznPosPr>');
   xmlData.Add('                    <tns:OznNapUr>12</tns:OznNapUr>');
   xmlData.Add('                </tns:BrRac>');
   xmlData.Add('                <tns:Pdv>');
   xmlData.Add('                    <tns:Porez>');
   xmlData.Add('                        <tns:Stopa>25.00</tns:Stopa>');
   xmlData.Add('                        <tns:Osnovica>10.00</tns:Osnovica>');
   xmlData.Add('                        <tns:Iznos>2.50</tns:Iznos>');
   xmlData.Add('                    </tns:Porez>');
   xmlData.Add('                </tns:Pdv>');
   xmlData.Add('                <tns:IznosUkupno>125.00</tns:IznosUkupno>');
   xmlData.Add('                <tns:NacinPlac>K</tns:NacinPlac>');
   xmlData.Add('                <tns:OibOper>01234567890</tns:OibOper>');
   xmlData.Add('                <tns:ZastKod>e4d909c290d0fb1ca068ffaddf22cbd0</tns:ZastKod>');
   xmlData.Add('                <tns:NakDost>false</tns:NakDost>');
   xmlData.Add('                <tns:ParagonBrRac>0123/458/5</tns:ParagonBrRac>');
   xmlData.Add('                <tns:SpecNamj>Navedeno kao primjer</tns:SpecNamj>');
   xmlData.Add('            </tns:Racun>');
   xmlData.Add('        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">');
   xmlData.Add('        <SignedInfo>');
   xmlData.Add('                <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>');
   xmlData.Add('                <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>');
   xmlData.Add('                <Reference URI="#racunId">');
   xmlData.Add('                <Transforms>');
   xmlData.Add('                <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>');
   xmlData.Add('                <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>');
   xmlData.Add('                </Transforms>');
   xmlData.Add('                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>');
   xmlData.Add('                <DigestValue/>');
   xmlData.Add('                </Reference>');
   xmlData.Add('        </SignedInfo>');
   xmlData.Add('        <SignatureValue/>');
   xmlData.Add('        <KeyInfo>');
   xmlData.Add('                <KeyName>'+keyname+'</KeyName>');
   xmlData.Add('                <X509Data/>');
   xmlData.Add('        </KeyInfo>');
   xmlData.Add('        </Signature>');
   xmlData.Add('        </tns:RacunZahtjev>');
   xmlData.Add('    </soapenv:Body>');
   xmlData.Add('</soapenv:Envelope>');
end;

procedure SignFile;
var  node: xmlNodePtr;
      doc: xmlDocPtr;
      buffer: PChar;
      bufSize: integer;
begin
   doc := xmlParseMemory(Pchar(xmlData.text),Length(xmlData.text));
   node := xmlSecFindNode(xmlDocGetRootElement(doc), PChar(xmlSecNodeSignature), PChar(xmlSecDSigNs));
   if not Assigned(node) then raise exception.Create('Start node not found');

  //id pizdarije
   xmlAddID(nil, doc, PChar('racunId'),
      xmlHasProp(xmlSecFindNode(xmlDocGetRootElement(doc), PChar('RacunZahtjev'), PChar('http://www.apis-it.hr/fin/2012/types/f73')), PChar('Id')));

   if (xmlSecDSigCtxSign(dsigCtx, node) < 0) then raise exception.Create('Signature failed');

    buffer := nil;
    xmlDocDumpMemory(doc, @buffer, @bufSize);
    signed_xmlData.Text := buffer;
//    MessageDlG(buffer,mtInformation,[mbOk],0);  //prikaz potipisanog xml-a
end;

function XMLFindNode(aNode:IXMLNode;aChildName:string):IXMLNode;
var i:integer;
begin
   result := nil;
   if aNode.HasChildNodes then for i:=0 to aNode.ChildNodes.Count-1 do
     if aNode.ChildNodes[i].NodeName = aChildName then begin
        result := aNode.ChildNodes[i];
        exit;
     end;
end;

function GetJir:string;
var HTTPReqResp: THTTPReqResp;
  Stream: TMemoryStream;
  StrStream: TStringStream; i:integer;
  aXML:TXMLDocument;  aJir:string; aNode:IXMLNode;
begin
  Stream := TMemoryStream.Create;
  StrStream := TStringStream.Create('');
  HTTPReqResp:= THTTPReqResp.Create(nil);
  aXML := TXMLDocument.Create(Application);

  try
    HTTPReqResp.UseUTF8InHeader := True;
    HTTPReqResp.URl :='https://cistest.apis-it.hr:8449/FiskalizacijaServiceTest';
    HTTPReqResp.Execute(signed_xmlData.Text, Stream);
    StrStream.CopyFrom(Stream, 0);
    aXML.LoadFromStream(StrStream);
    aXML.SaveToFile('response.xml');

    Result := 'greška';
    aNode := aXML.ChildNodes.FindNode('soap:Envelope');    //unutar envelope
    if assigned(aNode) and aNode.HasChildNodes then begin
      aNode := aNode.ChildNodes.FindNode('soap:Body');     //je body, a unutar body
        if assigned(aNode) and aNode.HasChildNodes then begin   //'tns:RacunOdgovor' find node ne nalazai?????
          aNode := XMLFindNode(aNode,'tns:RacunOdgovor');  //je RacunOdgovor (koji se ne može nać sa .FindNode, pa ga ručno tražim???
          if assigned(aNode) and aNode.HasChildNodes then begin
              aNode := aNode.ChildNodes.FindNode('tns:Jir');  //a unutar RacunOdgovor je Jir!!!!!
             if assigned(aNode) then Result := aNode.NodeValue;
          end;
        end;
    end;
  finally
    HTTPReqResp.Free;
    Stream.Free;
    StrStream.Free;
  end;
end;

procedure appFinish;
begin
  xmlData.Free;
  signed_xmlData.Free;
end;

begin
    xmlInitParser();
    __xmlLoadExtDtdDefaultValue^ := XML_DETECT_IDS or XML_COMPLETE_ATTRS;
    xmlSubstituteEntitiesDefault(1);
    __xmlIndentTreeOutput^ := 1;
    if (xmlSecInit() < 0) then Writeln(ErrOutput, 'Error: xmlsec initialization failed.');
   if (xmlSecCheckVersionExt(1, 2, 8, xmlSecCheckVersionABICompatible) <> 1) then  raise exception.Create('loaded xmlsec library version is not compatible.');
   if (xmlSecCryptoDLLoadLibrary('openssl') < 0) then raise exception.Create('unable to load default xmlsec-crypto library. Make sure'#10 );
   if (xmlSecCryptoAppInit(nil) < 0) then raise  exception.Create('crypto initialization failed.');
   if (xmlSecCryptoInit() < 0) then  raise exception.Create('xmlsec-crypto initialization failed.');

  try
    appInit;
    xmlInit;
    SignFile;
    MessageDlG(GetJir,mtInformation,[mbOk],0);
  finally
    { Shutdown xmlsec-crypto library }
    xmlSecCryptoShutdown();
    { Shutdown crypto library }
    xmlSecCryptoAppShutdown();
    { Shutdown xmlsec library }
    xmlSecShutdown();
    { Shutdown libxslt/libxml }
    xsltCleanupGlobals();
    xmlCleanupParser();
    appFinish;
  end;
end.


Coordinator
Oct 25, 2012 at 7:07 AM

Hvala vam na ovom doprinosu, svaka čast :)

Oct 25, 2012 at 9:33 AM

Kod mene ne prolazi dohvat ključa dakle Failed to load private key u ovoj liniji iako sam uredno definirao keyname i zaporku:

 dsigCtx.signKey := xmlSecCryptoAppKeyLoad(pchar(keyname), xmlSecKeyDataFormatPkcs12, 'zaporka', nil, nil);
   if dsigCtx.signKey = nil then raise exception.Create('Failed to load private key');

Kad testiram preko gotove Raverus.FiskalizacijaDEV.EXE.exe varijante uredno mi sve prolazi. A kroz delphi sa COM verzijom ne. Koristim DelphiXE i osim toga javlja mi grešku u compileu da npr. uz xmlSecNodeSignature i xmlSecDSigNs ne mogu koristiti pchar već moram definirati kao pAnsiChar

Oct 25, 2012 at 10:27 AM
Edited Oct 25, 2012 at 10:31 AM

DelphiXE je (usrani) unicode a xmlsec ne, tako da sve pchar treba definirati kao pAnsiChar,

isti problem je i sa stringovima svi su wide, ne mozes poslati pointer na "keyname: string" u xmlSecCryptoAppKeyLoad

moras keyname definirat prvo kao ansistring (jedno slovo jedan bajt) i unda poslat pointer u xmlSecCryptoAppKeyLoad,

ovaj dio 'zaporka' ti je po defaultu widestring konstanta, moras i to definirat kao ansi varijablu, ili stavis opciju da su svi string izrazi ansi...

mislim da ces imat iste probleme i sa COM verzijom.

Oct 25, 2012 at 10:31 AM
Edited Oct 25, 2012 at 2:57 PM

Očito me zato i COM varijanta zeza. 

Evo isprobao sa delphi 7 i sve radi bez greške. 

Hvala cipexp 

Oct 25, 2012 at 2:58 PM

Evo proradilo mi i na Delphi XE pa ako netko treba modificirani source od cipexp nek se javi

Oct 25, 2012 at 5:29 PM

Ako može pošalji meni da ne kemijam sam.

Fala unaprijed.

Poslao sam ti PM

Oct 25, 2012 at 6:28 PM
Edited Oct 25, 2012 at 6:34 PM

Evo ipak stavio ovdje jel vidim da ima zahtjeva. Dakle, verzija za DelphiXE 

program FiskalXE;
uses
libxml2,
libxslt,
libxmlsec,
SysUtils,
Classes,
Dialogs,
SOAPHTTPTrans,
XMLDoc,
XMLIntf,
Variants,
ComObj,
Forms;
{$R *.res}
var
dsigCtx: xmlSecDSigCtxPtr;
xmlData:AnsiString;
signed_xmlData:TStrings;
keyname,oib,UUID:UTF8String;
passw:AnsiString;
procedure appInit;
begin
oib := '11223344556'; //oib iz certifikata
keyname := 'fiskal_1.pfx';
passw:='ABCD_123456';
dsigCtx := xmlSecDSigCtxCreate(nil);
if dsigCtx=nil then raise exception.Create('Nije uspjelo kreiranje potpisnog konteksta');
dsigCtx.signKey := xmlSecCryptoAppKeyLoad(pchar(keyname), xmlSecKeyDataFormatPkcs12, pchar(passw), nil, nil);
if dsigCtx.signKey = nil then raise exception.Create('Ne mogu učitati privatni ključ');
end;
procedure xmlInit;
var
Guid: TGUID;
UUID: String;
begin
xmlData:='';
signed_xmlData:=TStringList.Create;
OleCheck(CreateGUID(Guid));
UUID := LowerCase(Copy(GUIDToString(Guid),2,length(GUIDToString(Guid))-2));
xmlData:='<?xml version="1.0"?>';
xmlData:='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">';
xmlData:=xmlData+' <soapenv:Body>';
xmlData:=xmlData+' <tns:RacunZahtjev xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.apis-it.hr/fin/2012/types/f73" xsi:schemaLocation="http://www.apis-it.hr/fin/2012/types/f73 ../schema/FiskalizacijaSchema.xsd" Id="racunId">';
xmlData:=xmlData+' <tns:Zaglavlje>';
xmlData:=xmlData+' <tns:IdPoruke>'+UUID+'</tns:IdPoruke>';
xmlData:=xmlData+' <tns:DatumVrijeme>'+FormatDateTime('dd.mm.yyyy',now)+'T'+FormatDateTime('hh:mm:ss',now)+'</tns:DatumVrijeme>';
xmlData:=xmlData+' </tns:Zaglavlje>';
xmlData:=xmlData+' <tns:Racun>';
xmlData:=xmlData+' <tns:Oib>'+oib+'</tns:Oib>';
xmlData:=xmlData+' <tns:USustPdv>true</tns:USustPdv>';
xmlData:=xmlData+' <tns:DatVrijeme>01.09.2012T21:10:34</tns:DatVrijeme>';
xmlData:=xmlData+' <tns:OznSlijed>P</tns:OznSlijed>';
xmlData:=xmlData+' <tns:BrRac>';
xmlData:=xmlData+' <tns:BrOznRac>123456789</tns:BrOznRac>';
xmlData:=xmlData+' <tns:OznPosPr>POSL1</tns:OznPosPr>';
xmlData:=xmlData+' <tns:OznNapUr>12</tns:OznNapUr>';
xmlData:=xmlData+' </tns:BrRac>';
xmlData:=xmlData+' <tns:Pdv>';
xmlData:=xmlData+' <tns:Porez>';
xmlData:=xmlData+' <tns:Stopa>25.00</tns:Stopa>';
xmlData:=xmlData+' <tns:Osnovica>10.00</tns:Osnovica>';
xmlData:=xmlData+' <tns:Iznos>2.50</tns:Iznos>';
xmlData:=xmlData+' </tns:Porez>';
xmlData:=xmlData+' </tns:Pdv>';
xmlData:=xmlData+' <tns:IznosUkupno>125.00</tns:IznosUkupno>';
xmlData:=xmlData+' <tns:NacinPlac>K</tns:NacinPlac>';
xmlData:=xmlData+' <tns:OibOper>01234567890</tns:OibOper>';
xmlData:=xmlData+' <tns:ZastKod>e4d909c290d0fb1ca068ffaddf22cbd0</tns:ZastKod>';
xmlData:=xmlData+' <tns:NakDost>false</tns:NakDost>';
xmlData:=xmlData+' <tns:ParagonBrRac>0123/458/5</tns:ParagonBrRac>';
xmlData:=xmlData+' <tns:SpecNamj>Navedeno kao primjer</tns:SpecNamj>';
xmlData:=xmlData+' </tns:Racun>';
xmlData:=xmlData+' <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">';
xmlData:=xmlData+' <SignedInfo>';
xmlData:=xmlData+' <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>';
xmlData:=xmlData+' <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>';
xmlData:=xmlData+' <Reference URI="#racunId">';
xmlData:=xmlData+' <Transforms>';
xmlData:=xmlData+' <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>';
xmlData:=xmlData+' <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>';
xmlData:=xmlData+' </Transforms>';
xmlData:=xmlData+' <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>';
xmlData:=xmlData+' <DigestValue/>';
xmlData:=xmlData+' </Reference>';
xmlData:=xmlData+' </SignedInfo>';
xmlData:=xmlData+' <SignatureValue/>';
xmlData:=xmlData+' <KeyInfo>';
xmlData:=xmlData+' <KeyName>'+keyname+'</KeyName>';
xmlData:=xmlData+' <X509Data/>';
xmlData:=xmlData+' </KeyInfo>';
xmlData:=xmlData+' </Signature>';
xmlData:=xmlData+' </tns:RacunZahtjev>';
xmlData:=xmlData+' </soapenv:Body>';
xmlData:=xmlData+'</soapenv:Envelope>';
end;
procedure SignFile;
var node: xmlNodePtr;
doc: xmlDocPtr;
buffer: PAnsiChar;
bufSize: integer;
duz,i:Integer;
adr:PChar;
begin
doc := xmlParseDoc(PAnsiChar(xmlData));
node := xmlSecFindNode(xmlDocGetRootElement(doc), PAnsiChar(xmlSecNodeSignature), PAnsiChar(xmlSecDSigNs));
if not Assigned(node) then raise exception.Create('XML početni čvor nije nađen');
//id pizdarije
xmlAddID(nil, doc, PAnsiChar('racunId'),
xmlHasProp(xmlSecFindNode(xmlDocGetRootElement(doc), PAnsiChar('RacunZahtjev'), PAnsiChar('http://www.apis-it.hr/fin/2012/types/f73')), PAnsiChar('Id')));
if (xmlSecDSigCtxSign(dsigCtx, node) < 0) then
begin
raise exception.Create('Potpisivanje neuspješno');
end;
buffer := nil;
xmlDocDumpMemory(doc, @buffer, @bufSize);
signed_xmlData.Text := buffer;
//MessageDlG(buffer,mtInformation,[mbOk],0); //prikaz potipisanog xml-a
end;
function XMLFindNode(aNode:IXMLNode;aChildName:string):IXMLNode;
var i:integer;
begin
result := nil;
if aNode.HasChildNodes then for i:=0 to aNode.ChildNodes.Count-1 do
if aNode.ChildNodes[i].NodeName = aChildName then begin
result := aNode.ChildNodes[i];
exit;
end;
end;
function GetJir:string;
var HTTPReqResp: THTTPReqResp;
Stream: TMemoryStream;
StrStream: TStringStream; i:integer;
aXML:TXMLDocument; aJir:string; aNode:IXMLNode;
begin
Stream := TMemoryStream.Create;
StrStream := TStringStream.Create('');
HTTPReqResp:= THTTPReqResp.Create(nil);
aXML := TXMLDocument.Create(Application);
try
HTTPReqResp.UseUTF8InHeader := True;
HTTPReqResp.Execute(signed_xmlData.Text, Stream);
StrStream.CopyFrom(Stream, 0);
aXML.LoadFromStream(StrStream);
aXML.SaveToFile('response.xml');
Result := 'greška';
aNode := aXML.ChildNodes.FindNode('soap:Envelope'); //unutar envelope
if assigned(aNode) and aNode.HasChildNodes then begin
aNode := aNode.ChildNodes.FindNode('soap:Body'); //je body, a unutar body
if assigned(aNode) and aNode.HasChildNodes then begin //'tns:RacunOdgovor' find node ne nalazai?????
aNode := XMLFindNode(aNode,'tns:RacunOdgovor'); //je RacunOdgovor (koji se ne može nać sa .FindNode, pa ga ručno tražim???
if assigned(aNode) and aNode.HasChildNodes then begin
aNode := aNode.ChildNodes.FindNode('tns:Jir'); //a unutar RacunOdgovor je Jir!!!!!
if assigned(aNode) then Result := aNode.NodeValue;
end;
end;
end;
finally
HTTPReqResp.Free;
Stream.Free;
StrStream.Free;
end;
end;
procedure appFinish;
begin
xmlData:='';
signed_xmlData.Free;
end;
begin
xmlInitParser();
__xmlLoadExtDtdDefaultValue^ := XML_DETECT_IDS or XML_COMPLETE_ATTRS;
xmlSubstituteEntitiesDefault(1);
__xmlIndentTreeOutput^ := 1;
if (xmlSecInit() < 0) then Writeln(ErrOutput, 'Greška: neuspjela xmlsec inicijalizacija.');
if (xmlSecCheckVersionExt(1, 2, 8, xmlSecCheckVersionABICompatible) <> 1) then raise exception.Create('Učitana kriva verzija xmlsec biblioteke.');
if (xmlSecCryptoDLLoadLibrary('openssl') < 0) then raise exception.Create('ne mogu učitati xmlsec-crypto biblioteku. Provjerite'#10 );
if (xmlSecCryptoAppInit(nil) < 0) then raise exception.Create('neuspjela crypto inicijalizacija.');
if (xmlSecCryptoInit() < 0) then raise exception.Create('neuspjela xmlsec-crypto inicijalizacija.');
try
appInit;
xmlInit;
SignFile;
MessageDlG(GetJir,mtInformation,[mbOk],0);
finally
{ Shutdown xmlsec-crypto library }
xmlSecCryptoShutdown();
{ Shutdown crypto library }
xmlSecCryptoAppShutdown();
{ Shutdown xmlsec library }
xmlSecShutdown();
{ Shutdown libxslt/libxml }
xsltCleanupGlobals();
xmlCleanupParser();
appFinish;
end;
end.
Oct 27, 2012 at 11:45 PM

Malo prije sam ostavio verziju za Delphi 7 i COM DLL na Issue tracker pod '613 - Podrška za COM DLL (VB6)'...

Oct 29, 2012 at 10:52 AM

COM EXE varijanta radi sa Delphijem, ali na žalost moram od nje odustati jer ne želim dodatno opterećivati (definitivno neuke) korisnike sa registracijom COM assemblija u windowsima.  Dovoljno problema će biti i sa importiranjem certifikata.

Činjenica je da bi stvar trebala biti krajnje jednostavna kad se automatizira sa nekim bat-om ili sl., ali tu uvijek nešto pođe po zlu i onda treba rješavati te probleme kod korisnika, i zapravo prvo treba detektirati da se assembli uopće nije ispravno registrirao. Probao na nekoliko računala i već na par njih nije prošlo iz prve, traži administratorske ovlasti i sl., a kad je broj korisnika 1000+ problema i previše.

Kao DLL koristim funkciju za HASH kod RSm-a od Fine, dll se deklarira sa jednom linijom koda i funkcija je dostupna kao sve druge.
procedure doSHAOnFile(Filename : PAnsiChar; dig : PAnsiChar); stdcall; external 'svcrypt.dll';

Da li je moguće napraviti jedno takvo rješenje??

 

Coordinator
Oct 29, 2012 at 11:43 AM
Edited Oct 29, 2012 at 11:50 AM

@deva55, u prilogu se nalazi arhiva COM installera. Nakon što instaliraš package, COM dll bi se trebao automatski instalirati i registrirati. Tip registracije je "vsdrpCOM". Ako ti ne prolazi niti ovo, možeš mi se javiti ovdje i onda ću ti napraviti "vsdrpCOMRelativePath" tip automatske registracije. Jedan od ta dva načina bi ti trebao pomoći da se ne patiš ručno sa registracijom i dodatno opterećuješ usere...

Javi rezultate :)

COM_installer:

http://sdrv.ms/QPBVab

 

* podrazumijeva se da imaš instaliran 2.0 framework

Oct 29, 2012 at 4:15 PM
dkustec wrote:

@deva55, u prilogu se nalazi arhiva COM installera. Nakon što instaliraš package, COM dll bi se trebao automatski instalirati i registrirati. Tip registracije je "vsdrpCOM". Ako ti ne prolazi niti ovo, možeš mi se javiti ovdje i onda ću ti napraviti "vsdrpCOMRelativePath" tip automatske registracije. Jedan od ta dva načina bi ti trebao pomoći da se ne patiš ručno sa registracijom i dodatno opterećuješ usere...

Javi rezultate :)

COM_installer:

http://sdrv.ms/QPBVab

 

* podrazumijeva se da imaš instaliran 2.0 framework

Ako sam dobro shvatio setup.exe bi trebao biti instalacijski program za korisnika sa kojim bi korisnik registrirao assembly u windowsima?
Ako je odgovor "da", to nije rješenje koje tražim.

Pokušat ću sa Importom Type Library-a u Delphi tj. importom .NET assemblia u Delphi.

Nov 5, 2012 at 8:22 AM

Dali je koja dobra duša riješila generiranje zaštitnog koda (ZKI-a) kroz delphi pa ako može ovdje jedan primjer. Hvala.  

Nov 5, 2012 at 1:53 PM
Edited Nov 6, 2012 at 2:21 PM
tZac wrote:

Dali je koja dobra duša riješila generiranje zaštitnog koda (ZKI-a) kroz delphi pa ako može ovdje jedan primjer. Hvala.  

Trebaš libeay32.dll i libeay32.pas

Nezgodno je što key čita iz .pem datoteke. Trebalo bi riješiti da čita iz .pfx-a.

Ne znam kako provjeriti jel to ono što se traži.

function Sign_RSA_SHA1(const aFileName:String; const aString:String): string;
var Len: cardinal;
    mdctx: EVP_MD_CTX;
    inbuf, outbuf: array [0..1023] of ansichar;
    key: pEVP_PKEY;
    a : pEVP_PKEY;
    keyfile: pBIO;

begin
  a := nil;
  OpenSSL_add_all_algorithms; //
  OpenSSL_add_all_ciphers; // InitOpenSSL
  OpenSSL_add_all_digests; //
  ERR_load_crypto_strings; //
  try
  keyfile := BIO_new(BIO_s_file());
  BIO_read_filename(keyfile, PAnsiChar(ansistring(aFileName)));
  key := PEM_read_bio_PrivateKey(keyfile, a, nil, nil);
  if key = nil then
  begin
    raise Exception.Create('Unable to read private key. ');
  end;
  EVP_SignInit(@mdctx, EVP_sha1());
  EVP_SignUpdate(@mdctx, pChar(aString), StrLen(pchar(aString)));
  EVP_SignFinal(@mdctx, @outbuf, Len, key);
  BinToHex(outbuf, inbuf,Len);
  inbuf[2*Len]:=#0;
  Result := inbuf;
  finally
    EVP_cleanup; // FreeOpenSSL
  end;
end;

Nov 5, 2012 at 3:25 PM
Edited Nov 6, 2012 at 2:21 PM
tZac wrote:

Dali je koja dobra duša riješila generiranje zaštitnog koda (ZKI-a) kroz delphi pa ako može ovdje jedan primjer. Hvala.  

Evo i funkcija koja čita iz pfx datoteke.

Jel može netko usporediti rezultat sa rezultatima iz primjera u Javi i .Net-u?


function Sign_RSA_SHA1(const aString:String; const aFileName: String; const aPass:String): string;
var
Len: cardinal;
mdctx: EVP_MD_CTX;
inbuf, outbuf: array [0..1023] of ansichar;
certfile: pBIO;
pCertificate: pX509;
p12: pPKCS12;
privatekey: pEVP_PKEY;
ca: pSTACK_OFX509;
begin
  OpenSSL_add_all_algorithms; //
  OpenSSL_add_all_ciphers; // InitOpenSSL
  OpenSSL_add_all_digests; //
  ERR_load_crypto_strings; //
  try
    StrPCopy(inbuf, aString);
    certfile:=BIO_new(BIO_s_file());
    BIO_read_filename(certfile, PAnsiChar(AnsiString(aFileName)));
    p12:=d2i_PKCS12_bio(certfile, nil);
    PKCS12_parse(p12, PAnsiChar(AnsiString(aPass)), privatekey, pCertificate, ca);
    if privatekey = nil then
      raise Exception.Create('Unable to read private key. ');
    EVP_SignInit(@mdctx, EVP_sha1());
    EVP_SignUpdate(@mdctx, @inbuf, StrLen(inbuf));
    EVP_SignFinal(@mdctx, @outbuf, Len, privatekey);
    EVP_cleanup;
    BinToHex(outbuf, inbuf,Len);
    inbuf[2*Len]:=#0;
    result := StrPas(inbuf);
  finally
    EVP_cleanup;
  end;
end;

Coordinator
Nov 5, 2012 at 3:27 PM

@didibau, Teško bez istog FISKAL certifikata :)

Nov 5, 2012 at 4:29 PM
nrasinec wrote:

@didibau, Teško bez istog FISKAL certifikata :)

Ali može sa istim certifikatom :-)

Coordinator
Nov 5, 2012 at 5:38 PM

U v1.2, koju izdajemo, nadam se, sutra, će biti moguće provjeriti .NET implementaciju za ZKI; dakle i kroz COM odnosno EXE, pa svatko zainteresiran može provjeriti .NET vs ostale platforme.

Nov 6, 2012 at 10:11 AM
didibau wrote:
Evo i funkcija koja čita iz pfx datoteke.

Može pomoć, na ovoj liniji mi baca EAccessViolation in  module LIBEAY32.DLL

    PKCS12_parse(p12, PAnsiChar(AnsiString(aPass)), privatekey, pCertificate, ca);

Ne vidim niš posebno, radim u delphi XE.

Nov 6, 2012 at 12:12 PM

Meni radi u Delphi 2009 a u XE3 je isto AccessViolation.

Nov 6, 2012 at 1:26 PM

//ovo je pomoću xmlsec libova i transformid-ova (kao i potpis xml-a)

function pas_xmlSecTransformCtxBinaryExecute(dsigCtx:xmlSecDSigCtxPtr;data:xmlsecbyteptr;dataSize:xmlSecSize):integer;
var  ret:integer;  t_ctx:xmlSecTransformCtxPtr;
transctx:xmlSecTransformPtr;
    dsigRefCtx:xmlSecDSigReferenceCtxPtr ;
    base64Encode:xmlSecTransformPtr ;
    md5:xmlSecTransformPtr ;xxx:string;
const xmlSecTransformDataTypeBin:cardinal =$0001;
begin    
    result := -1;
    t_ctx := @(dsigCtx.transformCtx);
    if not assigned(t_ctx) or assigned(t_ctx.result) or (t_ctx.status<>xmlSecTransformStatusNone) or  not assigned(data) or (dataSize=0) then exit;
    if assigned(t_ctx.uri) then exit; 
   
    dsigCtx.operation  := xmlSecTransformOperationSign;
    dsigCtx.status     := xmlSecDSigStatusUnknown;

    dsigCtx.defSignMethodId := xmlSecTransformIdListFindByHref(xmlSecTransformIdsGet(),pansiChar('http://www.w3.org/2000/09/xmldsig#rsa-sha1'),$0008);
    if assigned(dsigCtx.defSignMethodId) then begin
        dsigCtx.signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx,dsigCtx.defSignMethodId);
        dsigCtx.signMethod.operation :=  dsigCtx.operation;
        dsigCtx.signMethod.id.setKey(dsigCtx.signMethod,dsigCtx.signKey);
        if not assigned (dsigCtx.signMethod) then exit;
    end;
   
    if  false and (dsigCtx.operation = xmlSecTransformOperationSign) then begin //po novome se ne konverira u base64
        base64Encode := xmlSecTransformCtxCreateAndAppend(t_ctx,
                                                         xmlSecTransformBase64GetKlass);
        if not assigned(base64Encode) then exit;
        base64Encode.operation := xmlSecTransformOperationEncode;
    end;
   
    if false and (dsigCtx.operation = xmlSecTransformOperationSign) then begin  //md5 javlja greške pa je napravljen sa TIdHashMessageDigest5
        MD5 := xmlSecTransformCtxCreateAndAppend(t_ctx,xmlSecTransformHmacMd5GetKlass);
        if not assigned(MD5) then exit;
        MD5.operation := xmlSecTransformOperationSign;
    end;
   
   
   if not assigned(dsigCtx.signKey) then exit;


    ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
    if(ret < 0) then exit;
//    ret := transctx.id.pushBin(transctx,data,dataSize,1, t_ctx );
    ret := xmlSecTransformDefaultPushBin(t_ctx.first,data,dataSize,1, t_ctx);
    xxx :=pchar(t_ctx.result.data) ;

    with TIdHashMessageDigest5.Create do begin
      xxx := AsHex(HashValue( xxx ));
      free;
    end;
    showmessage(xxx);
    if(ret < 0) then exit;

    t_ctx.status := xmlSecTransformStatusFinished;
    result := 0;
end;

Nov 6, 2012 at 1:35 PM

didibau potpisuješ li xml sa xmlsec ili direktno pomoću libeay32.dll i libeay32.pas??

Nov 6, 2012 at 1:57 PM

xml potpisujem sa xmlsec a zaštitni kod sa libeay32

Nov 6, 2012 at 2:04 PM

OK, kome u D2009 radi potpisivanje iz pfx datoteke?
danas sam potrošio poprilično vremena i nisam ništa riješio.

Učita on ključ i sve to ali EVP_SignFinal ne upiše ništa u outbuf, len je 0!

Koja je verzija libeay32.dll -a?  Koristim 0.9.8.8 / 0.9.8h i libeay32.pas sa talijanskih stranica.

I što je s ovim Array of Char, ne bi li trebao biti array of ansichar?

Nov 6, 2012 at 2:21 PM

Je, ansichar mora biti. Editirano.

Nov 6, 2012 at 2:31 PM
Edited Nov 6, 2012 at 2:33 PM

oprova sam Sign_RSA_SHA1

i dobijem :

B39B1C54079BC88209FF0FBF07F2BC4DAEC50012D5349FF7C5578D508E9B9E3C3C1E3FF7498784CECAD3896

F0275F6409F1450273DA23744E98EB5F0690B5F5F835303A2F0E9C53541B1FBDE17CE6BDCCCE80A08EE1BCBC

A60B490FAFD1D0F6EDB83C3535BE0657BFAA475D69364959A7076A1725A2400A315B94DFC92F253F9C804F29

...

preprostavljam da je to potpis po uputama treba napravit sha5 od potpisa...

npr, na kraju dodati:

   with TIdHashMessageDigest5.Create do begin
      result:= AsHex(HashValue( result));
      free;
    end;

...

potpis pomoću xmlseca i libeay32 daje iste rezultate ali bez konverzije ključa iz bin to hex

umisto

    BinToHex(outbuf, inbuf,Len);
    inbuf[2*Len]:=#0;
    result := StrPas(inbuf);

stavim

   result:=StrPas(outbuf)

bintohex daje string reprezentaciju hex kodirane vridnosti, u uputama za zašt.ključ stoji izračunajMD5(elektronički potpisani medjurezultat)

bez konverzije u hex (ili šta je prije bilo u base64), te konverzije su potrebne samo radi zapisivanja rezultata u xml.

 

kad izađe COM verzije 1.2, možemo vidit jeli to u redu!

Nov 6, 2012 at 2:53 PM

Ajme, nakon nekoliko potrošenih sati  (bilo mi je sumnjivo što nisam dobivao pointer na p12, a onpo dokumentaciji ne smije biti nil za pcks_12 funkciju) ispada da cijeli dan funkciji šaljem samo ime datoteke certifikata bez putanja. Hm... No dobro, bar radi!

Nov 6, 2012 at 3:01 PM
Veky wrote:

Koja je verzija libeay32.dll -a?  Koristim 0.9.8.8 / 0.9.8h i libeay32.pas sa talijanskih stranica.

Isto tako 0.9.8.8. a libeay32.pas je version 0.7m sa:

http://www.disi.unige.it/person/FerranteM/delphiopenssl/

Nov 6, 2012 at 8:48 PM

Pitanje - da li bi ova koda radila i za Lazarus/Open Pascal ver. 1 ? Nisam tu baš doma...

Coordinator
Nov 7, 2012 at 10:17 AM

Ako je netko od vas koji radite u Delphi-u raspoložen poslati nam DLL (ili što već :) ) kreiran i buildan za Delphi, a koji se dalje može referencirati (linkati, uključiti) u druge projekte, stavit ćemo ga na službenu Downloads stranicu, uz napomenu o stvarnom autoru :)

Nov 7, 2012 at 1:05 PM
cipexp wrote:

oprova sam Sign_RSA_SHA1

 

cipexp, a jel može jedan primjer poziva ove funkcije. Pokušavam i stalno mi nešto fali u predaji i definiciji parametara. Nikako dobit xxx rezultat

 function pas_xmlSecTransformCtxBinaryExecute(dsigCtx:xmlSecDSigCtxPtr;data:xmlsecbyteptr;dataSize:xmlSecSize):integer;

Nov 7, 2012 at 2:08 PM
Edited Nov 7, 2012 at 2:20 PM

ovo ispod je kompletan unit signefile koji parsira xml i ako ima <tns:ZastKod/> dodat ce kod automatski

a ako upises <tns:ZastKod>e4d909c290d0fb1ca068ffaddf22cbd0</tns:ZastKod> samo će ga preskočiti

poziva se sa:

var dsigKey:xmlSecKeyPtr; //ključ
aXmlTxt:PAnsiChar; // nepotpisani xml
begin
  ...
  dsigKey := init(pansichar(keyname),pansichar(zaporka));
  SigneXML(aXmlTxt,dsigKey);  //nakon ovoga xml ima zastkod i potpis
  ...
  final;
end;


 

unit SigneFile;

interface
uses
  libxslt,
  libxmlsec,
  libxml2;

function init(aKey:PAnsiChar;aPwd:PAnsiChar):xmlSecKeyPtr;
procedure SigneXML(var aXML:PAnsiChar;aKey:xmlSecKeyPtr);
procedure final;

implementation
uses SysUtils,IdHashMessageDigest,dialogs; //dialogs je samo za testiranje

function GetXMLText(doc: xmlDocPtr):pchar;
var
      buffer: PChar;
      bufSize: integer;
begin
    buffer := nil;
    xmlDocDumpMemory(doc, @buffer, @bufSize);
    Result := buffer;
    xmlFree(@buffer);
end;

function init(aKey:PAnsiChar;aPwd:PAnsiChar):xmlSecKeyPtr;
begin
    result := nil;
    xmlInitParser();
    __xmlLoadExtDtdDefaultValue^ := XML_DETECT_IDS or XML_COMPLETE_ATTRS;
    xmlSubstituteEntitiesDefault(1);
    __xmlIndentTreeOutput^ := 1;
    if (xmlSecInit() < 0) then Writeln(ErrOutput, 'Error: xmlsec initialization failed.');
   if (xmlSecCheckVersionExt(1, 2, 8, xmlSecCheckVersionABICompatible) <> 1) then begin
     exit;
   end;
   if (xmlSecCryptoDLLoadLibrary('openssl') < 0) then begin
     exit;
   end;         
   if (xmlSecCryptoAppInit(nil) < 0) then begin
     exit;
   end;         
   if (xmlSecCryptoInit() < 0) then begin
     exit;
   end;         
   result := xmlSecCryptoAppKeyLoad(aKey, xmlSecKeyDataFormatPkcs12, aPwd, nil, nil);
end;                               

procedure final;
begin
    { Shutdown xmlsec-crypto library }
    xmlSecCryptoShutdown();
    { Shutdown crypto library }
    xmlSecCryptoAppShutdown();
    { Shutdown xmlsec library }
    xmlSecShutdown();
    { Shutdown libxslt/libxml }
    xsltCleanupGlobals();
    xmlCleanupParser();
end;

function IzracunajZastKod(zk:string;aKey:xmlSecKeyPtr):string;
var  ret:integer;  t_ctx:xmlSecTransformCtxPtr;
     transformCtx : xmlSecTransformCtx;
     signMethod:xmlSecTransformPtr;
     data:xmlSecBytePtr;datasize:integer;
     dsigRefCtx:xmlSecDSigReferenceCtxPtr ;
     rsa_sha1MethodId : xmlSecTransformId;
const xmlSecTransformDataTypeBin:cardinal =$0001;
begin
    result := '';
    data := xmlSecBytePtr( pansichar(zk));
    datasize := length(zk);
    t_ctx := @(transformCtx);
    xmlSecTransformCtxInitialize(t_ctx);
    if not assigned(t_ctx) or assigned(t_ctx.result) or (t_ctx.status<>xmlSecTransformStatusNone)
    or not assigned(data) or (dataSize=0) or not assigned(aKey) then exit;
    if assigned(t_ctx.uri) then exit;

    rsa_sha1MethodId :=  xmlSecTransformRsaSha1GetKlass;
    signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx,rsa_sha1MethodId);
    if not assigned (signMethod) then exit;
    signMethod.operation := xmlSecTransformOperationSign;
    xmlSecTransformSetKey(signMethod, aKey);
   
    ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
    if(ret < 0) then exit;
    ret := xmlSecTransformDefaultPushBin( t_ctx.first,data,dataSize,1, t_ctx);
    if(ret < 0) then exit;
   
    result :=pchar(t_ctx.result.data) ;

    with TIdHashMessageDigest5.Create do begin
      result := LowerCase(AsHex(HashValue( result )));
      free;
    end;

    t_ctx.status := xmlSecTransformStatusFinished;
end;

function DodajBrojRacuna(aNode:xmlNodePtr):string;
begin
  anode := aNode.children.next;  //'BrOznRac'
  result := anode.children.content;
  anode := aNode.next.next;  //'OznPosP'
  result := result+anode.children.content;
  anode := aNode.next.next;  //'OznNapUr'
  result := result+anode.children.content;
end;                                     

procedure DodajZastKod(var adoc:xmlDocPtr;aKey:xmlSecKeyPtr);
var node: xmlNodePtr; zk:string;
begin
  node := xmlDocGetRootElement(adoc);  //envelope
  node := node.children.next; //body
  node := node.children.next; // RacunZahtjev
  node := node.children.next; //Zaglavlje
  node := node.next.next; //racun
  node := node.children.next; //oib
  if not assigned(node.children) then exit;
  zk := node.children.content;
 
  while assigned(node) do begin
    node := node.next;
    if node.name = 'DatVrijeme' then begin
      zk := zk+StringReplace(node.children.content,'T',' ',[]);
    end else if node.name = 'BrRac' then begin
      zk := zk+DodajBrojRacuna(node);
    end else if node.name = 'IznosUkupno' then begin              
      zk := zk+node.children.content;
    end else if node.name = 'ZastKod' then begin              
      break;
    end;
  end;
  if not assigned(node.children) then begin
    zk := IzracunajZastKod(zk,aKey);
    xmlNodeSetContentLen(node, pansichar(zk),length(zk));
  end;
end;

procedure SigneXML(var aXML:PAnsiChar;aKey:xmlSecKeyPtr);
var dsigCtx: xmlSecDSigCtxPtr;
       node: xmlNodePtr;
        doc: xmlDocPtr;
begin
//   init;
   doc := xmlParseMemory(aXML,Length(aXml));
   DodajZastKod(doc,aKey);
   node := xmlSecFindNode(xmlDocGetRootElement(doc), PChar(xmlSecNodeSignature), PChar(xmlSecDSigNs));
   xmlAddID(nil, doc, PChar('racunId'), xmlHasProp(xmlSecFindNode(xmlDocGetRootElement(doc), PChar('RacunZahtjev'), PChar('http://www.apis-it.hr/fin/2012/types/f73')), PChar('Id')));
   dsigCtx := xmlSecDSigCtxCreate(nil);
   dsigCtx.signKey := aKey;
   xmlSecDSigCtxSign(dsigCtx, node);
   aXML := GetXMLText(doc);
   xmlFreeDoc(doc);
//   final;
end;


end.

Nov 7, 2012 at 2:20 PM

init bi trebalo pozvati jednom kod ulaska u kasu i zapamtiti key,

kod izlaska iz kase se poziva final...

tako radi puno brži (oko 5 sec za 100 potpisa) i ostavlja manje smeća u memoriji (oko 24 kb po potpisu)

sada ganjam taj memory leak, jer nakon 500 potpisa ostane oko 4 mb smeća!

Nov 7, 2012 at 3:28 PM
Edited Nov 7, 2012 at 4:10 PM

ovo je fiskalizacija.dpr za dll koji exportira 4 funkcije za potpis

procedure Fisk_init_sign_final; inicijalizira , potpiše i finalizira (nisam tu opciju testira) i za nju ne trebaju .pas-ovi koji statički linkaju dll-ove

(novi dll radi sa Pointer varijablama tako da ne treba pas sa xmlsec strukturama)

ink za .dll i pas sa strukturama

http://perfekta.hr/fiskalizacija/Fiskalizacija.dll

http://perfekta.hr/fiskalizacija/XMLSecType.pas  više ne treba ne treba za dll

ostali dll-ovi.

http://perfekta.hr/fiskalizacija/xmlsec_dll.zip

 

library Fiskalizacija;

uses
  SysUtils,
  Classes,libxmlsec,
  SigneFile in 'SigneFile.pas';

{$R *.res}
procedure Fisk_init_sign_final(var aXML:PAnsiChar;aKey:PAnsiChar;aPwd:PAnsiChar); export;
var aKeyPtr:xmlSecKeyPtr;
begin
  aKeyPtr :=init(aKey,aPwd);
  SigneXML(aXML,aKeyPtr);
  final;
end;

function  Fisk_init(aKey:PAnsiChar;aPwd:PAnsiChar):Pointer; export;
begin
  result := init(aKey,aPwd);
end;
procedure Fisk_SigneXML(var aXML:PAnsiChar;aKey:Pointer); export;
begin
  SigneXML(aXML,aKey);
end;

procedure Fisk_final; export;
begin
  final;
end;

exports Fisk_init;
exports Fisk_SigneXML;
exports Fisk_final;
exports Fisk_init_sign_final;
        
begin
end.

Nov 12, 2012 at 1:47 PM

pozdrav svima

zahvaljujem na kodu i trudu koji ste uložili

uspio sam implemenitrati kod da dobijem JIR

međutim radi mi samo na XP mašini (virtualnoj) na win 7 64 bita mi ne radi

 

jeli se netko susreo sa time?

Nov 12, 2012 at 9:54 PM

cipexp i tZac

da li ste naletjeli na problem šđč枊ĐČĆŽ

kada ga šaljem u unicode sve mi prolazi ali ovi papci iz apisa to nepreporučaju

utf-8 i latin mi štekaju imaš kakvu ideju. Problem mi se javlja kod potpisivanja xml-a.

Ili da se napravim budala i šaljem czs.

Nov 13, 2012 at 8:31 AM

@marekius, pa zamijeni samo šđč枊ĐČĆŽ s utf "dvobajtnim" pandamima pa će kod njih pisati ispravno.

Nov 13, 2012 at 9:49 AM

XMLSec radi isključivo s UTF8 što u kombinaciji s D2009 ili nivijim zna biti interesantno jer treba pravilno kovnertirati tipove za verzije Delphija koje su prešle na Unicode. Ja sam pogubio par dana dok nisam skladio gdje što i kako šaljem i preuzimam u kojem formatu jer mi nije prolazio dig. potpis. Kad sam to sve složio ČĆŽĐŠ se koriste uredno.   Prapotponu ideju "šišanja kvačica" ne bi preporučio jer ćete kad-tad naletjeti na poslovni prostor koji zbog toga ne bude imao korektno prijavljene podatke (npr. ulica Dobrise Cesarica ne postoji).  U doba DOS-a. 3.30 i tsr programa za croscii i yuscii sam to i mogao razumjeti, no u današnje doba je to doista neopravdana alternativa.

 

Testirao sam XMLSec i OpenSSL (za čitanje podataka iz certifikata i dsig zaštitnog koda) na windows Xp, W7 i w/ x64 i sve radi odlično. Jedini problem mi je bio Shell Nottifier koji je bugovito radio na Win XP no zamijenio sam ga kvalitetnijom klasom i sve što mi treba je kopirati jedan ini, exe , direktorij s certifikatima i psotaviti onih par dll-ova. u putanju. Radi bez pitanja i problema :-)

Nov 13, 2012 at 9:55 AM
Edited Nov 13, 2012 at 9:56 AM

našao sam rješenje za svoj problemčić:

root certifikat fine mi se nije instalirao u Trousted Root Certification Autorities.

to se na win 7 mora posebno enejblati, upute su na ova dva linka

http://technet.microsoft.com/en-us/library/cc754841.aspx#BKMK_managelocal

http://technet.microsoft.com/en-us/library/cc754841.aspx#BKMK_addlocal

potrošio dan i pol na import certifikata :-)

Coordinator
Nov 13, 2012 at 11:08 AM
Edited Nov 13, 2012 at 11:08 AM

Evo mene opet s ovim blogom, no, vrijedi pogledati: http://blog.fiskalizacija-dev.com.hr/post/2012/10/14/Kako-preuzeti-i-instalirati-democacert-Verifikacijskiroot-(samopotpisani)-certifikat-za-Demo-CA-.aspx

Možda nekom drugom pomogne da ne izgubi dan i pol na certifikate :)

Nov 13, 2012 at 12:16 PM

pročitao sam ja i taj blog,

međutim kao što sam i napisao, certifikat se nije instalirao u Trousted Root Certification Autorities, nego u Intermidiate.

na win 7 je bilo disabled učitavanje u root certifikate (možda su i prava na domeni / small biznis serveru 2011 uzrok tome; to ne znam nisam sistemaš)

Nov 13, 2012 at 2:32 PM
Edited Nov 13, 2012 at 3:02 PM
Veky wrote:

XMLSec radi isključivo s UTF8 što u kombinaciji s D2009 ili nivijim zna biti interesantno jer treba pravilno kovnertirati tipove za verzije Delphija koje su prešle na Unicode. Ja sam pogubio par dana dok nisam skladio gdje što i kako šaljem i preuzimam u kojem formatu jer mi nije prolazio dig. potpis. Kad sam to sve složio ČĆŽĐŠ se koriste uredno.   

 

evo kodova tablice za konverziju

Č    &#268;
č    &#269;
Ć    &#262;
ć    &#263;
Đ    &#272;
đ    &#273;
Š    &#352;
š    &#353;
Ž    &#381;
ž    &#382;
Nov 13, 2012 at 2:54 PM

Sa UTFEncode prolazi mi poslovni ali ne i računi tj. ona opisna polja .o(

Veky ak imaš rješenje šalji i meni to mi je jedino preostalo za kraj

Nov 14, 2012 at 7:51 AM

Hvala kreten sam u prošlom testiranju sa utf u kodu sam zaboravio staviti ; e budale ali jgb što je tu je

Nov 14, 2012 at 8:27 AM
marekius wrote:

Hvala kreten sam u prošlom testiranju sa utf u kodu sam zaboravio staviti ; e budale ali jgb što je tu je

x2 pa sam zato i stavio kodove tu

Nov 16, 2012 at 9:46 AM

Pozdrav svima.

Kako ste vi riješili provjeru da li je dobiveni XML iz CIS-a ispravno potpisan. Ili ste taj dio jednostavno preskočili?

Coordinator
Nov 16, 2012 at 10:01 AM

Nije rješenje za Delphi, ali, mislimo o tome, issue je ovdje, biti će riješeno u slijedećoj verziji: http://fiskalizacija.codeplex.com/workitem/671

Nov 16, 2012 at 1:04 PM

Što god radio i čime god (certifikatom iz fajla, certifikatom iz x509 podataka) provjeravao xmlsec mi vraća False.

Coordinator
Nov 16, 2012 at 1:06 PM

Samo da skrenem pažnju na ovu raspravu, možda pomogne: http://fiskalizacija.codeplex.com/discussions/403288

Coordinator
Nov 16, 2012 at 6:06 PM

Ažurirali smo Download section za v1.2. sa verzijom za Delphi: http://fiskalizacija.codeplex.com/releases/view/96854

Nov 16, 2012 at 6:42 PM

Maestralan uradak, velik uložen trud, doduše ne koristi FiskalizacijaDev.dll.

Bravo sa velikim B.

Nov 16, 2012 at 7:39 PM
vvrbane wrote:

Maestralan uradak, velik uložen trud, doduše ne koristi FiskalizacijaDev.dll.

Bravo sa velikim B.

Ako nekome pomogne ja sretan. U svakom slučaju bez podrške i savjeta dobrih ljudi sa ovog bloga ne bi bilo ni ovog rješenja.

Nov 17, 2012 at 11:41 AM

Jedno veliko HVALA i od mene.

Nov 17, 2012 at 3:56 PM

Izgleda da sam naletio na grešku... zaštitni kod generiran u Delphi-u je različit od onog koji generira Raverus.FiskalizacijaDEV.EXE

Molio bi da to netko još provjeri i potvrdi.

Nov 17, 2012 at 11:14 PM

dubravko

Provjerit ću u ponedjeljak još jednom source u ponedjeljak jedino kaj mi sada pada na pamet da je razlika u SHA1 ali jutro je pametnije od večeri. 

Jesi provjerio razliku u slanju dijela sa SHA1 datum/vrijeme racuna to mi trenutno pada na pamet.

 

Nov 18, 2012 at 4:33 PM
marekius wrote:

dubravko

Provjerit ću u ponedjeljak još jednom source u ponedjeljak jedino kaj mi sada pada na pamet da je razlika u SHA1 ali jutro je pametnije od večeri. 

Jesi provjerio razliku u slanju dijela sa SHA1 datum/vrijeme racuna to mi trenutno pada na pamet.

 

Ovaj red mi se čini da ima grešku:   

+ StringReplace(vDatumVrijemeRacuna,'T','',[rfReplaceAll])

Prema specifikaciji treba biti space između datuma i vremena, ali i kada to popravim i to mi daje različit kod.

Napravio sam u php-u algoritam za potpis i on mi daje isti rezultat kao i Raverus.FiskalizacijaDEV.EXE.

Zaštitni kod generiram funkcijom openssl_sign($s, $zastitni_kod, $key, OPENSSL_ALGO_SHA1);

Ne kužim baš taj dio tvojeg programa, pa ne mogu otkriti u čemu je problem.

 

Nov 18, 2012 at 4:53 PM

Još sam nešto primjetio...

Ukoliko se prilikom exporta certifikata uključi: Export all extended properties, tada se dobiva greška neispravan potpis, dok taj isti exportirani certifikat prolazi i sa Raverus.FiskalizacijaDEV.EXE i php-om.

Nov 18, 2012 at 8:30 PM
Edited Nov 18, 2012 at 8:39 PM
dubravko wrote:
marekius wrote:

dubravko

Provjerit ću u ponedjeljak još jednom source u ponedjeljak jedino kaj mi sada pada na pamet da je razlika u SHA1 ali jutro je pametnije od večeri. 

Jesi provjerio razliku u slanju dijela sa SHA1 datum/vrijeme racuna to mi trenutno pada na pamet.

 

Ovaj red mi se čini da ima grešku:   

+ StringReplace(vDatumVrijemeRacuna,'T','',[rfReplaceAll])

Prema specifikaciji treba biti space između datuma i vremena, ali i kada to popravim i to mi daje različit kod.

Napravio sam u php-u algoritam za potpis i on mi daje isti rezultat kao i Raverus.FiskalizacijaDEV.EXE.

Zaštitni kod generiram funkcijom openssl_sign($s, $zastitni_kod, $key, OPENSSL_ALGO_SHA1);

Ne kužim baš taj dio tvojeg programa, pa ne mogu otkriti u čemu je problem.

 

Sad sam i ja ponukan krenuo usporediti ZKI iz Raverusa EXE i funkcije IzracunajZastKod(zzk:AnsiString; aKey: xmlSecKeyPtr): AnsiString; I kod mene je razlika. 

Opet je problem u UNICODE-u i tipovima string varijabli. Ali nikako da dobijem isti ZKI. Jel još netko usporedio rezultate.

CipeXP jel si ti usporedio svoj ZKI s Raverusom ?

Nov 19, 2012 at 9:17 AM

Samo da dodam da na delphi 2007 sve radi bez problema, dakle ZKI iz delphija i ZKI iz raverusa.exe je isti

Nov 19, 2012 at 3:27 PM

>CipeXP jel si ti usporedio svoj ZKI s Raverusom ?

da, nema razlike "delphi 7".

Nov 19, 2012 at 4:02 PM

Ja koristim XE2

Nov 19, 2012 at 4:22 PM
Edited Nov 19, 2012 at 5:12 PM
dubravko wrote:

Ja koristim XE2

Da, očito ne radi kod svih UNICODE verzija. Razlika je kod MD5 poziva. Result je različit ovisno o verziji.  S 2007 je ok a s 2009, XE i XE2 ne.   

 

with TIdHashMessageDigest5.Create do

begin      

  result := lowercase(HashStringAsHex( result ));

  free; 

end;

 

Nov 19, 2012 at 5:10 PM
Edited Nov 19, 2012 at 5:13 PM

 

Uh google pomogao nakon cjelodnevnog kopanja. Proradilo. Dakle ovo važi ili za CipeXE primjer ili za Marekiusov projekt

1. Kao prvo kopirajte MessageDigest_5.pas i dodajte ga u svoj projekt ili samo dodajte novi path u project. Ta pas je sastavni dio DELPHI 2009-XE2 i nalazi se  u source\Win32\soap\wsdlimporter folderu

2. u procu u kojem vam se nalazi procedure za generiranje ZKI dodajte u USES  Types, MessageDigest_5;

3. Promijenite postojeću funkciju s ovom izmijenjenom 

function IzracunajZastKod(zk:AnsiString;aKey:xmlSecKeyPtr):AnsiString;
var  ret:integer;  t_ctx:xmlSecTransformCtxPtr;
     transformCtx : xmlSecTransformCtx;
     signMethod:xmlSecTransformPtr; 
     data:xmlSecBytePtr;datasize:integer;
     dsigRefCtx:xmlSecDSigReferenceCtxPtr ;
     rsa_sha1MethodId : xmlSecTransformId;
     MD5: IMD5; 

const xmlSecTransformDataTypeBin:cardinal =$0001;
begin
    result := '';
    data := xmlSecBytePtr( pansichar(zk));
    datasize := length(zk);
    t_ctx := @(transformCtx);
    xmlSecTransformCtxInitialize(t_ctx);
    if not assigned(t_ctx) or assigned(t_ctx.result) or (t_ctx.status<>xmlSecTransformStatusNone) 
    or not assigned(data) or (dataSize=0) or not assigned(aKey) then exit;
    if assigned(t_ctx.uri) then exit;

    rsa_sha1MethodId :=  xmlSecTransformRsaSha1GetKlass;
    signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx,rsa_sha1MethodId);
    if not assigned (signMethod) then exit;
    signMethod.operation := xmlSecTransformOperationSign;
    xmlSecTransformSetKey(signMethod, aKey);
    
    ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
    if(ret < 0) then exit;
    ret := xmlSecTransformDefaultPushBin( t_ctx.first,data,dataSize,1, t_ctx);
    if(ret < 0) then exit;
    
    result :=pAnsiChar(t_ctx.result.data) ;
   
   ///
   /// Ovo je novi dio
   ///

    MD5 := GetMD5;
    MD5.Init;
    MD5.Update(TByteDynArray(RawByteString(result)), Length(result));
    result := LowerCase(MD5.AsString);

    t_ctx.status := xmlSecTransformStatusFinished;
end;

 

I to je to. Dobar tek


Nov 19, 2012 at 8:16 PM

zahvalan do groba samo da ga još usporedim sa Raverusom. Imam blagi osjećaj da će me opet Delphi 10 ubiti u pojam.

Nego usput jedno glupo pitanje u vezi zaštitnog koda.

Kak se kuži da se radi o računu 1 i poslovnom prostoru 001 a da se ne radi o računu 10 i poslovnom prostoru 01 ?

Nov 19, 2012 at 10:13 PM

Mora ti radit na 2010 isto. Pa za zaštitni kod je sasvim svejedno što je br. računa, a što poslovni prostor. Bitan je samo ukupni niz kao zadani string. Koliko sam shvatio PU neće vršiti kontrolu ispravnosti ZKI-a već samo mora postojati mogućnost njegove provjere na samoj kasi. 

Nov 20, 2012 at 8:51 AM

Svejedno mi vraća drugačiji kod od Reverus-a ALI :

<tt>Poštovani,</tt>

<tt> </tt>
<tt>Ako je zaštitni kod ispravno implementiran sukladno danom algoritmu jedino korisnik sa svojim certifikatom može ponovo kreirati isti zaštitni kod za iste ulazne parametre.</tt>

<tt>Ne postoji referentni rezultat tj. zaštitni kod prema kojem bi se mogao usporediti vaš rezultat.</tt>
<tt>Najvažnije je da vaša implementacija daje ispravno oblikovan rezultat  (32-znamenkasti broj zapisan u heksadecimalnom formatu, brojevi i mala slova: 0-9, a-f) i da se za iste ulazne parametre i upotrijebljen certifikat generira isti zaštitni kod. </tt>
Lijep pozdrav,
Fiskalizacija Help 

Po ovome bitno je da je uvijek isti na osnovu parametara .o)

U svakom slučaju hvala

Coordinator
Nov 20, 2012 at 8:54 AM

Znači - ako ja odlučim da će u mom programu ZKI biti nešto sasvim deseto, uz uvjet da je rezultat "ispravno oblikovan" - to je ok ?   Dajte, molim vas, koji diletanti pišu te odgovore :)

Nov 20, 2012 at 9:02 AM

Po njihovom odgovoru uopće izgleda nije bitan ZKI (nebitan podatak ali neka se nađe) .o))) 

U svakom slučaju meni za Delphi 2010 ostaje varijanta da ga pokupim preko vašeg dll-a .o)

Nov 20, 2012 at 9:12 AM

Ma mora radit. Provjeri deklaraciju svih string varijabli dali su AnsiString

 

Nov 20, 2012 at 1:53 PM

za one koji imaju problema sa timout opcijama, delphi 7 ima bugu SOAPHTTPTrans.pas, treba pas kopirati u build path i prepravit slijedeće u funkciji THTTPReqResp.Send(), inache javlja grešku kod prvog slanja.

    { Timeouts old}
{    if FConnectTimeout > 0 then
      Check(InternetSetOption(Request, INTERNET_OPTION_CONNECT_TIMEOUT, Pointer(@FConnectTimeout), SizeOf(FConnectTimeout)));
    if FSendTimeout > 0 then
      Check(InternetSetOption(Request, INTERNET_OPTION_SEND_TIMEOUT, Pointer(@FSendTimeout), SizeOf(FSendTimeout)));
    if FReceiveTimeout > 0 then
      Check(InternetSetOption(Request, INTERNET_OPTION_RECEIVE_TIMEOUT, Pointer(@FReceiveTimeout), SizeOf(FReceiveTimeout)));}
     

    { Timeouts new }
    if FConnectTimeout > 0 then
      Check(not InternetSetOption(Request, INTERNET_OPTION_CONNECT_TIMEOUT, Pointer(@FConnectTimeout), SizeOf(FConnectTimeout)));
    if FSendTimeout > 0 then
      Check(not InternetSetOption(Request, INTERNET_OPTION_SEND_TIMEOUT, Pointer(@FSendTimeout), SizeOf(FSendTimeout)));
    if FReceiveTimeout > 0 then
      Check(not InternetSetOption(Request, INTERNET_OPTION_RECEIVE_TIMEOUT, Pointer(@FReceiveTimeout), SizeOf(FReceiveTimeout)));

btw, na xp strojevima timeout ne radi sa IE6, nisam oprova IE7, ali sa IR8 radi!

Nov 21, 2012 at 9:19 AM
tZac wrote:

 

Uh google pomogao nakon cjelodnevnog kopanja. Proradilo. Dakle ovo važi ili za CipeXE primjer ili za Marekiusov projekt

1. Kao prvo kopirajte MessageDigest_5.pas i dodajte ga u svoj projekt ili samo dodajte novi path u project. Ta pas je sastavni dio DELPHI 2009-XE2 i nalazi se  u source\Win32\soap\wsdlimporter folderu

2. u procu u kojem vam se nalazi procedure za generiranje ZKI dodajte u USES  Types, MessageDigest_5;

3. Promijenite postojeću funkciju s ovom izmijenjenom 

function IzracunajZastKod(zk:AnsiString;aKey:xmlSecKeyPtr):AnsiString;
var  ret:integer;  t_ctx:xmlSecTransformCtxPtr;
     transformCtx : xmlSecTransformCtx;
     signMethod:xmlSecTransformPtr; 
     data:xmlSecBytePtr;datasize:integer;
     dsigRefCtx:xmlSecDSigReferenceCtxPtr ;
     rsa_sha1MethodId : xmlSecTransformId;
     MD5: IMD5; 

const xmlSecTransformDataTypeBin:cardinal =$0001;
begin
    result := '';
    data := xmlSecBytePtr( pansichar(zk));
    datasize := length(zk);
    t_ctx := @(transformCtx);
    xmlSecTransformCtxInitialize(t_ctx);
    if not assigned(t_ctx) or assigned(t_ctx.result) or (t_ctx.status<>xmlSecTransformStatusNone) 
    or not assigned(data) or (dataSize=0) or not assigned(aKey) then exit;
    if assigned(t_ctx.uri) then exit;

    rsa_sha1MethodId :=  xmlSecTransformRsaSha1GetKlass;
    signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx,rsa_sha1MethodId);
    if not assigned (signMethod) then exit;
    signMethod.operation := xmlSecTransformOperationSign;
    xmlSecTransformSetKey(signMethod, aKey);
    
    ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
    if(ret < 0) then exit;
    ret := xmlSecTransformDefaultPushBin( t_ctx.first,data,dataSize,1, t_ctx);
    if(ret < 0) then exit;
    
    result :=pAnsiChar(t_ctx.result.data) ;
   
   ///
   /// Ovo je novi dio
   ///

    MD5 := GetMD5;
    MD5.Init;
    MD5.Update(TByteDynArray(RawByteString(result)), Length(result));
    result := LowerCase(MD5.AsString);

    t_ctx.status := xmlSecTransformStatusFinished;
end;

 

I to je to. Dobar tek


Radi u Delphiju XL2! s time da je potrebno promjeniti red

+ StringReplace(vDatumVrijemeRacuna,'T','',[rfReplaceAll]) u

u

+ StringReplace(vDatumVrijemeRacuna,'T',' ',[rfReplaceAll])

Nov 21, 2012 at 11:06 AM
marekius wrote:

Po njihovom odgovoru uopće izgleda nije bitan ZKI (nebitan podatak ali neka se nađe) .o))) 

U svakom slučaju meni za Delphi 2010 ostaje varijanta da ga pokupim preko vašeg dll-a .o)

Nisi u pravu. Potpuno je smisleno. Nitko osim tebe ne može generirati ZKI, to mu je upravo i smisao. Ne može, jer se ne može predstaviti u tvoje ime, odnosno potpisati ulazne podatke tvojim certifikatom.  ZKI štiti integritet podataka i identitet izdavatelja. Ono na što se trebaš posvetiti je nepromjenjivost ulaznih podataka. Time se čuvaš od toga da netko pošalje lazni račun ili lažni iznos, (kao integritet podataka), a istovremeno  i tebe drže u šaci jer naknadno ne možeš fiskalizirati isti račun s drugim vrijednostima (npr. izmjenjenim ukupnim iznosom).

Nov 28, 2012 at 8:16 AM

I je li je tko uspio validirati digitalni potpis odgovora?  Mislim, pomoću xmlsec lib-a?

Dec 24, 2012 at 8:49 AM
Edited Dec 24, 2012 at 8:49 AM
dubravko wrote:
tZac wrote:

 

Uh google pomogao nakon cjelodnevnog kopanja. Proradilo. Dakle ovo važi ili za CipeXE primjer ili za Marekiusov projekt

1. Kao prvo kopirajte MessageDigest_5.pas i dodajte ga u svoj projekt ili samo dodajte novi path u project. Ta pas je sastavni dio DELPHI 2009-XE2 i nalazi se  u source\Win32\soap\wsdlimporter folderu

2. u procu u kojem vam se nalazi procedure za generiranje ZKI dodajte u USES  Types, MessageDigest_5;



Radi u Delphiju XL2! s time da je potrebno promjeniti red

+ StringReplace(vDatumVrijemeRacuna,'T','',[rfReplaceAll]) u

u

+ StringReplace(vDatumVrijemeRacuna,'T',' ',[rfReplaceAll])

 

Prije svega velika hvala svima, naročito kolegama Dubravku imarekiusu. Uštedjeli su nam svima jako puno vremena.

Ovdje još nedostaje i "System.Types" pod uses deklaracijom, ali vjerujem da je to većina ispravila.

 

Ja koristim DelphiXE2, napravljeno je sve prema preporukama kolega, rporuke o poslovnom prostoru i račun uredno prolazi, dobivam nazad uredan JIR.

Međutim primjetio sam da ponekad za različite ulazne parametre (Drugačiji datum i vrijeme računa, broj računa, iznos računa) dobivam jedan te isti ZKI.

Ponekad kada se promjeni iznos ZKI bude različit, a nekada mi bude isti kao i neki prethodno generirani račun.

Da li je još netko primjetio sličnu situaciju ?

Dec 24, 2012 at 11:21 AM

>Ponekad kada se promjeni iznos ZKI bude različit, a nekada mi bude isti kao i neki prethodno generirani račun.

zki mora biti jedinstven??? valjda!

upravo sada istražujem priču,

neka je greška definitivno, i nema veze sa verzijom delphija... Meni se na Delphi 7 dogadja da se ponovi ključ.

kod testiranja usporedbe sa dotnet verzijiom neke ključeve definitivno računa različito!

 

 

Dec 24, 2012 at 12:00 PM
Edited Dec 24, 2012 at 12:03 PM

Hm, mi vrtimo JIR I ZKI već u živo u dućanu s demo certifikatom cca. 2 tjedna. Nema duplića. A i marekius je izvrtio mislim 10000 proba pa je sve ok. Problem je što se ZKI dobija svaki put, bez obzira na točnost predaje parametara, pa je teško skužit kad je krivi, ako se ne komparira sa Raverusom. 

Dec 24, 2012 at 12:41 PM

Komparirano sa službenim kodom iz tehničkih uputa, nekad je isti a nekad drugačiji...

Mislim da znam u cemu je stvar, kod prebacivanja rezultat buffera null može bit bilo di u rezultatu, a pchar tu odreže.

kad nulla nema rezultat je isti ko i dotnet, a svi rezultatu koji počinju sa null daju isti HashValue.

Dec 24, 2012 at 1:31 PM

evo već dva sata gulim po tome i izgleda da je stvarno problem sa pchar.

Evo promjera koji radi jednako ko i dotnet, osim kad su u igri hrvatska slova (dotnet potpisuje Š jednako ko i š, očigledno parsira znakove po kodnim stranicama). S obzirom da polja koja idu u sami zki ne bi trebala imat hrvatske znakove, mislim da to nije problem!

Inache nisam imao vremena za neka elegantna rješenja pa evo testne verzije di se može svaki korak kontrolirat:

function IzracunajZastKodTest(zk:string;aKey:xmlSecKeyPtr):string;
var  ret:integer;  t_ctx:xmlSecTransformCtxPtr;
     transformCtx : xmlSecTransformCtx;
     signMethod:xmlSecTransformPtr;
     data:xmlSecBytePtr;datasize:integer;
     dsigRefCtx:xmlSecDSigReferenceCtxPtr ;
     rsa_sha1MethodId : xmlSecTransformId;
    
     bptr:xmlSecBytePtr; aByte:xmlSecByte;
      ap:Pointer; i:integer;
      AStream: TStream ;
      StrBuffer:longInt;
const xmlSecTransformDataTypeBin:cardinal =$0001;
begin
    result := '';
    data := xmlSecBytePtr( pansichar(zk));
    datasize := length(zk);
    t_ctx := @(transformCtx);
    xmlSecTransformCtxInitialize(t_ctx);
    if not assigned(t_ctx) or assigned(t_ctx.result) or (t_ctx.status<>xmlSecTransformStatusNone)
    or not assigned(data) or (dataSize=0) or not assigned(aKey) then Exception.Create('Kontext za izračun zaštitnog ključa nije pravilno inicijaliziran!');
   
    if assigned(t_ctx.uri) then Exception.Create('Uri kontexta ne smije biti dodijeljen!');

    rsa_sha1MethodId :=  xmlSecTransformRsaSha1GetKlass;
    signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx,rsa_sha1MethodId);
    if not assigned (signMethod) then exit;
    signMethod.operation := xmlSecTransformOperationSign;
    xmlSecTransformSetKey(signMethod, aKey);
   
    ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
    if(ret < 0) then exit;
    ret := xmlSecTransformDefaultPushBin( t_ctx.first,data,dataSize,1, t_ctx);
    if(ret < 0) then exit;
   
   //Result := pchar(t_ctx.result.data);
    AStream := TMemoryStream.Create;
    try
      StrBuffer :=  Integer(t_ctx.result.data);
      for i:=0 to t_ctx.result.size-1 do begin
        ap := Pointer(StrBuffer);
        bptr := Pointer(ap);
        aByte := bptr^;
        AStream.Write(aByte,1);
        inc(StrBuffer);
      end;
      AStream.Position := 0;
   
      with TIdHashMessageDigest5.Create do begin
        result := LowerCase(AsHex(HashValue( AStream )));
  //      result := LowerCase(AsHex(HashValue( result )));
        free;
      end;
      t_ctx.status := xmlSecTransformStatusFinished;
    finally
      AStream.Free;
    end;
end;

Dec 24, 2012 at 1:50 PM

Može jedan primjer samo formiranog stringa sa elementima računa koji predajete u ZKI proceduru, a koja daje tak pogrešan ZKI. Pa da mogu probati kod sebe

Dec 24, 2012 at 1:54 PM

Evo još se gnjavim sa svime time, da ne budem lijen napravio sam dodatnu formu koja na osnovu ulaznih parametara generira samo ZKI, bez slanja cijelog XML-a u CIS.

 

I na toj novoj formi upita poziv funkcije:

IzracunajZastKod(Ulazni_kod,CIS_Init(OIB,CERTIFIKAT,LOZINKA).signKey);

daje nekada isti a nekada različiti kod. Još veći problem je što poziv te funkcije sa istim ulaznim parametrima ne daje isti rezultat kao i kada ga koristim na glavnoj formi za unos u bazu podataka itd.

 

Pretpotstavljam da najveću ulogu za generiranje zaštitnog koda ima zadnji dio stringa gdje se nalazi iznos. Bilo bi dobro ako netko može dodatno testirati račune sa istim iznosom, ali različitim vremenima i različitim rednim brojem računa.

Jedan kolega mi je preporučio da sve ulazne stringove za generiranje parametara dodatno deklariram kao UTF8STRING iako bi unutar Delphi-a već morao biti utf8.

Njemu je to navodno pomoglo da rješi problem, međutim kod mene i nakon toga se događa da mi se:

1.) ponavljaju pojedini ključevi.

2.) isti ulazni parametri na različitim formama gdje se poziva "IzracunajZastKod" ne daje isti rezultat.

Dec 24, 2012 at 2:05 PM

Na svim delphijima koji rade sa unicode stringovima je problem u deklaraciji stringova. Probaj to još jednom provjeriti, uz obavezno ansistring deklaracije i sl.

Dec 24, 2012 at 2:11 PM
tzac wrote:

Može jedan primjer samo formiranog stringa sa elementima računa koji predajete u ZKI proceduru, a koja daje tak pogrešan ZKI. Pa da mogu probati kod sebe

Evo ih nekoliko koji daju isti ZKI:

 

9806937635024.21.2012 09:29:292800001506.30

9806937635024.12.2012 09:30:322900001631.30

9806937635024.12.2012 10:56:553000001100.00

9806937635024.12.2012 14:04:093100001100.00

 

Isti ovi parametri na glavnoj formi računa sa upisima u bazu podataka itd. daje jedan (isti) ZKI, dok na pomoćnoj formi za kontrolu sa ručnim unosom dobijam nekakav drugi ZKI, ali opet isti za opisana 4 ulazna stringa.

Dec 24, 2012 at 3:00 PM
Edited Dec 24, 2012 at 3:10 PM

Evo koje ZKI ja dobivam za stringove koje si dao

9806937635024.21.2012 09:29:292800001506.30
ZKI: aeef95867f7d080f876bdb44e9965861

9806937635024.12.2012 09:30:322900001631.30
ZKI:edb711585419348394ae37aec1a46e1c

 

9806937635024.12.2012 10:56:553000001100.00
ZKI:ae2fded4a22ee12700f0f927bd0a7c81

9806937635024.12.2012 14:04:093100001100.00
ZKI:84395b196dfb01be23d4f7d3b8f0cdc0 

Dakle različite. Samo ih ionako ne možemo provjeriti jel ovise i o ključu koji svaki od nas koristi. Jedino što ih možemo provući kroz Raverus pa usporediti

Dec 24, 2012 at 3:16 PM
tZac wrote:

Evo koje ZKI ja dobivam za stringove koje si dao

9806937635024.21.2012 09:29:292800001506.30
ZKI: aeef95867f7d080f876bdb44e9965861

9806937635024.12.2012 09:30:322900001631.30
ZKI:edb711585419348394ae37aec1a46e1c

 

9806937635024.12.2012 10:56:553000001100.00
ZKI:ae2fded4a22ee12700f0f927bd0a7c81

9806937635024.12.2012 14:04:093100001100.00
ZKI:84395b196dfb01be23d4f7d3b8f0cdc0 

 

Hvala na trudu, vjerovatno je za tvoj certifikat neka druga kombinacija ulaznog stringa sa certifikatom. Gledam cijelo vrijeme da nešto nisam promašio sa pretvorbama UTF8 u AnsiString ili nešto takvoga, ali još uvijek ne pronalazim grešku.

 

Pokušavam implementirati novu test funkciju za ZKI koju je dao cipexp, međutim na ovome dijelu mi javlja sintaktičku grešku

Result:=LowerCase(AsHex(HashValue(Astream))); // Undeclared identifier: 'AsHex'

Očito mi nedostaje neki Unit u deklaraciji, pretpotstavljam da bi trebalo biti u "idHash", ili "IdHashMessageDigest", međutim kod mene to ne prolazi

Kod mene je deklarirano sljedeće:

uses
libxml2, libxslt, libxmlsec, SysUtils, Classes, Dialogs, SOAPHTTPTrans, XMLDoc, XMLIntf, Variants,
ComObj,Forms,IdHashMessageDigest, idHash, libeay32,MessageDigest_5,System.Types, //idHashSHA1;
DBAccess, Data.DB, MemDS, MyAccess,MemData; // ovaj dio je za povezivanje sa bazom, nema veze sa potpisivanjem

Dec 24, 2012 at 3:20 PM

Da CipeXp ti radi na Delphi 2007, a u XE ti ta funkcija ne prolazi. Imaš moj primjer te linije za XE delphi

Dec 27, 2012 at 8:08 AM

Kod mene još uvijek nije rješen problem još dobijam duple ZKI-e za različite račune. Evo primjera nove funkcije izračuna ZKI-a preprevljene za XE2, možda sam promašio nešto.

Da izbjegnem moguće greške sa čitanjem podataka iz baze testiranje je napravljeno sa podacima direktno sa forme.

 

MaskEdit3.Text:=MaskEdit20.Text+ // Oib
                     MaskEdit2.Text+' '+MaskEdit27.Text+ // datum i vrijeme
                     MaskEdit1.Text+ // broj računa
                     MaskEdit4.Text+ // poslovni prostor
                     Zarez2Tocka(iznos); // iznos računa zamjenjen sa točkom

     S:=UTF8string(MaskEdit3.Text); // prijedlog dodatnog poziva UTF8string funkcije koji je kolegi rješio problem (Delphi2010)

     //MaskEdit5.Text:= IzracunajZastKod(S,CIS_Init(OIB,CERTIFIKAT,LOZINKA).signKey);
     MaskEdit5.Text:= IzracunajZastKodTest(S,CIS_Init(OIB,CERTIFIKAT,LOZINKA).signKey); // OIB,CERTIFIKAT i LOZINKA isto imaju dodatnu pretvorbu UTF8

 

function IzracunajZastKodTest(zk:string;aKey:xmlSecKeyPtr):string;
         var ret:integer;
             t_ctx:xmlSecTransformCtxPtr;
             transformCtx : xmlSecTransformCtx;
             signMethod:xmlSecTransformPtr;
             data:xmlSecBytePtr;
             datasize:integer;
             dsigRefCtx:xmlSecDSigReferenceCtxPtr ;
             rsa_sha1MethodId : xmlSecTransformId;

             ////idmd5 : TIdHashMessageDigest;
             MD5:IMD5; // dodano za Delphi XE2

             // nova deklaracija varijabli u odnosu na prethodnu verziju
             bptr:xmlSecBytePtr;
             aByte:xmlSecByte;
             ap:Pointer;
             i:integer;
             AStream:TStream;
             StrBuffer:longInt;
        const xmlSecTransformDataTypeBin:cardinal =$0001;
begin
     result := '';
     data := xmlSecBytePtr( pansichar(zk));
     datasize := length(zk);
     t_ctx := @(transformCtx);
     xmlSecTransformCtxInitialize(t_ctx);

     if not assigned(t_ctx) or
        assigned(t_ctx.result) or
        (t_ctx.status<>xmlSecTransformStatusNone) or
        not assigned(data) or
        (dataSize=0) or
        not assigned(aKey)
     then
     begin
          Exception.Create('Kontext za izračun za�titnog ključa nije pravilno inicijaliziran !');
          exit;
     end;

     if assigned(t_ctx.uri) then
     begin
          Exception.Create('Uri kontexta ne smije biti dodjeljen !');
          exit;
     end;

     rsa_sha1MethodId :=  xmlSecTransformRsaSha1GetKlass;
     signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx,rsa_sha1MethodId);
     if not assigned (signMethod) then
     begin
          exit;
     end;
     signMethod.operation := xmlSecTransformOperationSign;
     xmlSecTransformSetKey(signMethod, aKey);

     ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
     if(ret < 0) then
     begin
          exit;
     end;
     ret := xmlSecTransformDefaultPushBin( t_ctx.first,data,dataSize,1, t_ctx);
     if(ret < 0) then
     begin
          exit;
     end;

     // Ovo je novi dio koji radi preko Streama

     AStream:= TMemoryStream.Create;
     try
        StrBuffer := Integer(T_ctx.result.data);
        for i:=0 to t_ctx.result.size-1 do
        begin
             ap:= Pointer(StrBuffer);
             bptr := Pointer(ap);
             aByte := bptr^;
             AStream.Write(aByte,1);
             inc(StrBuffer);
        end;
        AStream.Position:=0;

        {
        // Ovaj dio je za Delphi7
        with TIdHashMessageDigest5.Create do
        begin
             Result:=LowerCase(AsHex(HashValue(Astream)));
             Free;
        end;
        }


        // Novi ispravljeni dio za XE2
        // ------------------------
        MD5 := GetMD5;
        MD5.Init;
        //MD5.Update(TByteDynArray(RawByteString(result)),Length(result)); // stari dio koda tZac
        MD5.Update(TByteDynArray(Astream),SizeOf(Astream)); // Novo
        result:= LowerCase(MD5.AsString);
        t_ctx.status := xmlSecTransformStatusFinished;
        // ------------------------


        t_ctx.status:= xmlSecTransformStatusFinished;

     finally
        AStream.Free;
     end;
end;

Dec 27, 2012 at 10:13 AM
cipexp wrote:

Komparirano sa službenim kodom iz tehničkih uputa, nekad je isti a nekad drugačiji...

Mislim da znam u cemu je stvar, kod prebacivanja rezultat buffera null može bit bilo di u rezultatu, a pchar tu odreže.

kad nulla nema rezultat je isti ko i dotnet, a svi rezultatu koji počinju sa null daju isti HashValue.

Da li se nekome događa i sa službenim kodom da ima duple ključeve ? Znači oni koji imaju rješenja u C# ili javi.

Još čekamo odgovor iz porezne uprave ali evo što kažu o tome iz apis-a:

 

1. Ako je ZKI algoritam ispravno implementiran sukladno Tehničkoj 
specifikaciji onda se praktično ne bi smjela ponoviti dva ista ZKI za 
različite ulazne podatke.
Gotovo ste sigurno pogrešno implementirali algoritam za ZKI ako već na 
malom uzorku primjera računa:
- za iste ulazne podatke i za isti certifikat ne dobijete uvijek isti ZKI
- za različite ulazne podatke i za isti certifikat ne dobijete uvijek 
različiti ZKI

2. Ovo pitanje je pravno/poslovne prirode i namijenjeno je Poreznoj 
upravi (fiskalizacija@porezna-uprava.hr).
Naša je preporuka da napravite isto ali svakako bi ovo pitanje trebali 
uputiti Poreznoj upravi za službeno mišljenje.

Dec 27, 2012 at 1:16 PM
krunof wrote:
cipexp wrote:

Komparirano sa službenim kodom iz tehničkih uputa, nekad je isti a nekad drugačiji...

Mislim da znam u cemu je stvar, kod prebacivanja rezultat buffera null može bit bilo di u rezultatu, a pchar tu odreže.

kad nulla nema rezultat je isti ko i dotnet, a svi rezultatu koji počinju sa null daju isti HashValue.

Da li se nekome događa i sa službenim kodom da ima duple ključeve ? Znači oni koji imaju rješenja u C# ili javi.

Još čekamo odgovor iz porezne uprave ali evo što kažu o tome iz apis-a:

Ne, kod novog algoritma svi zki-ovi su isti u službenoj i xmlsec verziji i za sada nema duplih.

Dec 27, 2012 at 1:17 PM
Edited Dec 27, 2012 at 1:25 PM

Prvo pozdravljam sve koji pomažu svojim kodom i savjetima.

Problem mi je dupli digitalni potpis (točnije 509Certificate node) s produkcijskom p12 datotekom. S demo pfx file-om sve radi uredno. Koristim delphi kod koji ste objavili u ovoj temi.

Isti problem i kod slanja računa i kod zahtjeva za poslovni prostor.

Hvala.

Dec 27, 2012 at 3:05 PM
zeljkost1 wrote:

Prvo pozdravljam sve koji pomažu svojim kodom i savjetima.

Problem mi je dupli digitalni potpis (točnije 509Certificate node) s produkcijskom p12 datotekom. S demo pfx file-om sve radi uredno. Koristim delphi kod koji ste objavili u ovoj temi.

Isti problem i kod slanja računa i kod zahtjeva za poslovni prostor.

Hvala.

importiraj p12 u explorer pa exportiraj pfx bez root certifikata.

Dec 27, 2012 at 4:25 PM

Moćda ti je problem što pretvarsš string u utf8

 S:=UTF8string(MaskEdit3.Text); // prijedlog dodatnog poziva UTF8string funkcije koji je kolegi rješio problem (Delphi2010))

A funckija izracunaj.... ima deklaraciju "string"
function IzracunajZastKodTest(zk:string;aKey:xmlSecKeyPtr):string;

probaj zamijeniti sa
function IzracunajZastKodTest(zk:UTF8String;aKey:xmlSecKeyPtr):UTF8String;


Dec 27, 2012 at 6:06 PM
cipexp wrote:
zeljkost1 wrote:

Prvo pozdravljam sve koji pomažu svojim kodom i savjetima.

Problem mi je dupli digitalni potpis (točnije 509Certificate node) s produkcijskom p12 datotekom. S demo pfx file-om sve radi uredno. Koristim delphi kod koji ste objavili u ovoj temi.

Isti problem i kod slanja računa i kod zahtjeva za poslovni prostor.

Hvala.

importiraj p12 u explorer pa exportiraj pfx bez root certifikata.

Maestro veliko ti hvala. Jako sam se danas iznervirao kad je počeo s radom produkcijski server a vraća mi grešku. Sad radi i račun i poslovni prostor. Nisam do sad radio s certifikatima pa mi je to nepoznato. Ima ljudi koji sve znaju i hoće da pomognu. Pozdrav.

Dec 27, 2012 at 7:42 PM

cipexp daj mi otprilike reci koja je razlika između pfx i p12

na žalost tek sutra ću imati p12 (produkcijski) na raspolaganju pa da se mogu odmah prihvatiti posla jer nemam namjeru tražiti korisnike za još jedan export

Dec 27, 2012 at 10:31 PM

Probao sam sve ovo što je naveo i cipex i krunof na XE2 ali mi uvijek izbacuje isti ZKI.

Štoviše nije bitno što se stavi kao ulaz jer je ZKI uvijek isti. Sada sam već nervozan pa da pitam jer ima netko neko rješenje.

Dec 27, 2012 at 10:32 PM
Edited Dec 27, 2012 at 11:03 PM

Uffff, I kod mene je bila greška u generiranju ZKI-a koji je CIPExp riješio. Problem je i kod mene bio sa ZKI za XE delphi za one slučajeve kada međurezultat operacije generiranja sadrži nulL bytove. Ono rješenje cipexp-ovog sourca je za delphi2007 tako da to nije radilo kao što je rekao KrunoF.  Dakle kod CipeXp radi ali na novijim delphijima ne radi opet radi UNICODE stringova. Ona korištena funkcija TStream radi isto kao unicode, pa njen rezultat treba prekonvertirat u AnsiString

Mislio sam da sam riješio ali opet čorak. Kopam dalje

Dec 27, 2012 at 11:01 PM

tzac - ALELUJA !

RADI. Mnogo hvala. Sada vidim i ja u čemu je štos. Skužio sam da što kod da upišem vraća uvijek isto ali nisam našao što "smrdi"

Sada je sve 5.

Dec 27, 2012 at 11:04 PM
Edited Dec 27, 2012 at 11:22 PM

Ma izgleda da opet imam na nekim primjerima razliku sa Raverusom. Idem kopat dalje

 

Dec 27, 2012 at 11:07 PM

pazi da ne iskopas preduboko:) sretno!

Dec 27, 2012 at 11:27 PM
Edited Dec 28, 2012 at 1:22 PM

Ma već sam u banani pa generiram greške kod testiranja. SVE RADI DOBRO. Krivo sam generirao ZKI kod Raverusa

Dec 28, 2012 at 8:41 AM

tZac, kod mene niti ova najnovija promjena ne radi. Izgleda da imamo nekakav "poseban" certifikat :)

Barem sam uočio grešku zbog čega imam razliku između zasebne test forme i forme računa. Izostavio sam broj naplatnog uređaja pri kreiranju ZKI-a na test formi :)

Nekada od šume ne vidiš drvo (ili obrnuto). Uglavnom, sada na test formi dobivam iste rezultate kao i na glavnoj formi računa, ali i dalje dobivam duple rezultate za različite ulaze. Ove dodatne pretvorbe tipa: "UTFstring(ulaz)" nemaju apsolutno nikakvog utjecaja na rezultat, možda pomaže na nižim verzijama Delphi-a, ali na XE ne vrijedi.

Dec 28, 2012 at 9:18 AM
Pa ja sam na XE. Mora bit neki štos. Pošalji mi taj test projekt pa da probam kod sebe ako želiš


Sent from my iPhone

krunof <notifications@codeplex.com> wrote:

>From: krunof
>
> tZac, kod mene niti ova najnovija promjena ne radi. Izgleda da imamo nekakav "poseban" certifikat :) Barem sam uočio grešku zbog čega imam razliku između zasebne test forme i forme računa. Izostavio sam broj naplatnog uređaja pri kreiranju ZKI-a na test formi :) Nekada od šume ne vidiš drvo (ili obrnuto). Uglavnom, sada na test formi dobivam iste rezultate kao i na glavnoj formi računa, ali i dalje dobivam duple rezultate za različite ulaze. Ove dodatne pretvorbe tipa: "UTFstring(ulaz)" nemaju apsolutno nikakvog utjecaja na rezultat, možda pomaže na nižim verzijama Delphi-a, ali na XE ne vrijedi.
>
>
Dec 28, 2012 at 9:24 AM

Za one koji imaju problema sa korištenjem produkcijske .p12 datoteke, a testni certifikat .pfx je radio

ubaciti ovaj dio koda prije slanja paketa. odnosno linije:  Result := SaljiSOAP_Racun(xmldata_potpisan,vZastitniKod);

 

var brisiOd, brisiDo: Integer; //gore deklarirati u funkciji

.......

//jednostavno ako postoji dupli <X509Certificate> .... </X509Certificate>, izbacuje jedan van

    if LastDelimiter('<X509Certificate>', xmldata_potpisan.Text) <> Pos('<X509Certificate>', xmldata_potpisan.Text) then begin
      brisiOd:= Pos('<X509Certificate>', xmldata_potpisan.Text);
      brisiDo:= Pos('</X509Certificate>', xmldata_potpisan.Text) +17;
      xmldata_potpisan.Text:= Trim(Copy(xmldata_potpisan.Text, 1, brisiOd -1) +Copy(xmldata_potpisan.Text, brisiDo +1, Length(xmldata_potpisan.Text)));
    end;

//kraj ubačenog koda

    Result := SaljiSOAP_Racun(xmldata_potpisan,vZastitniKod); //ova linija ostaje kak je, tu je samo za pozicioniranje gore navedenog koda

....

Isto je i kod prijave poslovnog prostora.

provjereno radi

pozzz

Dec 28, 2012 at 10:26 AM
Edited Dec 28, 2012 at 1:17 PM

tZac, molim te javi se na (Edit-mail preko kontakta na forumu), preko foruma ne mogu doći do tvog e-mail-a da pošaljem. Hvala.

Dec 28, 2012 at 11:15 AM
krunof wrote:

tZac, kod mene niti ova najnovija promjena ne radi. Izgleda da imamo nekakav "poseban" certifikat :)

Barem sam uočio grešku zbog čega imam razliku između zasebne test forme i forme računa. Izostavio sam broj naplatnog uređaja pri kreiranju ZKI-a na test formi :)

Nekada od šume ne vidiš drvo (ili obrnuto). Uglavnom, sada na test formi dobivam iste rezultate kao i na glavnoj formi računa, ali i dalje dobivam duple rezultate za različite ulaze. Ove dodatne pretvorbe tipa: "UTFstring(ulaz)" nemaju apsolutno nikakvog utjecaja na rezultat, možda pomaže na nižim verzijama Delphi-a, ali na XE ne vrijedi.

Meni je na XE2 ova promjena izračunavala krivi ZKI, pa sam definirao funkciju ovako:

function IzracunajZastKodTest(zk:ansistring;aKey:xmlSecKeyPtr):ansistring;

i ponovo dobivam ispravni ZKI, molio bi da još netko ovo provjeri.
Dec 28, 2012 at 11:35 AM
Edited Dec 28, 2012 at 11:57 AM

Točno, kopirao sam sinoć source od krunef, jer me nešto zeza formatiranje ovdje na web-u, pa sam na njega dodao korekcije, ali je zato greškom definicija funkcije ostala kriva. I kod mene je točno ovakva definicija kakvu si naveo dakle sa AnsiString-om. Isprika. Evo još jednom koda da nebi bilo zabune. 

function IzracunajZastKod(zzk: AnsiString; aKey: xmlSecKeyPtr): AnsiString;
var
  ret: integer;
  t_ctx: xmlSecTransformCtxPtr;
  transformCtx: xmlSecTransformCtx;
  signMethod: xmlSecTransformPtr;
  data: xmlSecBytePtr;
  datasize: integer;
  dsigRefCtx: xmlSecDSigReferenceCtxPtr;
  rsa_sha1MethodId: xmlSecTransformId;
  MD5: IMD5;

  bptr: xmlSecBytePtr;
  aByte: xmlSecByte;
  ap: Pointer;
  i: integer;
  AStream: TMemoryStream;
  StrBuffer: longInt;
const
  xmlSecTransformDataTypeBin: cardinal = $0001;
begin
  result := '';
  data := xmlSecBytePtr(PAnsiChar(zzk));
  datasize := length(zzk);
  t_ctx := @(transformCtx);
  xmlSecTransformCtxInitialize(t_ctx);
  if not Assigned(t_ctx) or Assigned(t_ctx.result) or
    (t_ctx.status <> xmlSecTransformStatusNone) or not Assigned(data) or
    (datasize = 0) or not Assigned(aKey) then
    exit;
  if Assigned(t_ctx.uri) then
    exit;

  rsa_sha1MethodId := xmlSecTransformRsaSha1GetKlass;
  signMethod := xmlSecTransformCtxCreateAndAppend(t_ctx, rsa_sha1MethodId);
  if not Assigned(signMethod) then
    exit;
  signMethod.operation := xmlSecTransformOperationSign;
  xmlSecTransformSetKey(signMethod, aKey);

  ret := xmlSecTransformCtxPrepare(t_ctx, xmlSecTransformDataTypeBin);
  if (ret < 0) then
    exit;
  ret := xmlSecTransformDefaultPushBin(t_ctx.first, data, datasize, 1, t_ctx);
  if (ret < 0) then
    exit;

  AStream := TMemoryStream.Create;
  try
    StrBuffer := integer(t_ctx.result.data);
    for i := 0 to t_ctx.result.size - 1 do
    begin
      ap := Pointer(StrBuffer);
      bptr := Pointer(ap);
      aByte := bptr^;
      AStream.Write(aByte, 1);
      inc(StrBuffer);
    end;
    AStream.Position := 0;
    result := MemoryStreamToString(AStream);
    MD5 := GetMD5;
    MD5.init;
    MD5.Update(TByteDynArray(result), length(result));
    result := LowerCase(MD5.AsString);
    t_ctx.status := xmlSecTransformStatusFinished;
  finally
    AStream.Free;
  end;
end;

function MemoryStreamToString(M: TMemoryStream): AnsiString;
begin
  SetString(result, PAnsiChar(M.Memory), M.size);
end;

Dec 28, 2012 at 12:49 PM

Super, hvala!

Dec 28, 2012 at 1:12 PM

Hvala i od mene još jednom, potvrđeno, verzija sa AnsiString radi i na XE2

Jan 11, 2013 at 3:35 PM

Taj kod koji koristi openssl vas zeza zbog bug-a (pretpostavljam u openssl). gnutls i mscrypto (a i openssl u vecini slucajeva) MORAJU generirati isti ZK.Kod rada sa xmlsec-om zna se dogoditi da je ctx.data = nil (tj. kada das StrPas(ctx.data) dobijes prazan string), e onda vam se dogodi da vam se za razlicite podatke ponavlja isti ZKI. Kada se koristi gnutls (unix) ili mscrypto xmlsec plugin onda je sve ok (zato i sumnjam na openssl). Ovaj zadnji kod koji koristi TMemoryStream moze biti od pomoci kada doleti prazan string ,ali svejedno opet je rezultat razlicit od mscrypto ili gnutls (koji su uvijek isti).

Jan 13, 2013 at 10:42 AM

eh..da probao sam i ovaj dio koda gore naveden pa se pitam cemu sluzi ovoliko varijabli  (StrBuffer,ap,bptr) ?

AStream := TMemoryStream.Create;
  try
{stari dio
  StrBuffer := integer(t_ctx.result.data); for i := 0 to t_ctx.result.size - 1 do begin ap := Pointer(StrBuffer); bptr := Pointer(ap); aByte := bptr^; AStream.Write(aByte, 1); inc(StrBuffer); end;
}
// novi dio - radi potpuno istu stvar (mada moze i bez aByte :=, tj. AStream.Write(t_ctx.result.data^ ....)
    for i := 0 to t_ctx.result.size - 1 do
    begin
aByte := t_ctx.result.data^;
  AStream.Write(aByte, 1); inc(t_ctx.result.data); end;

// novi dio end.

 AStream.Position := 0; result := MemoryStreamToString(AStream); MD5 := GetMD5; MD5.init; MD5.Update(TByteDynArray(result), length(result)); result := LowerCase(MD5.AsString); t_ctx.status := xmlSecTransformStatusFinished; finally AStream.Free; end;
Jan 27, 2013 at 7:11 PM

Pozdrav,

iako je sada već pomalo kasno, konačno sam u prilici objaviti kompletan (manje-više) lib za Delphi i fiskalizaciju temeljen na xmlsec-u.  Ranija objava nije bila moguća, a možda nekom bude od koristi:  http://sourceforge.net/projects/f4d

 

Feb 4 at 12:33 PM
Evo da oživim i ovu temu, a sve vezano za najavu gašenja SSL v3 protokola i korištenje TLS protokola.

Ajde da nas već dokazani stručnjaci ( npr. Cipexe ) na tom području prosvijetle i da nama većini copy / paste majstorima ukažu kako stojimo s ovdje izrađenim rješenjem na Delphiju

Hvala unaprijed