program TestFirmaSat;
{
Some tests for the Delphi/FreePascal interface to FirmaSAT
$Id: TestFirmaSat.pas $
Copyright (C) 2010-16 David Ireland, DI Management Services Pty Limited.
All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net>
Provided as is with no warranties. Use at your own risk.
Last updated:
$Date: 2016-01-27 04:41 $
$Revision: 7.2.0 $
Remember to unzip the test files from FirmaSAT-testfiles.zip into TEST_DIR.
}
{$APPTYPE CONSOLE}
{$mode Delphi}
uses
SysUtils, diFirmaSat;
const
{ WARNING: this is where we expect to find the test files.
CHANGE THIS TO SUIT }
TEST_DIR = 'C:\Test\Muestra';
CRLF = #13 + #10;
Procedure disp_error(nErrCode : Integer; showLast : Boolean = True);
const
MAX_CHARS = SAT_MAX_ERROR_CHARS;
var
msg : Array[0..MAX_CHARS-1] of AnsiChar;
nchars : Integer;
begin
Write('Error code ' + IntToStr(nErrCode));
nchars := SAT_ErrorLookup(msg, MAX_CHARS, nErrCode);
If (nchars > 0) then
Write(': ' + msg);
if showLast then
begin
nchars := SAT_LastError(msg, MAX_CHARS);
if (nchars > 0) then
Write(': ' + msg);
end;
WriteLn('');
end;
Function RequiredFilesExist : Boolean;
begin
Result := True; // Innocent until proven guilty
if Not FileExists('emisor.cer') then Result := False;
if Not FileExists('emisor.key') then Result := False;
if Not FileExists('detallista_base2015.xml') then Result := False;
if Not FileExists('V3_2_BadCurp.xml') then Result := False;
if Not FileExists('ejemplo_v32-base2015.xml') then Result := False;
if Not FileExists('ejemplo_v32-signed2015.xml') then Result := False;
if Not FileExists('AC4_SAT.cer') then Result := False;
if Not FileExists('hehf7712015z2.cer') then Result := False;
end;
// DO THE TESTS TO CALL FIRMASAT FUNCTIONS
Procedure do_tests;
var
ret : Integer;
nchars : Integer;
buf : AnsiString;
buf1 : AnsiString;
ch : Char;
fname : AnsiString;
newname : AnsiString;
keyfile : AnsiString;
certfile : AnsiString;
password : AnsiString;
elementName : AnsiString;
attributeName : AnsiString;
query : AnsiString;
digest : Array[0..SAT_MAX_HASH_CHARS-1] of AnsiChar;
numstr : Array[Byte] of AnsiChar;
begin
WriteLn('Running ' + ExtractFileName(ParamStr(0)) + ' at ' + DateTimeToStr(Now));
// Set current working directory to find test files
ChDir(TEST_DIR);
if Not RequiredFilesExist then
begin
WriteLn('Cannot find required files! Please make sure test files are copied to TEST_DIR.');
ReadLn;
Exit;
end;
WriteLn(CRLF + 'GENERAL:');
WriteLn('Interrogate the core diFirmaSat DLL:');
WriteLn('SAT_Version='+(IntToStr(SAT_Version)));
nchars := SAT_CompileTime(NIL, 0);
WriteLn('SAT_CompileTime returns nchars=' + IntToStr(nchars));
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_CompileTime(Pointer(buf), nchars);
WriteLn('SAT_CompileTime=' + buf);
Assert (nchars > 0);
nchars := SAT_ModuleName(NIL, 0, 0);
WriteLn('SAT_ModuleName returns nchars=' + IntToStr(nchars));
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_ModuleName(Pointer(buf), nchars, 0);
WriteLn('SAT_ModuleName=' + buf);
Assert (nchars > 0);
ch := Chr(SAT_LicenceType());
WriteLn('SAT_LicenceType='+ ch);
WriteLn(CRLF + 'TRY VALIDATING XML FILES:');
WriteLn('1. A valid one:');
fname := 'ejemplo_v32-signed2015.xml';
ret := SAT_ValidateXml(fname, 0);
WriteLn('SAT_ValidateXml(' + string(fname) + ') returns ' + IntToStr(ret) + ' (0=>success)');
WriteLn('2. An invalid one:');
fname := 'V3_2_BadCurp.xml';
ret := SAT_ValidateXml(fname, 0);
WriteLn('SAT_ValidateXml(' + string(fname) + ') returns ' + IntToStr(ret) + ' (expected error)');
If (ret <> 0) then disp_error(ret, False);
WriteLn(CRLF + 'FORM THE PIPESTRING FROM AN XML FILE:');
fname := 'ejemplo_v32-signed2015.xml';
nchars := SAT_MakePipeStringFromXml(NIL, 0, fname, 0);
WriteLn('SAT_MakePipeStringFromXml returns nchars=' + IntToStr(nchars));
{ This may be larger than required }
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_MakePipeStringFromXml(Pointer(buf), nchars, fname, 0);
{ Make sure we trim any trailing null characters }
buf := Copy(buf, 1, nchars);
WriteLn('SAT_MakePipeStringFromXml=' + CRLF + buf);
Assert(nchars > 0);
WriteLn(CRLF + 'SIGN AN XML FILE:');
fname := 'ejemplo_v32-base2015.xml';
newname := 'ejemplo_v32_signed_new.xml';
keyfile := 'emisor.key';
password := '12345678a'; // CAUTION: DO NOT HARD-CODE REAL PASSWORDS!
certfile := 'emisor.cer';
ret := SAT_SignXml(newname, fname, keyfile, password, certfile, 0);
WriteLn('SAT_SignXml("' + string(fname) + '"-->"' + string(newname) + '") returns ' + IntToStr(ret));
If (ret <> 0) then disp_error(ret);
Assert (0 = ret);
// Did we make a valid XML file?
ret := SAT_ValidateXml(newname, 0);
WriteLn('SAT_ValidateXml(' + string(newname) + ') returns ' + IntToStr(ret) + ' (0=>success)');
Assert(0 = ret);
WriteLn(CRLF + 'VERIFY A SIGNATURE IN AN XML FILE:');
WriteLn('1. One we know is good:');
fname := 'ejemplo_v32-signed2015.xml';
ret := SAT_VerifySignature(fname, '', 0);
WriteLn('SAT_VerifySignature(' + string(fname) + ') returns ' + IntToStr(ret) + ' (0=>success)');
Assert(0 = ret);
WriteLn('2. One we just made, so it should be good:');
fname := newname;
ret := SAT_VerifySignature(fname, '', 0);
WriteLn('SAT_VerifySignature(' + string(fname) + ') returns ' + IntToStr(ret) + ' (0=>success)');
Assert(0 = ret);
WriteLn(CRLF + 'FORM THE DIGEST OF THE PIPESTRING IN AN XML FILE:');
fname := 'ejemplo_v32-signed2015.xml';
nchars := SAT_MakeDigestFromXml(digest, Length(digest), fname, 0);
WriteLn('SAT_MakeDigestFromXml returns nchars=' + IntToStr(nchars));
if (nchars < 0) then disp_error(nchars);
WriteLn('Digest=' + digest);
Assert(nchars > 0);
WriteLn(CRLF + 'EXTRACT THE DIGEST FROM THE SIGNATURE IN AN XML FILE:');
fname := 'ejemplo_v32-signed2015.xml';
nchars := SAT_ExtractDigestFromSignature(digest, Length(digest), fname, '', 0);
WriteLn('SAT_ExtractDigestFromSignature returns nchars=' + IntToStr(nchars));
if (nchars < 0) then disp_error(nchars);
WriteLn('Digest=' + digest);
Assert(nchars > 0);
WriteLn(CRLF + 'EXTRACT AN ATTRIBUTE FROM AN XML FILE:');
fname := 'ejemplo_v32-signed2015.xml';
elementName := 'Comprobante';
attributeName := 'sello';
nchars := SAT_GetXmlAttribute(NIL, 0, fname, attributeName, elementName);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_GetXmlAttribute(Pointer(buf), nchars, fname, attributeName, elementName);
WriteLn('SAT_GetXmlAttribute(' + string(fname) + ', ' + string(attributeName) + ', ' + string(elementName) + ')=' + CRLF + string(buf));
end
else
disp_error(nchars);
Assert(nchars > 0);
WriteLn(CRLF + 'GET DETAILS OF X.509 CERTIFICATE:');
WriteLn('1. From embedded `certificado` in XML');
fname := 'ejemplo_v32-signed2015.xml';
WriteLn('Input file: ' + fname);
nchars := SAT_GetCertNumber(numstr, Length(numstr), fname, 0);
WriteLn('SAT_GetCertNumber returns nchars=' + IntToStr(nchars));
if (nchars < 0) then disp_error(nchars);
WriteLn('serialNumber=' + numstr);
nchars := SAT_GetCertExpiry(numstr, Length(numstr), fname, 0);
WriteLn('SAT_GetCertExpiry returns nchars=' + IntToStr(nchars));
if (nchars < 0) then disp_error(nchars);
WriteLn('notAfter=' + numstr);
Assert(nchars > 0);
WriteLn('2. From X.509 file');
fname := 'emisor.cer';
WriteLn('Input file: ' + fname);
nchars := SAT_GetCertNumber(numstr, Length(numstr), fname, 0);
WriteLn('SAT_GetCertNumber returns nchars=' + IntToStr(nchars));
if (nchars < 0) then disp_error(nchars);
WriteLn('serialNumber=' + numstr);
nchars := SAT_GetCertExpiry(numstr, Length(numstr), fname, 0);
WriteLn('SAT_GetCertExpiry returns nchars=' + IntToStr(nchars));
if (nchars < 0) then disp_error(nchars);
WriteLn('notAfter=' + numstr);
Assert(nchars > 0);
WriteLn(CRLF + 'GET CERTIFICATE AS A BASE64 STRING:');
fname := 'emisor.cer';
WriteLn('For file ' + string(fname) + '...');
nchars := SAT_GetCertAsString(NIL, 0, fname, 0);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_GetCertAsString(Pointer(buf), nchars, fname, 0);
WriteLn('SAT_GetCertAsString(' + string(fname) + ')=' + CRLF + string(buf));
WriteLn('Length of cert string=' + IntToStr(nchars));
end
else
disp_error(nchars);
Assert(nchars > 0);
// Compare against string from XML file
fname := 'ejemplo_v32-signed2015.xml';
WriteLn('For file ' + string(fname) + '...');
nchars := SAT_GetCertAsString(NIL, 0, fname, 0);
if (nchars >= 0) then
begin
buf1 := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_GetCertAsString(Pointer(buf1), nchars, fname, 0);
WriteLn('Length of cert string=' + IntToStr(nchars));
end
else
disp_error(nchars);
Assert(nchars > 0);
If buf <> buf1 then
WriteLn('ERROR: cert strings do not match!')
else
WriteLn('OK, cert strings match.');
WriteLn(CRLF + 'MAKE A SIGNATURE FROM A BASE XML FILE:');
fname := 'ejemplo_v32-base2015.xml';
keyfile := 'emisor.key';
password := '12345678a'; // CAUTION: DO NOT HARD-CODE REAL PASSWORDS!
nchars := SAT_MakeSignatureFromXml(NIL, 0, fname, keyfile, password);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_MakeSignatureFromXml(Pointer(buf), nchars, fname, keyfile, password);
WriteLn('SAT_MakeSignatureFromXml(' + string(fname) + ', ' + string(keyfile) + ')=' + CRLF + string(buf));
end
else
disp_error(nchars);
Assert(nchars > 0);
WriteLn(CRLF + 'SIGN A DETALLISTA XML FILE:');
fname := 'detallista_base2015.xml';
newname := 'detallista-new-signed.xml';
keyfile := 'emisor.key';
password := '12345678a'; // CAUTION: DO NOT HARD-CODE REAL PASSWORDS!
certfile := 'emisor.cer';
ret := SAT_SignXml(newname, fname, keyfile, password, certfile, 0);
WriteLn('SAT_SignXml("' + string(fname) + '"-->"' + string(newname) + '") returns ' + IntToStr(ret));
If (ret <> 0) then disp_error(ret);
Assert(0 = ret);
// Did we make a valid XML file?
fname := newname;
ret := SAT_ValidateXml(fname, 0);
WriteLn('SAT_ValidateXml(' + string(fname) + ') returns ' + IntToStr(ret) + ' (0=>success)');
If (ret <> 0) then disp_error(ret);
Assert(0 = ret);
// Is the signature valid?
ret := SAT_VerifySignature(fname, '', 0);
WriteLn('SAT_VerifySignature(' + string(fname) + ') returns ' + IntToStr(ret) + ' (0=>success)');
If (ret <> 0) then disp_error(ret);
Assert(0 = ret);
WriteLn(CRLF + 'EXTRACT AN ATTRIBUTE FROM A DETALLISTA XML FILE:');
fname := 'detallista-new-signed.xml';
elementName := 'detallista:detallista';
attributeName := 'documentStructureVersion';
nchars := SAT_GetXmlAttribute(NIL, 0, fname, attributeName, elementName);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_GetXmlAttribute(Pointer(buf), nchars, fname, attributeName, elementName);
WriteLn('SAT_GetXmlAttribute(' + string(fname) + ', ' + string(attributeName) + ', ' + string(elementName) + ')="' + string(buf) + '"');
end
else
disp_error(nchars);
Assert(nchars > 0);
// Check against the correct answer
if AnsiCompareStr(string(buf), 'AMC8.1')= 0 then
WriteLn('OK, attribute value is correct.')
else
WriteLN('ERROR: attribute value is wrong!');
Assert(AnsiCompareStr(string(buf), 'AMC8.1')= 0);
WriteLn(CRLF + 'QUERY KEY SIZE OF CERTIFICATE:');
fname := 'AC4_SAT.cer';
query := 'keySize';
nchars := SAT_QueryCert(NIL, 0, fname, query, 0);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_QueryCert(Pointer(buf), nchars, fname, query, 0);
WriteLn('SAT_QueryCert(' + string(fname) + ', ' + string(query) + ')=[' + string(buf) + ']');
end
else
disp_error(nchars);
Assert(nchars > 0);
WriteLn(CRLF + 'QUERY SIGNATURE ALGORITHM IN CERTIFICATES:');
fname := 'emisor.cer';
query := 'sigAlg';
nchars := SAT_QueryCert(NIL, 0, fname, query, 0);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_QueryCert(Pointer(buf), nchars, fname, query, 0);
WriteLn('SAT_QueryCert(' + string(fname) + ', ' + string(query) + ')=[' + string(buf) + ']');
end
else
disp_error(nchars);
Assert(nchars > 0);
fname := 'hehf7712015z2.cer';
query := 'sigAlg';
nchars := SAT_QueryCert(NIL, 0, fname, query, 0);
if (nchars >= 0) then
begin
buf := AnsiString(StringOfChar(#0,nchars));
nchars := SAT_QueryCert(Pointer(buf), nchars, fname, query, 0);
WriteLn('SAT_QueryCert(' + string(fname) + ', ' + string(query) + ')=[' + string(buf) + ']');
end
else
disp_error(nchars);
Assert(nchars > 0);
WriteLn(CRLF+'ALL DONE.');
end;
// MAIN PROCEDURE
begin
try
do_tests;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.