Using Delphi with CryptoSys API, CryptoSys PKI and FirmaSAT


It is possible to call all the functions in our cryptographic products CryptoSys API, CryptoSys PKI and FirmaSAT from Delphi. This page explains what we know and gives some sample code.

FirmaSAT | CryptoSys API | CryptoSys PKI Toolkit | Notes for programmers | Acknowledgements | Disclaimer | Contact | Spanish Español

The Delphi code on this page works for us using Delphi Builder 2010 on a Windows XP machine. There may well be better or more elegant ways of calling the functions. We don't know how backwards compatible this code is. We do not offer to provide updates for Delphi except for providing this sample code as is. Use at your own risk.

The code and links on this page are all the Delphi code we have. If anyone has any corrections or useful suggestions, we'd be delighted to hear from you. Please send us a message. For more info on creating interfaces see Writing an interface in another programming language.

FirmaSAT

Here is an (unsupported) Delphi interface to the functions in FirmaSAT including a series of tests and some test files: diFirmaSat.pas.zip (16 kB. Last updated 2010-03-18). The Delphi interfaces to the FirmaSAT functions are provided in the file diFirmaSat.pas. (Use at your own risk. No warranties, etc. See the Disclaimer below.)

You need to have installed both FirmaSAT and the CryptoSys PKI Toolkit on your system (FirmaSAT 4 and 5 do not require CryptoSys PKI). For more information see How to get started on the FirmaSAT page.

Note that the tests in TestFirmaSat require certain files to exist in a specified directory. The test files are provided in the zip file above. The directory is hardcoded in the code

const
  TEST_DIR = 'C:\Test\Muestra';

- you may need to edit this to suit your system.

SHA-1 and 2011 and 2012 changes: The above Delphi code was written in March 2010 for FirmaSAT 2. If you upgraded to FirmaSAT 3 or 4 or 5 there are no changes to make. All the declarations are still valid and should still work. The core DLL is still called diFirmaSAT2.dll and the functions all still work the same. The default algorithm is now SHA-1 instead of MD5, as required from 1 January 2011. If you pass a CFD version 2.2 or 3.2 XML file as input to FirmaSAT 5 it will cope. It should not be hard to add declarations for any new functions added since then.

For more information on the FirmaSAT function parameters and return values, see the C include file diFirmaSat2.h.

CryptoSys API

Here is a Delphi interface to all the functions in CryptoSys API with a start on some typical tests: diCryptoSys.pas.zip (11 kB. Last updated 2010-03-18). The function declarations and associated constants are in the file diCryptoSys.pas.

For more information on the CryptoSys API function parameters and return values, see the Main manual for CryptoSys API.

CryptoSys PKI Toolkit

Here is a provisional Delphi interface to all the functions in CryptoSys PKI with a few sample tests: diCrPKI.pas.zip (7 kB. Last updated 2010-03-17). The function declarations and associated constants are in the file diCrPKI.pas.

For more information on the CryptoSys PKI function parameters and return values, see the Main manual for CryptoSys PKI.

Pedro Miguel Martins has provided some code in Delphi that uses the Delphi interface to CryptoSys PKI to compute an RSA signature using the test key for the Portugal General Directorate of Taxes (Direcção Geral dos Impostos). See Delphi Code.

Notes for programmers

Variable types used in the interface:

C++ TypeDelphi TypeDescription
long, int Integer A signed 32-bit integer, passed by value
char *sz AnsiString ANSI string: a string of single-byte non-zero characters terminated by a zero byte
unsigned char *lp Array of Byte Byte array: an ordered sequence of single-byte values of any value in the range [0,255]
  1. All integer variables passed to our DLLs (and return values from them) must be of type Integer, a 32-bit signed integer.
  2. All strings are of type AnsiString. Attempting to pass a "normal" Unicode or Wide string will not work.
  3. Byte arrays should be of type Array of Byte.
  4. Strings and byte arrays that receive output need to be pre-dimensioned to the correct length before calling a DLL function. Then pass a Pointer as the parameter.
    buf : AnsiString;
    //...
    buf := AnsiString(StringOfChar(#0,nchars));
    ret := FOO_StringFunction(Pointer(buf), nchars, ...);
    
    arrbytes : Array of Byte;
    //...
    SetLength(arrbytes, nbytes);
    ret := FOO_ByteFunction(Pointer(arrbytes), nbytes, ...);
    
    These output parameters are expected as PChar PAnsiChar and PByte respectively. [PChar also seemed to work OK for us in early tests and the compiler didn't complain either].
  5. Constant strings passed as input can be simply passed as an AnsiString type. Constant byte arrays passed as input still need to be passed as a pointer (AFAWK).
  6. To pass a null pointer to either an AnsiString or Array of Byte, use the Delphi NIL value, as in
    nchars := SAT_CompileTime(NIL, 0);
    
  7. Depending on how you've defined your byte arrays, you pass pointers to them differently,
    abKey : Array of Byte;
    tag   : Array[0..15] of Byte;
    //...
    ret := GCM_Encrypt(NIL, 0, @tag[0], Length(tag), NIL, 0,
      Pointer(abKey), Length(abKey),...);
    
  8. For a reason we haven't worked out yet, re-using a dynamic byte array variable after using it in a DLL function can give erroneous results unless you re-do the SetLength operation
    SetLength(abOut, Length(abIn));
    
  9. Strings used in the _UpdateHex functions which are used as both input and to receive output, need to be declared as global vars, not local.

Acknowledgements

Thanks to Sebastian Jäschke and Humberto Souza for their help in providing example Delphi interfaces to CryptoSys API, without which we would not have been able to get started, and to Cesar Ruiz for his feedback. Thanks, too, to Neil Moffatt for his excellent Delphi Basics site.

Disclaimer

Our CryptoSys products are offered primarily with interfaces using the C/C++, C#, VB6/VBA and VB.NET languages. We don't offer to support any other interfaces or languages. We will try and help if we can. The code on this page is offered for free in good faith but may contain nuts and/or errors. Please make whatever checks you need to before purchase of the main product.

Contact

For more information or to comment on this page, please send us a message.

This page first published 13 March 2010. Last updated 5 January 2012