this slowpoke moves

WCrypt2 File Crypter

unit WCrypt2.pas :
unit wcrypt2;

{.DEFINE NT5}

{$ALIGN ON}

{$IFNDEF VER90}
{$WEAKPACKAGEUNIT}
{$ENDIF}

interface

uses
  Windows
{$IFDEF VER90}
  , Ole2
{$ENDIF};

const
  ADVAPI32 = 'advapi32.dll';
  CRYPT32 = 'crypt32.dll';
  SOFTPUB = 'softpub.dll';
{$IFDEF NT5}
  ADVAPI32NT5 = 'advapi32.dll';
{$ENDIF}

{Support Type}

type
  PVOID = Pointer;
  LONG = DWORD;
{$IFDEF UNICODE}
  LPAWSTR = PWideChar;
{$ELSE}
  LPAWSTR = PAnsiChar;
{$ENDIF}

//-----------------------------------------------------------------------------
    // Type support for a pointer to an array of pointer (type **name)
  PLPSTR = Pointer; // type for a pointer to Array of pointer a type
  PPCERT_INFO = Pointer; // type for a pointer to Array of pointer a type
  PPVOID = Pointer; // type for a pointer to Array of pointer a type
  PPCCERT_CONTEXT = Pointer; // type for a pointer to Array of pointer a type
  PPCCTL_CONTEXT = Pointer; // type for a pointer to Array of pointer a type
  PPCCRL_CONTEXT = Pointer; // type for a pointer to Array of pointer a type

function GET_ALG_CLASS(x: integer): integer;
function GET_ALG_TYPE(x: integer): integer;
function GET_ALG_SID(x: integer): integer;

const
  // Algorithm classes
  ALG_CLASS_ANY = 0;
  ALG_CLASS_SIGNATURE = (1 shl 13);
  ALG_CLASS_MSG_ENCRYPT = (2 shl 13);
  ALG_CLASS_DATA_ENCRYPT = (3 shl 13);
  ALG_CLASS_HASH = (4 shl 13);
  ALG_CLASS_KEY_EXCHANGE = (5 shl 13);

  // Algorithm types
  ALG_TYPE_ANY = 0;
  ALG_TYPE_DSS = (1 shl 9);
  ALG_TYPE_RSA = (2 shl 9);
  ALG_TYPE_BLOCK = (3 shl 9);
  ALG_TYPE_STREAM = (4 shl 9);
  ALG_TYPE_DH = (5 shl 9);
  ALG_TYPE_SECURECHANNEL = (6 shl 9);

  // Generic sub-ids
  ALG_SID_ANY = 0;

  // Some RSA sub-ids
  ALG_SID_RSA_ANY = 0;
  ALG_SID_RSA_PKCS = 1;
  ALG_SID_RSA_MSATWORK = 2;
  ALG_SID_RSA_ENTRUST = 3;
  ALG_SID_RSA_PGP = 4;

  // Some DSS sub-ids
  ALG_SID_DSS_ANY = 0;
  ALG_SID_DSS_PKCS = 1;
  ALG_SID_DSS_DMS = 2;

  // Block cipher sub ids
  // DES sub_ids
  ALG_SID_DES = 1;
  ALG_SID_3DES = 3;
  ALG_SID_DESX = 4;
  ALG_SID_IDEA = 5;
  ALG_SID_CAST = 6;
  ALG_SID_SAFERSK64 = 7;
  ALD_SID_SAFERSK128 = 8;
  ALG_SID_SAFERSK128 = 8;
  ALG_SID_3DES_112 = 9;
  ALG_SID_CYLINK_MEK = 12;
  ALG_SID_RC5 = 13;

  // Fortezza sub-ids
  ALG_SID_SKIPJACK = 10;
  ALG_SID_TEK = 11;

  // KP_MODE
  CRYPT_MODE_CBCI = 6; {ANSI CBC Interleaved}
  CRYPT_MODE_CFBP = 7; {ANSI CFB Pipelined}
  CRYPT_MODE_OFBP = 8; {ANSI OFB Pipelined}
  CRYPT_MODE_CBCOFM = 9; {ANSI CBC + OF Masking}
  CRYPT_MODE_CBCOFMI = 10; {ANSI CBC + OFM Interleaved}

  // RC2 sub-ids
  ALG_SID_RC2 = 2;

  // Stream cipher sub-ids
  ALG_SID_RC4 = 1;
  ALG_SID_SEAL = 2;

  // Diffie-Hellman sub-ids
  ALG_SID_DH_SANDF = 1;
  ALG_SID_DH_EPHEM = 2;
  ALG_SID_AGREED_KEY_ANY = 3;
  ALG_SID_KEA = 4;

  // Hash sub ids
  ALG_SID_MD2 = 1;
  ALG_SID_MD4 = 2;
  ALG_SID_MD5 = 3;
  ALG_SID_SHA = 4;
  ALG_SID_SHA1 = 4;
  ALG_SID_MAC = 5;
  ALG_SID_RIPEMD = 6;
  ALG_SID_RIPEMD160 = 7;
  ALG_SID_SSL3SHAMD5 = 8;
  ALG_SID_HMAC = 9;

  // secure channel sub ids
  ALG_SID_SSL3_MASTER = 1;
  ALG_SID_SCHANNEL_MASTER_HASH = 2;
  ALG_SID_SCHANNEL_MAC_KEY = 3;
  ALG_SID_PCT1_MASTER = 4;
  ALG_SID_SSL2_MASTER = 5;
  ALG_SID_TLS1_MASTER = 6;
  ALG_SID_SCHANNEL_ENC_KEY = 7;

  // Our silly example sub-id
  ALG_SID_EXAMPLE = 80;

{$IFNDEF ALGIDDEF}
{$DEFINE ALGIDDEF}
type ALG_ID = ULONG;
{$ENDIF}

// algorithm identifier definitions
const
  CALG_MD2 = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD2);
  CALG_MD4 = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD4);
  CALG_MD5 = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MD5);
  CALG_SHA = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA);
  CALG_SHA1 = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SHA1);
  CALG_MAC = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_MAC);
  CALG_RSA_SIGN = (ALG_CLASS_SIGNATURE or ALG_TYPE_RSA or ALG_SID_RSA_ANY);
  CALG_DSS_SIGN = (ALG_CLASS_SIGNATURE or ALG_TYPE_DSS or ALG_SID_DSS_ANY);
  CALG_RSA_KEYX = (ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_RSA or ALG_SID_RSA_ANY);
  CALG_DES = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_DES);
  CALG_3DES_112 = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_3DES_112);
  CALG_3DES = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_3DES);
  CALG_RC2 = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_RC2);
  CALG_RC4 = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_STREAM or ALG_SID_RC4);
  CALG_SEAL = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_STREAM or ALG_SID_SEAL);
  CALG_DH_SF = (ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_DH_SANDF);
  CALG_DH_EPHEM = (ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_DH_EPHEM);
  CALG_AGREEDKEY_ANY = (ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_AGREED_KEY_ANY);
  CALG_KEA_KEYX = (ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_DH or ALG_SID_KEA);
  CALG_HUGHES_MD5 = (ALG_CLASS_KEY_EXCHANGE or ALG_TYPE_ANY or ALG_SID_MD5);
  CALG_SKIPJACK = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_SKIPJACK);
  CALG_TEK = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_TEK);
  CALG_CYLINK_MEK = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_CYLINK_MEK);
  CALG_SSL3_SHAMD5 = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_SSL3SHAMD5);
  CALG_SSL3_MASTER = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SSL3_MASTER);
  CALG_SCHANNEL_MASTER_HASH = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SCHANNEL_MASTER_HASH);
  CALG_SCHANNEL_MAC_KEY = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SCHANNEL_MAC_KEY);
  CALG_SCHANNEL_ENC_KEY = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SCHANNEL_ENC_KEY);
  CALG_PCT1_MASTER = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_PCT1_MASTER);
  CALG_SSL2_MASTER = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_SSL2_MASTER);
  CALG_TLS1_MASTER = (ALG_CLASS_MSG_ENCRYPT or ALG_TYPE_SECURECHANNEL or ALG_SID_TLS1_MASTER);
  CALG_RC5 = (ALG_CLASS_DATA_ENCRYPT or ALG_TYPE_BLOCK or ALG_SID_RC5);
  CALG_HMAC = (ALG_CLASS_HASH or ALG_TYPE_ANY or ALG_SID_HMAC);

type
  PVTableProvStruc = ^VTableProvStruc;
  VTableProvStruc = record
    Version: DWORD;
    FuncVerifyImage: TFarProc;
    FuncReturnhWnd: TFarProc;
    dwProvType: DWORD;
    pbContextInfo: PBYTE;
    cbContextInfo: DWORD;
  end;

//type HCRYPTPROV = ULONG;
//type HCRYPTKEY  = ULONG;
//type HCRYPTHASH = ULONG;


const
  // dwFlags definitions for CryptAcquireContext
  CRYPT_VERIFYCONTEXT = $F0000000;
  CRYPT_NEWKEYSET = $00000008;
  CRYPT_DELETEKEYSET = $00000010;
  CRYPT_MACHINE_KEYSET = $00000020;

  // dwFlag definitions for CryptGenKey
  CRYPT_EXPORTABLE = $00000001;
  CRYPT_USER_PROTECTED = $00000002;
  CRYPT_CREATE_SALT = $00000004;
  CRYPT_UPDATE_KEY = $00000008;
  CRYPT_NO_SALT = $00000010;
  CRYPT_PREGEN = $00000040;
  CRYPT_RECIPIENT = $00000010;
  CRYPT_INITIATOR = $00000040;
  CRYPT_ONLINE = $00000080;
  CRYPT_SF = $00000100;
  CRYPT_CREATE_IV = $00000200;
  CRYPT_KEK = $00000400;
  CRYPT_DATA_KEY = $00000800;

  // dwFlags definitions for CryptDeriveKey
  CRYPT_SERVER = $00000400;

  KEY_LENGTH_MASK = $FFFF0000;

  // dwFlag definitions for CryptExportKey
  CRYPT_Y_ONLY = $00000001;
  CRYPT_SSL2_SLUMMING = $00000002;

  // dwFlags definitions for CryptHashSessionKey
  CRYPT_LITTLE_ENDIAN = $00000001;

  // dwFlag definitions for CryptSetProviderEx and CryptGetDefaultProvider
  CRYPT_MACHINE_DEFAULT = $00000001;
  CRYPT_USER_DEFAULT = $00000002;
  CRYPT_DELETE_DEFAULT = $00000004;

  // exported key blob definitions
  SIMPLEBLOB = $1;
  PUBLICKEYBLOB = $6;
  PRIVATEKEYBLOB = $7;
  PLAINTEXTKEYBLOB = $8;
  AT_KEYEXCHANGE = 1;
  AT_SIGNATURE = 2;
  CRYPT_USERDATA = 1;

  // dwParam
  KP_IV = 1; // Initialization vector
  KP_SALT = 2; // Salt value
  KP_PADDING = 3; // Padding values
  KP_MODE = 4; // Mode of the cipher
  KP_MODE_BITS = 5; // Number of bits to feedback
  KP_PERMISSIONS = 6; // Key permissions DWORD
  KP_ALGID = 7; // Key algorithm
  KP_BLOCKLEN = 8; // Block size of the cipher
  KP_KEYLEN = 9; // Length of key in bits
  KP_SALT_EX = 10; // Length of salt in bytes
  KP_P = 11; // DSS/Diffie-Hellman P value
  KP_G = 12; // DSS/Diffie-Hellman G value
  KP_Q = 13; // DSS Q value
  KP_X = 14; // Diffie-Hellman X value
  KP_Y = 15; // Y value
  KP_RA = 16; // Fortezza RA value
  KP_RB = 17; // Fortezza RB value
  KP_INFO = 18; // for putting information into an RSA envelope
  KP_EFFECTIVE_KEYLEN = 19; // setting and getting RC2 effective key length
  KP_SCHANNEL_ALG = 20; // for setting the Secure Channel algorithms
  KP_CLIENT_RANDOM = 21; // for setting the Secure Channel client random data
  KP_SERVER_RANDOM = 22; // for setting the Secure Channel server random data
  KP_RP = 23;
  KP_PRECOMP_MD5 = 24;
  KP_PRECOMP_SHA = 25;
  KP_CERTIFICATE = 26; // for setting Secure Channel certificate data (PCT1)
  KP_CLEAR_KEY = 27; // for setting Secure Channel clear key data (PCT1)
  KP_PUB_EX_LEN = 28;
  KP_PUB_EX_VAL = 29;

  // KP_PADDING
  PKCS5_PADDING = 1; {PKCS 5 (sec 6.2) padding method}
  RANDOM_PADDING = 2;
  ZERO_PADDING = 3;

  // KP_MODE
  CRYPT_MODE_CBC = 1; // Cipher block chaining
  CRYPT_MODE_ECB = 2; // Electronic code book
  CRYPT_MODE_OFB = 3; // Output feedback mode
  CRYPT_MODE_CFB = 4; // Cipher feedback mode
  CRYPT_MODE_CTS = 5; // Ciphertext stealing mode

  // KP_PERMISSIONS
  CRYPT_ENCRYPT = $0001; // Allow encryption
  CRYPT_DECRYPT = $0002; // Allow decryption
  CRYPT_EXPORT = $0004; // Allow key to be exported
  CRYPT_READ = $0008; // Allow parameters to be read
  CRYPT_WRITE = $0010; // Allow parameters to be set
  CRYPT_MAC = $0020; // Allow MACs to be used with key
  CRYPT_EXPORT_KEY = $0040; // Allow key to be used for exporting keys
  CRYPT_IMPORT_KEY = $0080; // Allow key to be used for importing keys

  HP_ALGID = $0001; // Hash algorithm
  HP_HASHVAL = $0002; // Hash value
  HP_HASHSIZE = $0004; // Hash value size

  HP_HMAC_INFO = $0005; // information for creating an HMAC

  CRYPT_FAILED = FALSE;
  CRYPT_SUCCEED = TRUE;

function RCRYPT_SUCCEEDED(rt: BOOL): BOOL;
function RCRYPT_FAILED(rt: BOOL): BOOL;

const
  // CryptGetProvParam
  PP_ENUMALGS = 1;
  PP_ENUMCONTAINERS = 2;
  PP_IMPTYPE = 3;
  PP_NAME = 4;
  PP_VERSION = 5;
  PP_CONTAINER = 6;
  PP_CHANGE_PASSWORD = 7;
  PP_KEYSET_SEC_DESCR = 8; // get/set security descriptor of keyset
  PP_CERTCHAIN = 9; // for retrieving certificates from tokens
  PP_KEY_TYPE_SUBTYPE = 10;
  PP_PROVTYPE = 16;
  PP_KEYSTORAGE = 17;
  PP_APPLI_CERT = 18;
  PP_SYM_KEYSIZE = 19;
  PP_SESSION_KEYSIZE = 20;
  PP_UI_PROMPT = 21;
  PP_ENUMALGS_EX = 22;
  CRYPT_FIRST = 1;
  CRYPT_NEXT = 2;
  CRYPT_IMPL_HARDWARE = 1;
  CRYPT_IMPL_SOFTWARE = 2;
  CRYPT_IMPL_MIXED = 3;
  CRYPT_IMPL_UNKNOWN = 4;

  // key storage flags
  CRYPT_SEC_DESCR = $00000001;
  CRYPT_PSTORE = $00000002;
  CRYPT_UI_PROMPT = $00000004;

  // protocol flags
  CRYPT_FLAG_PCT1 = $0001;
  CRYPT_FLAG_SSL2 = $0002;
  CRYPT_FLAG_SSL3 = $0004;
  CRYPT_FLAG_TLS1 = $0008;

  // CryptSetProvParam
  PP_CLIENT_HWND = 1;
  PP_CONTEXT_INFO = 11;
  PP_KEYEXCHANGE_KEYSIZE = 12;
  PP_SIGNATURE_KEYSIZE = 13;
  PP_KEYEXCHANGE_ALG = 14;
  PP_SIGNATURE_ALG = 15;
  PP_DELETEKEY = 24;

  PROV_RSA_FULL = 1;
  PROV_RSA_SIG = 2;
  PROV_DSS = 3;
  PROV_FORTEZZA = 4;
  PROV_MS_EXCHANGE = 5;
  PROV_SSL = 6;

  PROV_RSA_SCHANNEL = 12;
  PROV_DSS_DH = 13;
  PROV_EC_ECDSA_SIG = 14;
  PROV_EC_ECNRA_SIG = 15;
  PROV_EC_ECDSA_FULL = 16;
  PROV_EC_ECNRA_FULL = 17;
  PROV_SPYRUS_LYNKS = 20;


  // STT defined Providers
  PROV_STT_MER = 7;
  PROV_STT_ACQ = 8;
  PROV_STT_BRND = 9;
  PROV_STT_ROOT = 10;
  PROV_STT_ISS = 11;

  // Provider friendly names
  MS_DEF_PROV_A = 'Microsoft Base Cryptographic Provider v1.0';
{$IFNDEF VER90}
  MS_DEF_PROV_W = WideString('Microsoft Base Cryptographic Provider v1.0');
{$ELSE}
  MS_DEF_PROV_W = ('Microsoft Base Cryptographic Provider v1.0');
{$ENDIF}

{$IFDEF UNICODE}
  MS_DEF_PROV = MS_DEF_PROV_W;
{$ELSE}
  MS_DEF_PROV = MS_DEF_PROV_A;
{$ENDIF}

  MS_ENHANCED_PROV_A = 'Microsoft Enhanced Cryptographic Provider v1.0';
{$IFNDEF VER90}
  MS_ENHANCED_PROV_W = WideString('Microsoft Enhanced Cryptographic Provider v1.0');
{$ELSE}
  MS_ENHANCED_PROV_W = ('Microsoft Enhanced Cryptographic Provider v1.0');
{$ENDIF}

{$IFDEF UNICODE}
  MS_ENHANCED_PROV = MS_ENHANCED_PROV_W;
{$ELSE}
  MS_ENHANCED_PROV = MS_ENHANCED_PROV_A;
{$ENDIF}

  MS_DEF_RSA_SIG_PROV_A = 'Microsoft RSA Signature Cryptographic Provider';
{$IFNDEF VER90}
  MS_DEF_RSA_SIG_PROV_W = WideString('Microsoft RSA Signature Cryptographic Provider');
{$ELSE}
  MS_DEF_RSA_SIG_PROV_W = ('Microsoft RSA Signature Cryptographic Provider');
{$ENDIF}

{$IFDEF UNICODE}
  MS_DEF_RSA_SIG_PROV = MS_DEF_RSA_SIG_PROV_W;
{$ELSE}
  MS_DEF_RSA_SIG_PROV = MS_DEF_RSA_SIG_PROV_A;
{$ENDIF}

  MS_DEF_RSA_SCHANNEL_PROV_A = 'Microsoft Base RSA SChannel Cryptographic Provider';
{$IFNDEF VER90}
  MS_DEF_RSA_SCHANNEL_PROV_W = WideString('Microsoft Base RSA SChannel Cryptographic Provider');
{$ELSE}
  MS_DEF_RSA_SCHANNEL_PROV_W = ('Microsoft Base RSA SChannel Cryptographic Provider');
{$ENDIF}


{$IFDEF UNICODE}
  MS_DEF_RSA_SCHANNEL_PROV = MS_DEF_RSA_SCHANNEL_PROV_W;
{$ELSE}
  MS_DEF_RSA_SCHANNEL_PROV = MS_DEF_RSA_SCHANNEL_PROV_A;
{$ENDIF}

  MS_ENHANCED_RSA_SCHANNEL_PROV_A = 'Microsoft Enhanced RSA SChannel Cryptographic Provider';
{$IFNDEF VER90}
  MS_ENHANCED_RSA_SCHANNEL_PROV_W = WideString('Microsoft Enhanced RSA SChannel Cryptographic Provider');
{$ELSE}
  MS_ENHANCED_RSA_SCHANNEL_PROV_W = ('Microsoft Enhanced RSA SChannel Cryptographic Provider');
{$ENDIF}

{$IFDEF UNICODE}
  MS_ENHANCED_RSA_SCHANNEL_PROV = MS_ENHANCED_RSA_SCHANNEL_PROV_W;
{$ELSE}
  MS_ENHANCED_RSA_SCHANNEL_PROV = MS_ENHANCED_RSA_SCHANNEL_PROV_A;
{$ENDIF}

  MS_DEF_DSS_PROV_A = 'Microsoft Base DSS Cryptographic Provider';
{$IFNDEF VER90}
  MS_DEF_DSS_PROV_W = WideString('Microsoft Base DSS Cryptographic Provider');
{$ELSE}
  MS_DEF_DSS_PROV_W = ('Microsoft Base DSS Cryptographic Provider');
{$ENDIF}

{$IFDEF UNICODE}
  MS_DEF_DSS_PROV = MS_DEF_DSS_PROV_W;
{$ELSE}
  MS_DEF_DSS_PROV = MS_DEF_DSS_PROV_A;
{$ENDIF}

  MS_DEF_DSS_DH_PROV_A = 'Microsoft Base DSS and Diffie-Hellman Cryptographic Provider';
{$IFNDEF VER90}
  MS_DEF_DSS_DH_PROV_W = WideString('Microsoft Base DSS and Diffie-Hellman Cryptographic Provider');
{$ELSE}
  MS_DEF_DSS_DH_PROV_W = ('Microsoft Base DSS and Diffie-Hellman Cryptographic Provider');
{$ENDIF}

{$IFDEF UNICODE}
  MS_DEF_DSS_DH_PROV = MS_DEF_DSS_DH_PROV_W;
{$ELSE}
  MS_DEF_DSS_DH_PROV = MS_DEF_DSS_DH_PROV_A;
{$ENDIF}

  MAXUIDLEN = 64;
  CUR_BLOB_VERSION = 2;

{structure for use with CryptSetHashParam with CALG_HMAC}
type
  PHMAC_INFO = ^HMAC_INFO;
  HMAC_INFO = record
    HashAlgid: ALG_ID;
    pbInnerString: PBYTE;
    cbInnerString: DWORD;
    pbOuterString: PBYTE;
    cbOuterString: DWORD;
  end;

// structure for use with CryptSetHashParam with CALG_HMAC
type
  PSCHANNEL_ALG = ^SCHANNEL_ALG;
  SCHANNEL_ALG = record
    dwUse: DWORD;
    Algid: ALG_ID;
    cBits: DWORD;
  end;

// uses of algortihms for SCHANNEL_ALG structure
const
  SCHANNEL_MAC_KEY = $00000000;
  SCHANNEL_ENC_KEY = $00000001;

type
  PPROV_ENUMALGS = ^PROV_ENUMALGS;
  PROV_ENUMALGS = record
    aiAlgid: ALG_ID;
    dwBitLen: DWORD;
    dwNameLen: DWORD;
    szName: array[0..20 - 1] of Char;
  end;

type
  PPROV_ENUMALGS_EX = ^PROV_ENUMALGS_EX;
  PROV_ENUMALGS_EX = record
    aiAlgid: ALG_ID;
    dwDefaultLen: DWORD;
    dwMinLen: DWORD;
    dwMaxLen: DWORD;
    dwProtocols: DWORD;
    dwNameLen: DWORD;
    szName: array[0..20 - 1] of Char;
    dwLongNameLen: DWORD;
    szLongName: array[0..40 - 1] of Char;
  end;

type
  PPUBLICKEYSTRUC = ^PUBLICKEYSTRUC;
  PUBLICKEYSTRUC = record
    bType: BYTE;
    bVersion: BYTE;
    reserved: Word;
    aiKeyAlg: ALG_ID;
  end;

type
  BLOBHEADER = PUBLICKEYSTRUC;
  PBLOBHEADER = ^BLOBHEADER;

type
  PRSAPUBKEY = ^RSAPUBKEY;
  RSAPUBKEY = record
    magic: DWORD; // Has to be RSA1
    bitlen: DWORD; // # of bits in modulus
    pubexp: DWORD; // public exponent
                    // Modulus data follows
  end;

type
  PPUBKEY = ^PUBKEY;
  PUBKEY = record
    magic: DWORD;
    bitlen: DWORD; // # of bits in modulus
  end;

type
  DHPUBKEY = PUBKEY;
  DSSPUBKEY = PUBKEY;
  KEAPUBKEY = PUBKEY;
  TEKPUBKEY = PUBKEY;


type
  PDSSSEED = ^DSSSEED;
  DSSSEED = record
    counter: DWORD;
    seed: array[0..20 - 1] of BYTE;
  end;

type
  PKEY_TYPE_SUBTYPE = ^KEY_TYPE_SUBTYPE;
  KEY_TYPE_SUBTYPE = record
    dwKeySpec: DWORD;
    Type_: TGUID; {conflict with base Delphi type: original name 'Type'}
    Subtype: TGUID;
  end;

type
  HCRYPTPROV = ULONG;
  PHCRYPTPROV = ^HCRYPTPROV;
  HCRYPTKEY = ULONG;
  PHCRYPTKEY = ^HCRYPTKEY;
  HCRYPTHASH = ULONG;
  PHCRYPTHASH = ^HCRYPTHASH;

function CryptAcquireContextA(phProv: PHCRYPTPROV;
  pszContainer: PAnsiChar;
  pszProvider: PAnsiChar;
  dwProvType: DWORD;
  dwFlags: DWORD): BOOL; stdcall;

function CryptAcquireContext(phProv: PHCRYPTPROV;
  pszContainer: LPAWSTR;
  pszProvider: LPAWSTR;
  dwProvType: DWORD;
  dwFlags: DWORD): BOOL; stdcall;

function CryptAcquireContextW(phProv: PHCRYPTPROV;
  pszContainer: PWideChar;
  pszProvider: PWideChar;
  dwProvType: DWORD;
  dwFlags: DWORD): BOOL; stdcall;


function CryptReleaseContext(hProv: HCRYPTPROV;
  dwFlags: DWORD): BOOL; stdcall;



function CryptGenKey(hProv: HCRYPTPROV;
  Algid: ALG_ID;
  dwFlags: DWORD;
  phKey: PHCRYPTKEY): BOOL; stdcall;


function CryptDeriveKey(hProv: HCRYPTPROV;
  Algid: ALG_ID;
  hBaseData: HCRYPTHASH;
  dwFlags: DWORD;
  phKey: PHCRYPTKEY): BOOL; stdcall;



function CryptDestroyKey(hKey: HCRYPTKEY): BOOL; stdcall;


function CryptSetKeyParam(hKey: HCRYPTKEY;
  dwParam: DWORD;
  pbData: PBYTE;
  dwFlags: DWORD): BOOL; stdcall;


function CryptGetKeyParam(hKey: HCRYPTKEY;
  dwParam: DWORD;
  pbData: PBYTE;
  pdwDataLen: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;


function CryptSetHashParam(hHash: HCRYPTHASH;
  dwParam: DWORD;
  pbData: PBYTE;
  dwFlags: DWORD): BOOL; stdcall;


function CryptGetHashParam(hHash: HCRYPTHASH;
  dwParam: DWORD;
  pbData: PBYTE;
  pdwDataLen: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;


function CryptSetProvParam(hProv: HCRYPTPROV;
  dwParam: DWORD;
  pbData: PBYTE;
  dwFlags: DWORD): BOOL; stdcall;


function CryptGetProvParam(hProv: HCRYPTPROV;
  dwParam: DWORD;
  pbData: PBYTE;
  pdwDataLen: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;


function CryptGenRandom(hProv: HCRYPTPROV;
  dwLen: DWORD;
  pbBuffer: PBYTE): BOOL; stdcall;


function CryptGetUserKey(hProv: HCRYPTPROV;
  dwKeySpec: DWORD;
  phUserKey: PHCRYPTKEY): BOOL; stdcall;


function CryptExportKey(hKey: HCRYPTKEY;
  hExpKey: HCRYPTKEY;
  dwBlobType: DWORD;
  dwFlags: DWORD;
  pbData: PBYTE;
  pdwDataLen: PDWORD): BOOL; stdcall;


function CryptImportKey(hProv: HCRYPTPROV;
  pbData: PBYTE;
  dwDataLen: DWORD;
  hPubKey: HCRYPTKEY;
  dwFlags: DWORD;
  phKey: PHCRYPTKEY): BOOL; stdcall;


function CryptEncrypt(hKey: HCRYPTKEY;
  hHash: HCRYPTHASH;
  Final: BOOL;
  dwFlags: DWORD;
  pbData: PBYTE;
  pdwDataLen: PDWORD;
  dwBufLen: DWORD): BOOL; stdcall;


function CryptDecrypt(hKey: HCRYPTKEY;
  hHash: HCRYPTHASH;
  Final: BOOL;
  dwFlags: DWORD;
  pbData: PBYTE;
  pdwDataLen: PDWORD): BOOL; stdcall;


function CryptCreateHash(hProv: HCRYPTPROV;
  Algid: ALG_ID;
  hKey: HCRYPTKEY;
  dwFlags: DWORD;
  phHash: PHCRYPTHASH): BOOL; stdcall;


function CryptHashData(hHash: HCRYPTHASH;
  const pbData: PBYTE;
  dwDataLen: DWORD;
  dwFlags: DWORD): BOOL; stdcall;


function CryptHashSessionKey(hHash: HCRYPTHASH;
  hKey: HCRYPTKEY;
  dwFlags: DWORD): BOOL; stdcall;


function CryptDestroyHash(hHash: HCRYPTHASH): BOOL; stdcall;


function CryptSignHashA(hHash: HCRYPTHASH;
  dwKeySpec: DWORD;
  sDescription: PAnsiChar;
  dwFlags: DWORD;
  pbSignature: PBYTE;
  pdwSigLen: PDWORD): BOOL; stdcall;


function CryptSignHash(hHash: HCRYPTHASH;
  dwKeySpec: DWORD;
  sDescription: LPAWSTR;
  dwFlags: DWORD;
  pbSignature: PBYTE;
  pdwSigLen: PDWORD): BOOL; stdcall;

function CryptSignHashW(hHash: HCRYPTHASH;
  dwKeySpec: DWORD;
  sDescription: PWideChar;
  dwFlags: DWORD;
  pbSignature: PBYTE;
  pdwSigLen: PDWORD): BOOL; stdcall;

function CryptSignHashU(hHash: HCRYPTHASH;
  dwKeySpec: DWORD;
  sDescription: PWideChar;
  dwFlags: DWORD;
  pbSignature: PBYTE;
  pdwSigLen: PDWORD): BOOL; stdcall;

function CryptVerifySignatureA(hHash: HCRYPTHASH;
  const pbSignature: PBYTE;
  dwSigLen: DWORD;
  hPubKey: HCRYPTKEY;
  sDescription: PAnsiChar;
  dwFlags: DWORD): BOOL; stdcall;

function CryptVerifySignature(hHash: HCRYPTHASH;
  const pbSignature: PBYTE;
  dwSigLen: DWORD;
  hPubKey: HCRYPTKEY;
  sDescription: LPAWSTR;
  dwFlags: DWORD): BOOL; stdcall;


function CryptVerifySignatureW(hHash: HCRYPTHASH;
  const pbSignature: PBYTE;
  dwSigLen: DWORD;
  hPubKey: HCRYPTKEY;
  sDescription: PWideChar;
  dwFlags: DWORD): BOOL; stdcall;


function CryptSetProviderA(pszProvName: PAnsiChar;
  dwProvType: DWORD): BOOL; stdcall;

function CryptSetProvider(pszProvName: LPAWSTR;
  dwProvType: DWORD): BOOL; stdcall;

function CryptSetProviderW(pszProvName: PWideChar;
  dwProvType: DWORD): BOOL; stdcall;

function CryptSetProviderU(pszProvName: PWideChar;
  dwProvType: DWORD): BOOL; stdcall;

{$IFDEF NT5}

function CryptSetProviderExA(pszProvName: LPCSTR;
  dwProvType: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;

function CryptSetProviderExW(pszProvName: LPCWSTR;
  dwProvType: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;

function CryptSetProviderEx(pszProvName: LPAWSTR;
  dwProvType: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;


function CryptGetDefaultProviderA(dwProvType: DWORD;
  pdwReserved: DWORD;
  dwFlags: DWORD;
  pszProvName: LPSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

function CryptGetDefaultProviderW(dwProvType: DWORD;
  pdwReserved: DWORD;
  dwFlags: DWORD;
  pszProvName: LPWSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

function CryptGetDefaultProvider(dwProvType: DWORD;
  pdwReserved: DWORD;
  dwFlags: DWORD;
  pszProvName: LPAWSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

function CryptEnumProviderTypesA(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszTypeName: LPSTR;
  pcbTypeName: PDWORD): BOOL; stdcall;

function CryptEnumProviderTypesW(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszTypeName: LPWSTR;
  pcbTypeName: PDWORD): BOOL; stdcall;

function CryptEnumProviderTypes(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszTypeName: LPAWSTR;
  pcbTypeName: PDWORD): BOOL; stdcall;

function CryptEnumProvidersA(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszProvName: LPSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

function CryptEnumProvidersW(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszProvName: LPWSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

function CryptEnumProviders(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszProvName: LPAWSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

function CryptContextAddRef(hProv: HCRYPTPROV;
  pdwReserved: PDWORD;
  dwFlags: DWORD): BOOL; stdcall;

function CryptDuplicateKey(hKey: HCRYPTKEY;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  phKey: PHCRYPTKEY): BOOL; stdcall;

function CryptDuplicateHash(hHash: HCRYPTHASH;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  phHash: PHCRYPTHASH): BOOL; stdcall;

{$ENDIF NT5}

function CryptEnumProvidersU(dwIndex: DWORD;
  pdwReserved: PDWORD;
  dwFlags: DWORD;
  pdwProvType: PDWORD;
  pszProvName: LPWSTR;
  pcbProvName: PDWORD): BOOL; stdcall;

type
  PCRYPTOAPI_BLOB = ^CRYPTOAPI_BLOB;
  CRYPTOAPI_BLOB = record
    cbData: DWORD;
    pbData: PBYTE;
  end;

type
  CRYPT_INTEGER_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_INTEGER_BLOB = ^CRYPT_INTEGER_BLOB;
  CRYPT_UINT_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_UINT_BLOB = ^CRYPT_UINT_BLOB;
  CRYPT_OBJID_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_OBJID_BLOB = ^CRYPT_OBJID_BLOB;
  CERT_NAME_BLOB = CRYPTOAPI_BLOB;
  PCERT_NAME_BLOB = ^CERT_NAME_BLOB;
  CERT_RDN_VALUE_BLOB = CRYPTOAPI_BLOB;
  PCERT_RDN_VALUE_BLOB = ^CERT_RDN_VALUE_BLOB;
  CERT_BLOB = CRYPTOAPI_BLOB;
  PCERT_BLOB = ^CERT_BLOB;
  CRL_BLOB = CRYPTOAPI_BLOB;
  PCRL_BLOB = ^CRL_BLOB;
  DATA_BLOB = CRYPTOAPI_BLOB;
  PDATA_BLOB = ^DATA_BLOB; // JEFFJEFF temporary (too generic)
  CRYPT_DATA_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_DATA_BLOB = ^CRYPT_DATA_BLOB;
  CRYPT_HASH_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_HASH_BLOB = ^CRYPT_HASH_BLOB;
  CRYPT_DIGEST_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_DIGEST_BLOB = ^CRYPT_DIGEST_BLOB;
  CRYPT_DER_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_DER_BLOB = ^CRYPT_DER_BLOB;
  CRYPT_ATTR_BLOB = CRYPTOAPI_BLOB;
  PCRYPT_ATTR_BLOB = ^CRYPT_ATTR_BLOB;


type
  PCRYPT_BIT_BLOB = ^CRYPT_BIT_BLOB;
  CRYPT_BIT_BLOB = record
    cbData: DWORD;
    pbData: PBYTE;
    cUnusedBits: DWORD;
  end;


type
  PCRYPT_ALGORITHM_IDENTIFIER = ^CRYPT_ALGORITHM_IDENTIFIER;
  CRYPT_ALGORITHM_IDENTIFIER = record
    pszObjId: LPSTR;
    Parameters: CRYPT_OBJID_BLOB;
  end;

// Following are the definitions of various algorithm object identifiers
// RSA
const
  szOID_RSA = '1.2.840.113549';
  szOID_PKCS = '1.2.840.113549.1';
  szOID_RSA_HASH = '1.2.840.113549.2';
  szOID_RSA_ENCRYPT = '1.2.840.113549.3';

  szOID_PKCS_1 = '1.2.840.113549.1.1';
  szOID_PKCS_2 = '1.2.840.113549.1.2';
  szOID_PKCS_3 = '1.2.840.113549.1.3';
  szOID_PKCS_4 = '1.2.840.113549.1.4';
  szOID_PKCS_5 = '1.2.840.113549.1.5';
  szOID_PKCS_6 = '1.2.840.113549.1.6';
  szOID_PKCS_7 = '1.2.840.113549.1.7';
  szOID_PKCS_8 = '1.2.840.113549.1.8';
  szOID_PKCS_9 = '1.2.840.113549.1.9';
  szOID_PKCS_10 = '1.2.840.113549.1.10';

  szOID_RSA_RSA = '1.2.840.113549.1.1.1';
  szOID_RSA_MD2RSA = '1.2.840.113549.1.1.2';
  szOID_RSA_MD4RSA = '1.2.840.113549.1.1.3';
  szOID_RSA_MD5RSA = '1.2.840.113549.1.1.4';
  szOID_RSA_SHA1RSA = '1.2.840.113549.1.1.5';
  szOID_RSA_SETOAEP_RSA = '1.2.840.113549.1.1.6';

  szOID_RSA_data = '1.2.840.113549.1.7.1';
  szOID_RSA_signedData = '1.2.840.113549.1.7.2';
  szOID_RSA_envelopedData = '1.2.840.113549.1.7.3';
  szOID_RSA_signEnvData = '1.2.840.113549.1.7.4';
  szOID_RSA_digestedData = '1.2.840.113549.1.7.5';
  szOID_RSA_hashedData = '1.2.840.113549.1.7.5';
  szOID_RSA_encryptedData = '1.2.840.113549.1.7.6';

  szOID_RSA_emailAddr = '1.2.840.113549.1.9.1';
  szOID_RSA_unstructName = '1.2.840.113549.1.9.2';
  szOID_RSA_contentType = '1.2.840.113549.1.9.3';
  szOID_RSA_messageDigest = '1.2.840.113549.1.9.4';
  szOID_RSA_signingTime = '1.2.840.113549.1.9.5';
  szOID_RSA_counterSign = '1.2.840.113549.1.9.6';
  szOID_RSA_challengePwd = '1.2.840.113549.1.9.7';
  szOID_RSA_unstructAddr = '1.2.840.113549.1.9.8';
  szOID_RSA_extCertAttrs = '1.2.840.113549.1.9.9';
  szOID_RSA_SMIMECapabilities = '1.2.840.113549.1.9.15';
  szOID_RSA_preferSignedData = '1.2.840.113549.1.9.15.1';

  szOID_RSA_MD2 = '1.2.840.113549.2.2';
  szOID_RSA_MD4 = '1.2.840.113549.2.4';
  szOID_RSA_MD5 = '1.2.840.113549.2.5';

  szOID_RSA_RC2CBC = '1.2.840.113549.3.2';
  szOID_RSA_RC4 = '1.2.840.113549.3.4';
  szOID_RSA_DES_EDE3_CBC = '1.2.840.113549.3.7';
  szOID_RSA_RC5_CBCPad = '1.2.840.113549.3.9';

// ITU-T UsefulDefinitions
  szOID_DS = '2.5';
  szOID_DSALG = '2.5.8';
  szOID_DSALG_CRPT = '2.5.8.1';
  szOID_DSALG_HASH = '2.5.8.2';
  szOID_DSALG_SIGN = '2.5.8.3';
  szOID_DSALG_RSA = '2.5.8.1.1';

// NIST OSE Implementors' Workshop (OIW)
// http://nemo.ncsl.nist.gov/oiw/agreements/stable/OSI/12s_9506.w51
// http://nemo.ncsl.nist.gov/oiw/agreements/working/OSI/12w_9503.w51
  szOID_OIW = '1.3.14';
// NIST OSE Implementors' Workshop (OIW) Security SIG algorithm identifiers
  szOID_OIWSEC = '1.3.14.3.2';
  szOID_OIWSEC_md4RSA = '1.3.14.3.2.2';
  szOID_OIWSEC_md5RSA = '1.3.14.3.2.3';
  szOID_OIWSEC_md4RSA2 = '1.3.14.3.2.4';
  szOID_OIWSEC_desECB = '1.3.14.3.2.6';
  szOID_OIWSEC_desCBC = '1.3.14.3.2.7';
  szOID_OIWSEC_desOFB = '1.3.14.3.2.8';
  szOID_OIWSEC_desCFB = '1.3.14.3.2.9';
  szOID_OIWSEC_desMAC = '1.3.14.3.2.10';
  szOID_OIWSEC_rsaSign = '1.3.14.3.2.11';
  szOID_OIWSEC_dsa = '1.3.14.3.2.12';
  szOID_OIWSEC_shaDSA = '1.3.14.3.2.13';
  szOID_OIWSEC_mdc2RSA = '1.3.14.3.2.14';
  szOID_OIWSEC_shaRSA = '1.3.14.3.2.15';
  szOID_OIWSEC_dhCommMod = '1.3.14.3.2.16';
  szOID_OIWSEC_desEDE = '1.3.14.3.2.17';
  szOID_OIWSEC_sha = '1.3.14.3.2.18';
  szOID_OIWSEC_mdc2 = '1.3.14.3.2.19';
  szOID_OIWSEC_dsaComm = '1.3.14.3.2.20';
  szOID_OIWSEC_dsaCommSHA = '1.3.14.3.2.21';
  szOID_OIWSEC_rsaXchg = '1.3.14.3.2.22';
  szOID_OIWSEC_keyHashSeal = '1.3.14.3.2.23';
  szOID_OIWSEC_md2RSASign = '1.3.14.3.2.24';
  szOID_OIWSEC_md5RSASign = '1.3.14.3.2.25';
  szOID_OIWSEC_sha1 = '1.3.14.3.2.26';
  szOID_OIWSEC_dsaSHA1 = '1.3.14.3.2.27';
  szOID_OIWSEC_dsaCommSHA1 = '1.3.14.3.2.28';
  szOID_OIWSEC_sha1RSASign = '1.3.14.3.2.29';
// NIST OSE Implementors' Workshop (OIW) Directory SIG algorithm identifiers
  szOID_OIWDIR = '1.3.14.7.2';
  szOID_OIWDIR_CRPT = '1.3.14.7.2.1';
  szOID_OIWDIR_HASH = '1.3.14.7.2.2';
  szOID_OIWDIR_SIGN = '1.3.14.7.2.3';
  szOID_OIWDIR_md2 = '1.3.14.7.2.2.1';
  szOID_OIWDIR_md2RSA = '1.3.14.7.2.3.1';


// INFOSEC Algorithms
// joint-iso-ccitt(2) country(16) us(840) organization(1) us-government(101) dod(2) id-infosec(1)
  szOID_INFOSEC = '2.16.840.1.101.2.1';
  szOID_INFOSEC_sdnsSignature = '2.16.840.1.101.2.1.1.1';
  szOID_INFOSEC_mosaicSignature = '2.16.840.1.101.2.1.1.2';
  szOID_INFOSEC_sdnsConfidentiality = '2.16.840.1.101.2.1.1.3';
  szOID_INFOSEC_mosaicConfidentiality = '2.16.840.1.101.2.1.1.4';
  szOID_INFOSEC_sdnsIntegrity = '2.16.840.1.101.2.1.1.5';
  szOID_INFOSEC_mosaicIntegrity = '2.16.840.1.101.2.1.1.6';
  szOID_INFOSEC_sdnsTokenProtection = '2.16.840.1.101.2.1.1.7';
  szOID_INFOSEC_mosaicTokenProtection = '2.16.840.1.101.2.1.1.8';
  szOID_INFOSEC_sdnsKeyManagement = '2.16.840.1.101.2.1.1.9';
  szOID_INFOSEC_mosaicKeyManagement = '2.16.840.1.101.2.1.1.10';
  szOID_INFOSEC_sdnsKMandSig = '2.16.840.1.101.2.1.1.11';
  szOID_INFOSEC_mosaicKMandSig = '2.16.840.1.101.2.1.1.12';
  szOID_INFOSEC_SuiteASignature = '2.16.840.1.101.2.1.1.13';
  szOID_INFOSEC_SuiteAConfidentiality = '2.16.840.1.101.2.1.1.14';
  szOID_INFOSEC_SuiteAIntegrity = '2.16.840.1.101.2.1.1.15';
  szOID_INFOSEC_SuiteATokenProtection = '2.16.840.1.101.2.1.1.16';
  szOID_INFOSEC_SuiteAKeyManagement = '2.16.840.1.101.2.1.1.17';
  szOID_INFOSEC_SuiteAKMandSig = '2.16.840.1.101.2.1.1.18';
  szOID_INFOSEC_mosaicUpdatedSig = '2.16.840.1.101.2.1.1.19';
  szOID_INFOSEC_mosaicKMandUpdSig = '2.16.840.1.101.2.1.1.20';
  szOID_INFOSEC_mosaicUpdatedInteg = '2.16.840.1.101.2.1.1.21';

type
  PCRYPT_OBJID_TABLE = ^CRYPT_OBJID_TABLE;
  CRYPT_OBJID_TABLE = record
    dwAlgId: DWORD;
    pszObjId: LPCSTR;
  end;


type
  PCRYPT_HASH_INFO = ^CRYPT_HASH_INFO;
  CRYPT_HASH_INFO = record
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    Hash: CRYPT_HASH_BLOB;
  end;


type
  PCERT_EXTENSION = ^CERT_EXTENSION;
  CERT_EXTENSION = record
    pszObjId: LPSTR;
    fCritical: BOOL;
    Value: CRYPT_OBJID_BLOB;
  end;


type
  PCRYPT_ATTRIBUTE_TYPE_VALUE = ^CRYPT_ATTRIBUTE_TYPE_VALUE;
  CRYPT_ATTRIBUTE_TYPE_VALUE = record
    pszObjId: LPSTR;
    Value: CRYPT_OBJID_BLOB;
  end;


type
  PCRYPT_ATTRIBUTE = ^CRYPT_ATTRIBUTE;
  CRYPT_ATTRIBUTE = record
    pszObjId: LPSTR;
    cValue: DWORD;
    rgValue: PCRYPT_ATTR_BLOB;
  end;

type
  PCRYPT_ATTRIBUTES = ^CRYPT_ATTRIBUTES;
  CRYPT_ATTRIBUTES = record
    cAttr: DWORD; {IN}
    rgAttr: PCRYPT_ATTRIBUTE; {IN}
  end;

type
  PCERT_RDN_ATTR = ^CERT_RDN_ATTR;
  CERT_RDN_ATTR = record
    pszObjId: LPSTR;
    dwValueType: DWORD;
    Value: CERT_RDN_VALUE_BLOB;
  end;

// Labeling attribute types:
const
  szOID_COMMON_NAME = '2.5.4.3'; // case-ignore string
  szOID_SUR_NAME = '2.5.4.4'; // case-ignore string
  szOID_DEVICE_SERIAL_NUMBER = '2.5.4.5'; // printable string

// Geographic attribute types:
  szOID_COUNTRY_NAME = '2.5.4.6'; // printable 2char string
  szOID_LOCALITY_NAME = '2.5.4.7'; // case-ignore string
  szOID_STATE_OR_PROVINCE_NAME = '2.5.4.8'; // case-ignore string
  szOID_STREET_ADDRESS = '2.5.4.9'; // case-ignore string

// Organizational attribute types:
  szOID_ORGANIZATION_NAME = '2.5.4.10'; // case-ignore string
  szOID_ORGANIZATIONAL_UNIT_NAME = '2.5.4.11'; // case-ignore string
  szOID_TITLE = '2.5.4.12'; // case-ignore string

// Explanatory attribute types:
  szOID_DESCRIPTION = '2.5.4.13'; // case-ignore string
  szOID_SEARCH_GUIDE = '2.5.4.14';
  szOID_BUSINESS_CATEGORY = '2.5.4.15'; // case-ignore string

// Postal addressing attribute types:
  szOID_POSTAL_ADDRESS = '2.5.4.16';
  szOID_POSTAL_CODE = '2.5.4.17'; // case-ignore string
  szOID_POST_OFFICE_BOX = '2.5.4.18'; // case-ignore string
  szOID_PHYSICAL_DELIVERY_OFFICE_NAME = '2.5.4.19'; // case-ignore string

// Telecommunications addressing attribute types:
  szOID_TELEPHONE_NUMBER = '2.5.4.20'; // telephone number
  szOID_TELEX_NUMBER = '2.5.4.21';
  szOID_TELETEXT_TERMINAL_IDENTIFIER = '2.5.4.22';
  szOID_FACSIMILE_TELEPHONE_NUMBER = '2.5.4.23';
  szOID_X21_ADDRESS = '2.5.4.24'; // numeric string
  szOID_INTERNATIONAL_ISDN_NUMBER = '2.5.4.25'; // numeric string
  szOID_REGISTERED_ADDRESS = '2.5.4.26';
  szOID_DESTINATION_INDICATOR = '2.5.4.27'; // printable string

// Preference attribute types:
  szOID_PREFERRED_DELIVERY_METHOD = '2.5.4.28';

// OSI application attribute types:
  szOID_PRESENTATION_ADDRESS = '2.5.4.29';
  szOID_SUPPORTED_APPLICATION_CONTEXT = '2.5.4.30';

// Relational application attribute types:
  szOID_MEMBER = '2.5.4.31';
  szOID_OWNER = '2.5.4.32';
  szOID_ROLE_OCCUPANT = '2.5.4.33';
  szOID_SEE_ALSO = '2.5.4.34';

// Security attribute types:
  szOID_USER_PASSWORD = '2.5.4.35';
  szOID_USER_CERTIFICATE = '2.5.4.36';
  szOID_CA_CERTIFICATE = '2.5.4.37';
  szOID_AUTHORITY_REVOCATION_LIST = '2.5.4.38';
  szOID_CERTIFICATE_REVOCATION_LIST = '2.5.4.39';
  szOID_CROSS_CERTIFICATE_PAIR = '2.5.4.40';

// Undocumented attribute types???
//#define szOID_???                         '2.5.4.41'
  szOID_GIVEN_NAME = '2.5.4.42'; // case-ignore string
  szOID_INITIALS = '2.5.4.43'; // case-ignore string

// Pilot user attribute types:
  szOID_DOMAIN_COMPONENT = '0.9.2342.19200300.100.1.25'; // IA5 string


const
  CERT_RDN_ANY_TYPE = 0;
  CERT_RDN_ENCODED_BLOB = 1;
  CERT_RDN_OCTET_STRING = 2;
  CERT_RDN_NUMERIC_STRING = 3;
  CERT_RDN_PRINTABLE_STRING = 4;
  CERT_RDN_TELETEX_STRING = 5;
  CERT_RDN_T61_STRING = 5;
  CERT_RDN_VIDEOTEX_STRING = 6;
  CERT_RDN_IA5_STRING = 7;
  CERT_RDN_GRAPHIC_STRING = 8;
  CERT_RDN_VISIBLE_STRING = 9;
  CERT_RDN_ISO646_STRING = 9;
  CERT_RDN_GENERAL_STRING = 10;
  CERT_RDN_UNIVERSAL_STRING = 11;
  CERT_RDN_INT4_STRING = 11;
  CERT_RDN_BMP_STRING = 12;
  CERT_RDN_UNICODE_STRING = 12;


// Macro to check that the dwValueType is a character string and not an
// encoded blob or octet string
function IS_CERT_RDN_CHAR_STRING(X: DWORD): BOOL;

type
  PCERT_RDN = ^CERT_RDN;
  CERT_RDN = record
    cRDNAttr: DWORD;
    rgRDNAttr: PCERT_RDN_ATTR;
  end;


type
  PCERT_NAME_INFO = ^CERT_NAME_INFO;
  CERT_NAME_INFO = record
    cRDN: DWORD;
    rgRDN: PCERT_RDN;
  end;


type
  PCERT_NAME_VALUE = ^CERT_NAME_VALUE;
  CERT_NAME_VALUE = record
    dwValueType: DWORD;
    Value: CERT_RDN_VALUE_BLOB;
  end;


type
  PCERT_PUBLIC_KEY_INFO = ^CERT_PUBLIC_KEY_INFO;
  CERT_PUBLIC_KEY_INFO = record
    Algorithm: CRYPT_ALGORITHM_IDENTIFIER;
    PublicKey: CRYPT_BIT_BLOB;
  end;

const
  CERT_RSA_PUBLIC_KEY_OBJID = szOID_RSA_RSA;
  CERT_DEFAULT_OID_PUBLIC_KEY_SIGN = szOID_RSA_RSA;
  CERT_DEFAULT_OID_PUBLIC_KEY_XCHG = szOID_RSA_RSA;


type
  PCERT_INFO = ^CERT_INFO;
  CERT_INFO = record
    dwVersion: DWORD;
    SerialNumber: CRYPT_INTEGER_BLOB;
    SignatureAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    Issuer: CERT_NAME_BLOB;
    NotBefore: TFILETIME;
    NotAfter: TFILETIME;
    Subject: CERT_NAME_BLOB;
    SubjectPublicKeyInfo: CERT_PUBLIC_KEY_INFO;
    IssuerUniqueId: CRYPT_BIT_BLOB;
    SubjectUniqueId: CRYPT_BIT_BLOB;
    cExtension: DWORD;
    rgExtension: PCERT_EXTENSION;
  end;

//+-------------------------------------------------------------------------
//  Certificate versions
//--------------------------------------------------------------------------
const
  CERT_V1 = 0;
  CERT_V2 = 1;
  CERT_V3 = 2;

//+-------------------------------------------------------------------------
//  Certificate Information Flags
//--------------------------------------------------------------------------

  CERT_INFO_VERSION_FLAG = 1;
  CERT_INFO_SERIAL_NUMBER_FLAG = 2;
  CERT_INFO_SIGNATURE_ALGORITHM_FLAG = 3;
  CERT_INFO_ISSUER_FLAG = 4;
  CERT_INFO_NOT_BEFORE_FLAG = 5;
  CERT_INFO_NOT_AFTER_FLAG = 6;
  CERT_INFO_SUBJECT_FLAG = 7;
  CERT_INFO_SUBJECT_PUBLIC_KEY_INFO_FLAG = 8;
  CERT_INFO_ISSUER_UNIQUE_ID_FLAG = 9;
  CERT_INFO_SUBJECT_UNIQUE_ID_FLAG = 10;
  CERT_INFO_EXTENSION_FLAG = 11;


type
  PCRL_ENTRY = ^CRL_ENTRY;
  CRL_ENTRY = record
    SerialNumber: CRYPT_INTEGER_BLOB;
    RevocationDate: TFILETIME;
    cExtension: DWORD;
    rgExtension: PCERT_EXTENSION;
  end;


type
  PCRL_INFO = ^CRL_INFO;
  CRL_INFO = record
    dwVersion: DWORD;
    SignatureAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    Issuer: CERT_NAME_BLOB;
    ThisUpdate: TFILETIME;
    NextUpdate: TFILETIME;
    cCRLEntry: DWORD;
    rgCRLEntry: PCRL_ENTRY;
    cExtension: DWORD;
    rgExtension: PCERT_EXTENSION;
  end;

//+-------------------------------------------------------------------------
//  CRL versions
//--------------------------------------------------------------------------
const
  CRL_V1 = 0;
  CRL_V2 = 1;


type
  PCERT_REQUEST_INFO = ^CERT_REQUEST_INFO;
  CERT_REQUEST_INFO = record
    dwVersion: DWORD;
    Subject: CERT_NAME_BLOB;
    SubjectPublicKeyInfo: CERT_PUBLIC_KEY_INFO;
    cAttribute: DWORD;
    rgAttribute: PCRYPT_ATTRIBUTE;
  end;

//+-------------------------------------------------------------------------
//  Certificate Request versions
//--------------------------------------------------------------------------
const CERT_REQUEST_V1 = 0;

//+-------------------------------------------------------------------------
//  Information stored in Netscape's Keygen request
//--------------------------------------------------------------------------
type
  PCERT_KEYGEN_REQUEST_INFO = ^CERT_KEYGEN_REQUEST_INFO;
  CERT_KEYGEN_REQUEST_INFO = record
    dwVersion: DWORD;
    SubjectPublicKeyInfo: CERT_PUBLIC_KEY_INFO;
    pwszChallengeString: LPWSTR; // encoded as IA5
  end;

const
  CERT_KEYGEN_REQUEST_V1 = 0;

type
  PCERT_SIGNED_CONTENT_INFO = ^CERT_SIGNED_CONTENT_INFO;
  CERT_SIGNED_CONTENT_INFO = record
    ToBeSigned: CRYPT_DER_BLOB;
    SignatureAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    Signature: CRYPT_BIT_BLOB;
  end;

//+-------------------------------------------------------------------------
//  Certificate Trust List (CTL)
//--------------------------------------------------------------------------

//+-------------------------------------------------------------------------
//  CTL Usage. Also used for EnhancedKeyUsage extension.
//--------------------------------------------------------------------------

type
  PCTL_USAGE = ^CTL_USAGE;
  CTL_USAGE = record
    cUsageIdentifier: DWORD;
    rgpszUsageIdentifier: PLPSTR; // array of pszObjId
  end;

type
  CERT_ENHKEY_USAGE = CTL_USAGE;
  PCERT_ENHKEY_USAGE = ^CERT_ENHKEY_USAGE;


//+-------------------------------------------------------------------------
//  An entry in a CTL
//--------------------------------------------------------------------------
type
  PCTL_ENTRY = ^CTL_ENTRY;
  CTL_ENTRY = record
    SubjectIdentifier: CRYPT_DATA_BLOB; // For example, its hash
    cAttribute: DWORD;
    rgAttribute: PCRYPT_ATTRIBUTE; // OPTIONAL
  end;

//+-------------------------------------------------------------------------
//  Information stored in a CTL
//--------------------------------------------------------------------------
type
  PCTL_INFO = ^CTL_INFO;
  CTL_INFO = record
    dwVersion: DWORD;
    SubjectUsage: CTL_USAGE;
    ListIdentifier: CRYPT_DATA_BLOB; // OPTIONAL
    SequenceNumber: CRYPT_INTEGER_BLOB; // OPTIONAL
    ThisUpdate: TFILETIME;
    NextUpdate: TFILETIME; // OPTIONAL
    SubjectAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    cCTLEntry: DWORD;
    rgCTLEntry: PCTL_ENTRY; // OPTIONAL
    cExtension: DWORD;
    rgExtension: PCERT_EXTENSION; // OPTIONAL
  end;

//+-------------------------------------------------------------------------
//  CTL versions
//--------------------------------------------------------------------------
const
  CTL_V1 = 0;

type
  PCRYPT_TIME_STAMP_REQUEST_INFO = ^CRYPT_TIME_STAMP_REQUEST_INFO;
  CRYPT_TIME_STAMP_REQUEST_INFO = record
    pszTimeStampAlgorithm: LPSTR; // pszObjId
    pszContentType: LPSTR; // pszObjId
    Content: CRYPT_OBJID_BLOB;
    cAttribute: DWORD;
    rgAttribute: PCRYPT_ATTRIBUTE;
  end;

const
  CERT_ENCODING_TYPE_MASK = $0000FFFF;
  CMSG_ENCODING_TYPE_MASK = $FFFF0000;

//#define GET_CERT_ENCODING_TYPE(X)   (X & CERT_ENCODING_TYPE_MASK)
//#define GET_CMSG_ENCODING_TYPE(X)   (X & CMSG_ENCODING_TYPE_MASK)
function GET_CERT_ENCODING_TYPE(X: DWORD): DWORD;
function GET_CMSG_ENCODING_TYPE(X: DWORD): DWORD;

const
  CRYPT_ASN_ENCODING = $00000001;
  CRYPT_NDR_ENCODING = $00000002;
  X509_ASN_ENCODING = $00000001;
  X509_NDR_ENCODING = $00000002;
  PKCS_7_ASN_ENCODING = $00010000;
  PKCS_7_NDR_ENCODING = $00020000;


function CryptFormatObject(dwCertEncodingType: DWORD;
  dwFormatType: DWORD;
  dwFormatStrType: DWORD;
  pFormatStruct: PVOID;
  lpszStructType: LPCSTR;
  const pbEncoded: PBYTE;
  cbEncoded: DWORD;
  pbFormat: PVOID;
  pcbFormat: PDWORD): BOOL; stdcall;


function CryptEncodeObject(dwCertEncodingType: DWORD;
  lpszStructType: LPCSTR;
  const pvStructInfo: PVOID;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD): BOOL; stdcall;

function CryptDecodeObject(dwCertEncodingType: DWORD;
  lpszStructType: LPCSTR;
  const pbEncoded: PBYTE;
  cbEncoded: DWORD;
  dwFlags: DWORD;
  pvStructInfo: PVOID;
  pcbStructInfo: PDWORD): BOOL; stdcall;


const
  CRYPT_DECODE_NOCOPY_FLAG = $1;

//+-------------------------------------------------------------------------
//  Predefined X509 certificate data structures that can be encoded / decoded.
//--------------------------------------------------------------------------
  CRYPT_ENCODE_DECODE_NONE = 0;
  X509_CERT = (LPCSTR(1));
  X509_CERT_TO_BE_SIGNED = (LPCSTR(2));
  X509_CERT_CRL_TO_BE_SIGNED = (LPCSTR(3));
  X509_CERT_REQUEST_TO_BE_SIGNED = (LPCSTR(4));
  X509_EXTENSIONS = (LPCSTR(5));
  X509_NAME_VALUE = (LPCSTR(6));
  X509_NAME = (LPCSTR(7));
  X509_PUBLIC_KEY_INFO = (LPCSTR(8));

//+-------------------------------------------------------------------------
//  Predefined X509 certificate extension data structures that can be
//  encoded / decoded.
//--------------------------------------------------------------------------
  X509_AUTHORITY_KEY_ID = (LPCSTR(9));
  X509_KEY_ATTRIBUTES = (LPCSTR(10));
  X509_KEY_USAGE_RESTRICTION = (LPCSTR(11));
  X509_ALTERNATE_NAME = (LPCSTR(12));
  X509_BASIC_CONSTRAINTS = (LPCSTR(13));
  X509_KEY_USAGE = (LPCSTR(14));
  X509_BASIC_CONSTRAINTS2 = (LPCSTR(15));
  X509_CERT_POLICIES = (LPCSTR(16));

//+-------------------------------------------------------------------------
//  Additional predefined data structures that can be encoded / decoded.
//--------------------------------------------------------------------------
  PKCS_UTC_TIME = (LPCSTR(17));
  PKCS_TIME_REQUEST = (LPCSTR(18));
  RSA_CSP_PUBLICKEYBLOB = (LPCSTR(19));
  X509_UNICODE_NAME = (LPCSTR(20));

  X509_KEYGEN_REQUEST_TO_BE_SIGNED = (LPCSTR(21));
  PKCS_ATTRIBUTE = (LPCSTR(22));
  PKCS_CONTENT_INFO_SEQUENCE_OF_ANY = (LPCSTR(23));

//+-------------------------------------------------------------------------
//  Predefined primitive data structures that can be encoded / decoded.
//--------------------------------------------------------------------------
  X509_UNICODE_NAME_VALUE = (LPCSTR(24));
  X509_ANY_STRING = X509_NAME_VALUE;
  X509_UNICODE_ANY_STRING = X509_UNICODE_NAME_VALUE;
  X509_OCTET_STRING = (LPCSTR(25));
  X509_BITS = (LPCSTR(26));
  X509_INTEGER = (LPCSTR(27));
  X509_MULTI_BYTE_INTEGER = (LPCSTR(28));
  X509_ENUMERATED = (LPCSTR(29));
  X509_CHOICE_OF_TIME = (LPCSTR(30));

//+-------------------------------------------------------------------------
//  More predefined X509 certificate extension data structures that can be
//  encoded / decoded.
//--------------------------------------------------------------------------

  X509_AUTHORITY_KEY_ID2 = (LPCSTR(31));
//  X509_AUTHORITY_INFO_ACCESS          (LPCSTR(32));
  X509_CRL_REASON_CODE = X509_ENUMERATED;
  PKCS_CONTENT_INFO = (LPCSTR(33));
  X509_SEQUENCE_OF_ANY = (LPCSTR(34));
  X509_CRL_DIST_POINTS = (LPCSTR(35));
  X509_ENHANCED_KEY_USAGE = (LPCSTR(36));
  PKCS_CTL = (LPCSTR(37));

  X509_MULTI_BYTE_UINT = (LPCSTR(38));
  X509_DSS_PUBLICKEY = X509_MULTI_BYTE_UINT;
  X509_DSS_PARAMETERS = (LPCSTR(39));
  X509_DSS_SIGNATURE = (LPCSTR(40));
  PKCS_RC2_CBC_PARAMETERS = (LPCSTR(41));
  PKCS_SMIME_CAPABILITIES = (LPCSTR(42));

//+-------------------------------------------------------------------------
//  Predefined PKCS #7 data structures that can be encoded / decoded.
//--------------------------------------------------------------------------
  PKCS7_SIGNER_INFO = (LPCSTR(500));


const
  szOID_AUTHORITY_KEY_IDENTIFIER = '2.5.29.1';
  szOID_KEY_ATTRIBUTES = '2.5.29.2';
  szOID_KEY_USAGE_RESTRICTION = '2.5.29.4';
  szOID_SUBJECT_ALT_NAME = '2.5.29.7';
  szOID_ISSUER_ALT_NAME = '2.5.29.8';
  szOID_BASIC_CONSTRAINTS = '2.5.29.10';
  szOID_KEY_USAGE = '2.5.29.15';
  szOID_BASIC_CONSTRAINTS2 = '2.5.29.19';
  szOID_CERT_POLICIES = '2.5.29.32';

  szOID_AUTHORITY_KEY_IDENTIFIER2 = '2.5.29.35';
  szOID_SUBJECT_KEY_IDENTIFIER = '2.5.29.14';
  szOID_SUBJECT_ALT_NAME2 = '2.5.29.17';
  szOID_ISSUER_ALT_NAME2 = '2.5.29.18';
  szOID_CRL_REASON_CODE = '2.5.29.21';
  szOID_CRL_DIST_POINTS = '2.5.29.31';
  szOID_ENHANCED_KEY_USAGE = '2.5.29.37';


// Internet Public Key Infrastructure
  szOID_PKIX = '1.3.6.1.5.5.7';
  szOID_AUTHORITY_INFO_ACCESS = '1.3.6.1.5.5.7.2';

// Microsoft extensions or attributes
  szOID_CERT_EXTENSIONS = '1.3.6.1.4.1.311.2.1.14';
  szOID_NEXT_UPDATE_LOCATION = '1.3.6.1.4.1.311.10.2';

//  Microsoft PKCS #7 ContentType Object Identifiers
  szOID_CTL = '1.3.6.1.4.1.311.10.1';

//+-------------------------------------------------------------------------
//  Extension Object Identifiers (currently not implemented)
//--------------------------------------------------------------------------
  szOID_POLICY_MAPPINGS = '2.5.29.5';
  szOID_SUBJECT_DIR_ATTRS = '2.5.29.9';

//+-------------------------------------------------------------------------
//  Enhanced Key Usage (Purpose) Object Identifiers
//--------------------------------------------------------------------------
const szOID_PKIX_KP = '1.3.6.1.5.5.7.3';

// Consistent key usage bits: DIGITAL_SIGNATURE, KEY_ENCIPHERMENT
// or KEY_AGREEMENT
  szOID_PKIX_KP_SERVER_AUTH = '1.3.6.1.5.5.7.3.1';

// Consistent key usage bits: DIGITAL_SIGNATURE
  szOID_PKIX_KP_CLIENT_AUTH = '1.3.6.1.5.5.7.3.2';

// Consistent key usage bits: DIGITAL_SIGNATURE
  szOID_PKIX_KP_CODE_SIGNING = '1.3.6.1.5.5.7.3.3';

// Consistent key usage bits: DIGITAL_SIGNATURE, NON_REPUDIATION and/or
// (KEY_ENCIPHERMENT or KEY_AGREEMENT)
  szOID_PKIX_KP_EMAIL_PROTECTION = '1.3.6.1.5.5.7.3.4';

//+-------------------------------------------------------------------------
//  Microsoft Enhanced Key Usage (Purpose) Object Identifiers
//+-------------------------------------------------------------------------

//  Signer of CTLs
  szOID_KP_CTL_USAGE_SIGNING = '1.3.6.1.4.1.311.10.3.1';

//  Signer of TimeStamps
  szOID_KP_TIME_STAMP_SIGNING = '1.3.6.1.4.1.311.10.3.2';

//+-------------------------------------------------------------------------
//  Microsoft Attribute Object Identifiers
//+-------------------------------------------------------------------------
  szOID_YESNO_TRUST_ATTR = '1.3.6.1.4.1.311.10.4.1';

type
  PCERT_EXTENSIONS = ^CERT_EXTENSIONS;
  CERT_EXTENSIONS = record
    cExtension: DWORD;
    rgExtension: PCERT_EXTENSION;
  end;


const
  CERT_UNICODE_RDN_ERR_INDEX_MASK = $3FF;
  CERT_UNICODE_RDN_ERR_INDEX_SHIFT = 22;
  CERT_UNICODE_ATTR_ERR_INDEX_MASK = $003F;
  CERT_UNICODE_ATTR_ERR_INDEX_SHIFT = 16;
  CERT_UNICODE_VALUE_ERR_INDEX_MASK = $0000FFFF;
  CERT_UNICODE_VALUE_ERR_INDEX_SHIFT = 0;

{#define GET_CERT_UNICODE_RDN_ERR_INDEX(X)   \
    ((X >> CERT_UNICODE_RDN_ERR_INDEX_SHIFT) & CERT_UNICODE_RDN_ERR_INDEX_MASK)}
function GET_CERT_UNICODE_RDN_ERR_INDEX(X: integer): integer;
{#define GET_CERT_UNICODE_ATTR_ERR_INDEX(X)  \
    ((X >> CERT_UNICODE_ATTR_ERR_INDEX_SHIFT) & CERT_UNICODE_ATTR_ERR_INDEX_MASK)}
function GET_CERT_UNICODE_ATTR_ERR_INDEX(X: integer): integer;
{#define GET_CERT_UNICODE_VALUE_ERR_INDEX(X) \
    (X & CERT_UNICODE_VALUE_ERR_INDEX_MASK)}
function GET_CERT_UNICODE_VALUE_ERR_INDEX(X: integer): integer;
type
  PCERT_AUTHORITY_KEY_ID_INFO = ^CERT_AUTHORITY_KEY_ID_INFO;
  CERT_AUTHORITY_KEY_ID_INFO = record
    KeyId: CRYPT_DATA_BLOB;
    CertIssuer: CERT_NAME_BLOB;
    CertSerialNumber: CRYPT_INTEGER_BLOB;
  end;

type
  PCERT_PRIVATE_KEY_VALIDITY = ^CERT_PRIVATE_KEY_VALIDITY;
  CERT_PRIVATE_KEY_VALIDITY = record
    NotBefore: TFILETIME;
    NotAfter: TFILETIME;
  end;

type
  PCERT_KEY_ATTRIBUTES_INFO = ^CERT_KEY_ATTRIBUTES_INFO;
  CERT_KEY_ATTRIBUTES_INFO = record
    KeyId: CRYPT_DATA_BLOB;
    IntendedKeyUsage: CRYPT_BIT_BLOB;
    pPrivateKeyUsagePeriod: PCERT_PRIVATE_KEY_VALIDITY; // OPTIONAL
  end;

const
  CERT_DIGITAL_SIGNATURE_KEY_USAGE = $80;
  CERT_NON_REPUDIATION_KEY_USAGE = $40;
  CERT_KEY_ENCIPHERMENT_KEY_USAGE = $20;
  CERT_DATA_ENCIPHERMENT_KEY_USAGE = $10;
  CERT_KEY_AGREEMENT_KEY_USAGE = $08;
  CERT_KEY_CERT_SIGN_KEY_USAGE = $04;
  CERT_OFFLINE_CRL_SIGN_KEY_USAGE = $02;

  CERT_CRL_SIGN_KEY_USAGE = $02;

type
  PCERT_POLICY_ID = ^CERT_POLICY_ID;
  CERT_POLICY_ID = record
    cCertPolicyElementId: DWORD;
    rgpszCertPolicyElementId: PLPSTR; // pszObjId
  end;

type
  PCERT_KEY_USAGE_RESTRICTION_INFO = ^CERT_KEY_USAGE_RESTRICTION_INFO;
  CERT_KEY_USAGE_RESTRICTION_INFO = record
    cCertPolicyId: DWORD;
    rgCertPolicyId: PCERT_POLICY_ID;
    RestrictedKeyUsage: CRYPT_BIT_BLOB;
  end;

type
  PCERT_ALT_NAME_ENTRY = ^CERT_ALT_NAME_ENTRY;
  CERT_ALT_NAME_ENTRY = record
    dwAltNameChoice: DWORD;
    case integer of
    {1}0: ({OtherName :Not implemented});
    {2}1: (pwszRfc822Name: LPWSTR); //(encoded IA5)
    {3}2: (pwszDNSName: LPWSTR); //(encoded IA5)
    {4}3: ({x400Address    :Not implemented});
    {5}4: (DirectoryName: CERT_NAME_BLOB);
    {6}5: ({pEdiPartyName  :Not implemented});
    {7}6: (pwszURL: LPWSTR); //(encoded IA5)
    {8}7: (IPAddress: CRYPT_DATA_BLOB); //(Octet String)
    {9}8: (pszRegisteredID: LPSTR); //(Octet String)
  end;

const
  CERT_ALT_NAME_OTHER_NAME = 1;
  CERT_ALT_NAME_RFC822_NAME = 2;
  CERT_ALT_NAME_DNS_NAME = 3;
  CERT_ALT_NAME_X400_ADDRESS = 4;
  CERT_ALT_NAME_DIRECTORY_NAME = 5;
  CERT_ALT_NAME_EDI_PARTY_NAME = 6;
  CERT_ALT_NAME_URL = 7;
  CERT_ALT_NAME_IP_ADDRESS = 8;
  CERT_ALT_NAME_REGISTERED_ID = 9;

type
  PCERT_ALT_NAME_INFO = ^CERT_ALT_NAME_INFO;
  CERT_ALT_NAME_INFO = record
    cAltEntry: DWORD;
    rgAltEntry: PCERT_ALT_NAME_ENTRY;
  end;


const
  CERT_ALT_NAME_ENTRY_ERR_INDEX_MASK = $FF;
  CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT = 16;
  CERT_ALT_NAME_VALUE_ERR_INDEX_MASK = $0000FFFF;
  CERT_ALT_NAME_VALUE_ERR_INDEX_SHIFT = 0;

{#define GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(X)   \
    ((X >> CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT) & \
                                  CERT_ALT_NAME_ENTRY_ERR_INDEX_MASK)}
function GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(X: DWORD): DWORD;

{#define GET_CERT_ALT_NAME_VALUE_ERR_INDEX(X) \
    (X & CERT_ALT_NAME_VALUE_ERR_INDEX_MASK)}
function GET_CERT_ALT_NAME_VALUE_ERR_INDEX(X: DWORD): DWORD;

type
  PCERT_BASIC_CONSTRAINTS_INFO = ^CERT_BASIC_CONSTRAINTS_INFO;
  CERT_BASIC_CONSTRAINTS_INFO = record
    SubjectType: CRYPT_BIT_BLOB;
    fPathLenConstraint: BOOL;
    dwPathLenConstraint: DWORD;
    cSubtreesConstraint: DWORD;
    rgSubtreesConstraint: PCERT_NAME_BLOB;
  end;

const
  CERT_CA_SUBJECT_FLAG = $80;
  CERT_END_ENTITY_SUBJECT_FLAG = $40;

type
  PCERT_BASIC_CONSTRAINTS2_INFO = ^CERT_BASIC_CONSTRAINTS2_INFO;
  CERT_BASIC_CONSTRAINTS2_INFO = record
    fCA: BOOL;
    fPathLenConstraint: BOOL;
    dwPathLenConstraint: DWORD;
  end;


type
  PCERT_POLICY_QUALIFIER_INFO = ^CERT_POLICY_QUALIFIER_INFO;
  CERT_POLICY_QUALIFIER_INFO = record
    pszPolicyQualifierId: LPSTR; // pszObjId
    Qualifier: CRYPT_OBJID_BLOB; // optional
  end;

type
  PCERT_POLICY_INFO = ^CERT_POLICY_INFO;
  CERT_POLICY_INFO = record
    pszPolicyIdentifier: LPSTR; // pszObjId
    cPolicyQualifier: DWORD; // optional
    rgPolicyQualifier: PCERT_POLICY_QUALIFIER_INFO;
  end;

type
  PCERT_POLICIES_INFO = ^CERT_POLICIES_INFO;
  CERT_POLICIES_INFO = record
    cPolicyInfo: DWORD;
    rgPolicyInfo: PCERT_POLICY_INFO;
  end;

type
  PCRYPT_CONTENT_INFO_SEQUENCE_OF_ANY = ^CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY;
  CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY = record
    pszObjId: LPSTR;
    cValue: DWORD;
    rgValue: PCRYPT_DER_BLOB;
  end;

type
  PCRYPT_CONTENT_INFO = ^CRYPT_CONTENT_INFO;
  CRYPT_CONTENT_INFO = record
    pszObjId: LPSTR;
    Content: CRYPT_DER_BLOB;
  end;




type
  PCRYPT_SEQUENCE_OF_ANY = ^CRYPT_SEQUENCE_OF_ANY;
  CRYPT_SEQUENCE_OF_ANY = record
    cValue: DWORD;
    rgValue: PCRYPT_DER_BLOB;
  end;


type
  PCERT_AUTHORITY_KEY_ID2_INFO = ^CERT_AUTHORITY_KEY_ID2_INFO;
  CERT_AUTHORITY_KEY_ID2_INFO = record
    KeyId: CRYPT_DATA_BLOB;
    AuthorityCertIssuer: CERT_ALT_NAME_INFO; // Optional, set cAltEntry to 0 to omit.
    AuthorityCertSerialNumber: CRYPT_INTEGER_BLOB;
  end;


const
  CRL_REASON_UNSPECIFIED = 0;
  CRL_REASON_KEY_COMPROMISE = 1;
  CRL_REASON_CA_COMPROMISE = 2;
  CRL_REASON_AFFILIATION_CHANGED = 3;
  CRL_REASON_SUPERSEDED = 4;
  CRL_REASON_CESSATION_OF_OPERATION = 5;
  CRL_REASON_CERTIFICATE_HOLD = 6;
  CRL_REASON_REMOVE_FROM_CRL = 8;


type
  PCRL_DIST_POINT_NAME = ^CRL_DIST_POINT_NAME;
  CRL_DIST_POINT_NAME = record
    dwDistPointNameChoice: DWORD;
    case integer of
      0: (FullName: CERT_ALT_NAME_INFO); {1}
      1: ({IssuerRDN :Not implemented}); {2}
  end;

const
  CRL_DIST_POINT_NO_NAME = 0;
  CRL_DIST_POINT_FULL_NAME = 1;
  CRL_DIST_POINT_ISSUER_RDN_NAME = 2;

type
  PCRL_DIST_POINT = ^CRL_DIST_POINT;
  CRL_DIST_POINT = record
    DistPointName: CRL_DIST_POINT_NAME; // OPTIONAL
    ReasonFlags: CRYPT_BIT_BLOB; // OPTIONAL
    CRLIssuer: CERT_ALT_NAME_INFO; // OPTIONAL
  end;

const
  CRL_REASON_UNUSED_FLAG = $80;
  CRL_REASON_KEY_COMPROMISE_FLAG = $40;
  CRL_REASON_CA_COMPROMISE_FLAG = $20;
  CRL_REASON_AFFILIATION_CHANGED_FLAG = $10;
  CRL_REASON_SUPERSEDED_FLAG = $08;
  CRL_REASON_CESSATION_OF_OPERATION_FLAG = $04;
  CRL_REASON_CERTIFICATE_HOLD_FLAG = $02;

type
  PCRL_DIST_POINTS_INFO = ^CRL_DIST_POINTS_INFO;
  CRL_DIST_POINTS_INFO = record
    cDistPoint: DWORD;
    rgDistPoint: PCRL_DIST_POINT;
  end;

const
  CRL_DIST_POINT_ERR_INDEX_MASK = $7F;
  CRL_DIST_POINT_ERR_INDEX_SHIFT = 24;

{#define GET_CRL_DIST_POINT_ERR_INDEX(X)   \
    ((X >> CRL_DIST_POINT_ERR_INDEX_SHIFT) & CRL_DIST_POINT_ERR_INDEX_MASK)}
function GET_CRL_DIST_POINT_ERR_INDEX(X: DWORD): DWORD;
const CRL_DIST_POINT_ERR_CRL_ISSUER_BIT = (DWORD($80000000));

{#define IS_CRL_DIST_POINT_ERR_CRL_ISSUER(X)   \
    (0 != (X & CRL_DIST_POINT_ERR_CRL_ISSUER_BIT))}
function IS_CRL_DIST_POINT_ERR_CRL_ISSUER(X: DWORD): BOOL;

type
  PCERT_DSS_PARAMETERS = ^CERT_DSS_PARAMETERS;
  CERT_DSS_PARAMETERS = record
    p: CRYPT_UINT_BLOB;
    q: CRYPT_UINT_BLOB;
    g: CRYPT_UINT_BLOB;
  end;


const
  CERT_DSS_R_LEN = 20;
  CERT_DSS_S_LEN = 20;
  CERT_DSS_SIGNATURE_LEN = (CERT_DSS_R_LEN + CERT_DSS_S_LEN);

// Sequence of 2 unsigned integers (the extra +1 is for a potential leading
// 0x00 to make the integer unsigned)
  CERT_MAX_ASN_ENCODED_DSS_SIGNATURE_LEN = (2 + 2 * (2 + 20 + 1));


type
  PCRYPT_RC2_CBC_PARAMETERS = ^CRYPT_RC2_CBC_PARAMETERS;
  CRYPT_RC2_CBC_PARAMETERS = record
    dwVersion: DWORD;
    fIV: BOOL; // set if has following IV
    rgbIV: array[0..8 - 1] of BYTE;
  end;

const
  CRYPT_RC2_40BIT_VERSION = 160;
  CRYPT_RC2_64BIT_VERSION = 120;
  CRYPT_RC2_128BIT_VERSION = 58;


type
  PCRYPT_SMIME_CAPABILITY = ^CRYPT_SMIME_CAPABILITY;
  CRYPT_SMIME_CAPABILITY = record
    pszObjId: LPSTR;
    Parameters: CRYPT_OBJID_BLOB;
  end;

type
  PCRYPT_SMIME_CAPABILITIES = ^CRYPT_SMIME_CAPABILITIES;
  CRYPT_SMIME_CAPABILITIES = record
    cCapability: DWORD;
    rgCapability: PCRYPT_SMIME_CAPABILITY;
  end;

const
  szOID_NETSCAPE = '2.16.840.1.113730';
  szOID_NETSCAPE_CERT_EXTENSION = '2.16.840.1.113730.1';
  szOID_NETSCAPE_CERT_TYPE = '2.16.840.1.113730.1.1';
  szOID_NETSCAPE_BASE_URL = '2.16.840.1.113730.1.2';
  szOID_NETSCAPE_REVOCATION_URL = '2.16.840.1.113730.1.3';
  szOID_NETSCAPE_CA_REVOCATION_URL = '2.16.840.1.113730.1.4';
  szOID_NETSCAPE_CERT_RENEWAL_URL = '2.16.840.1.113730.1.7';
  szOID_NETSCAPE_CA_POLICY_URL = '2.16.840.1.113730.1.8';
  szOID_NETSCAPE_SSL_SERVER_NAME = '2.16.840.1.113730.1.12';
  szOID_NETSCAPE_COMMENT = '2.16.840.1.113730.1.13';

//+-------------------------------------------------------------------------
//  Netscape Certificate Data Type Object Identifiers
//--------------------------------------------------------------------------

const
  szOID_NETSCAPE_DATA_TYPE = '2.16.840.1.113730.2';
  szOID_NETSCAPE_CERT_SEQUENCE = '2.16.840.1.113730.2.5';

const
  NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE = $80;
  NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE = $40;
  NETSCAPE_SSL_CA_CERT_TYPE = $04;

type
  HCRYPTOIDFUNCSET = procedure;
  HCRYPTOIDFUNCADDR = procedure;

// Predefined OID Function Names
const
  CRYPT_OID_ENCODE_OBJECT_FUNC = 'CryptDllEncodeObject';
  CRYPT_OID_DECODE_OBJECT_FUNC = 'CryptDllDecodeObject';
  CRYPT_OID_CREATE_COM_OBJECT_FUNC = 'CryptDllCreateCOMObject';
  CRYPT_OID_VERIFY_REVOCATION_FUNC = 'CertDllVerifyRevocation';
  CRYPT_OID_VERIFY_CTL_USAGE_FUNC = 'CertDllVerifyCTLUsage';
  CRYPT_OID_FORMAT_OBJECT_FUNC = 'CryptDllFormatObject';
  CRYPT_OID_FIND_OID_INFO_FUNC = 'CryptDllFindOIDInfo';

const
  CRYPT_OID_REGPATH = 'Software\\Microsoft\\Cryptography\\OID';
  CRYPT_OID_REG_ENCODING_TYPE_PREFIX = 'EncodingType ';
{$IFNDEF VER90}
  CRYPT_OID_REG_DLL_VALUE_NAME = WideString('Dll');
  CRYPT_OID_REG_FUNC_NAME_VALUE_NAME = WideString('FuncName');
{$ELSE}
  CRYPT_OID_REG_DLL_VALUE_NAME = ('Dll');
  CRYPT_OID_REG_FUNC_NAME_VALUE_NAME = ('FuncName');
{$ENDIF}
  CRYPT_OID_REG_FUNC_NAME_VALUE_NAME_A = 'FuncName';

// OID used for Default OID functions
  CRYPT_DEFAULT_OID = 'DEFAULT';

type
  PCRYPT_OID_FUNC_ENTRY = ^CRYPT_OID_FUNC_ENTRY;
  CRYPT_OID_FUNC_ENTRY = record
    pszOID: LPCSTR;
    pvFuncAddr: PVOID;
  end;

const
  CRYPT_INSTALL_OID_FUNC_BEFORE_FLAG = 1;

function CryptInstallOIDFunctionAddress(hModule: HMODULE; // hModule passed to DllMain
  dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  cFuncEntry: DWORD;
  const rgFuncEntry: array of CRYPT_OID_FUNC_ENTRY;
  dwFlags: DWORD): BOOL; stdcall;


function CryptInitOIDFunctionSet(pszFuncName: LPCSTR;
  dwFlags: DWORD): HCRYPTOIDFUNCSET; stdcall;


function CryptGetOIDFunctionAddress(hFuncSet: HCRYPTOIDFUNCSET;
  dwEncodingType: DWORD;
  pszOID: LPCSTR;
  dwFlags: DWORD;
  var ppvFuncAddr: array of PVOID;
  var phFuncAddr: HCRYPTOIDFUNCADDR): BOOL; stdcall;


function CryptGetDefaultOIDDllList(hFuncSet: HCRYPTOIDFUNCSET;
  dwEncodingType: DWORD;
  pwszDllList: LPWSTR;
  pcchDllList: PDWORD): BOOL; stdcall;

function CryptGetDefaultOIDFunctionAddress(hFuncSet: HCRYPTOIDFUNCSET;
  dwEncodingType: DWORD;
  pwszDll: DWORD;
  dwFlags: LPCWSTR;
  var ppvFuncAddr: array of PVOID;
  var phFuncAddr: HCRYPTOIDFUNCADDR): BOOL; stdcall;


function CryptFreeOIDFunctionAddress(hFuncAddr: HCRYPTOIDFUNCADDR;
  dwFlags: DWORD): BOOL; stdcall;

function CryptRegisterOIDFunction(dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  pszOID: LPCSTR; //OPTIONAL
  pwszDll: LPCWSTR; //OPTIONAL
  pszOverrideFuncName: LPCSTR): BOOL; stdcall;

function CryptUnregisterOIDFunction(dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  pszOID: LPCSTR): BOOL; stdcall;

function CryptRegisterDefaultOIDFunction(dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  dwIndex: DWORD;
  pwszDll: LPCWSTR): BOOL; stdcall;

const
  CRYPT_REGISTER_FIRST_INDEX = 0;
  CRYPT_REGISTER_LAST_INDEX = $FFFFFFFF;

function CryptUnregisterDefaultOIDFunction(dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  pwszDll: LPCWSTR): BOOL; stdcall;

function CryptSetOIDFunctionValue(dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  pszOID: LPCSTR;
  pwszValueName: LPCWSTR;
  dwValueType: DWORD;
  const pbValueData: PBYTE;
  cbValueData: DWORD): BOOL; stdcall;

function CryptGetOIDFunctionValue(dwEncodingType: DWORD;
  pszFuncName: LPCSTR;
  pwszValueName: LPCSTR;
  pszOID: LPCWSTR;
  pdwValueType: PDWORD;
  pbValueData: PBYTE;
  pcbValueData: PDWORD): BOOL; stdcall;

type
  PFN_CRYPT_ENUM_OID_FUNC = function(dwEncodingType: DWORD;
    pszFuncName: LPCSTR;
    pszOID: LPCSTR;
    cValue: DWORD;
    const rgdwValueType: array of DWORD;
    const rgpwszValueName: array of LPCWSTR;
    const rgpbValueData: array of PBYTE;
    const rgcbValueData: array of DWORD;
    pvArg: PVOID): BOOL; stdcall;

function CryptEnumOIDFunction(dwEncodingType: DWORD;
  pszFuncName: LPCSTR; //OPTIONAL
  pszOID: LPCSTR; //OPTIONAL
  dwFlags: DWORD;
  pvArg: PVOID;
  pfnEnumOIDFunc: PFN_CRYPT_ENUM_OID_FUNC): BOOL; stdcall;

const
  CRYPT_MATCH_ANY_ENCODING_TYPE = $FFFFFFFF;

//+-------------------------------------------------------------------------
//  OID Information
//--------------------------------------------------------------------------

type
  PCRYPT_OID_INFO = ^CRYPT_OID_INFO;
  CRYPT_OID_INFO = record
    cbSize: DWORD;
    pszOID: LPCSTR;
    pwszName: LPCWSTR;
    dwGroupId: DWORD;
    EnumValue: record {type EnumValue for the union part of the original struct --max--}
      case integer of
        0: (dwValue: DWORD);
        1: (Algid: ALG_ID);
        2: (dwLength: DWORD);
    end;
    ExtraInfo: CRYPT_DATA_BLOB;
  end;

type
  CCRYPT_OID_INFO = CRYPT_OID_INFO;
  PCCRYPT_OID_INFO = ^CCRYPT_OID_INFO;

//+-------------------------------------------------------------------------
//  OID Group IDs
//--------------------------------------------------------------------------

const
  CRYPT_HASH_ALG_OID_GROUP_ID = 1;
  CRYPT_ENCRYPT_ALG_OID_GROUP_ID = 2;
  CRYPT_PUBKEY_ALG_OID_GROUP_ID = 3;
  CRYPT_SIGN_ALG_OID_GROUP_ID = 4;
  CRYPT_RDN_ATTR_OID_GROUP_ID = 5;
  CRYPT_EXT_OR_ATTR_OID_GROUP_ID = 6;
  CRYPT_ENHKEY_USAGE_OID_GROUP_ID = 7;
  CRYPT_POLICY_OID_GROUP_ID = 8;
  CRYPT_LAST_OID_GROUP_ID = 8;

  CRYPT_FIRST_ALG_OID_GROUP_ID = CRYPT_HASH_ALG_OID_GROUP_ID;
  CRYPT_LAST_ALG_OID_GROUP_ID = CRYPT_SIGN_ALG_OID_GROUP_ID;
  CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG = $1;
  CRYPT_OID_USE_PUBKEY_PARA_FOR_PKCS7_FLAG = $2;

function CryptFindOIDInfo(dwKeyType: DWORD;
  pvKey: PVOID;
  dwGroupId: DWORD): PCCRYPT_OID_INFO; stdcall;

const
  CRYPT_OID_INFO_OID_KEY = 1;
  CRYPT_OID_INFO_NAME_KEY = 2;
  CRYPT_OID_INFO_ALGID_KEY = 3;
  CRYPT_OID_INFO_SIGN_KEY = 4;

function CryptRegisterOIDInfo(pInfo: PCCRYPT_OID_INFO;
  dwFlags: DWORD): BOOL; stdcall;

const
  CRYPT_INSTALL_OID_INFO_BEFORE_FLAG = 1;

function CryptUnregisterOIDInfo(pInfo: PCCRYPT_OID_INFO): BOOL; stdcall;

//+=========================================================================
//  Low Level Cryptographic Message Data Structures and APIs
//==========================================================================

type
  HCRYPTMSG = Pointer;

const
  szOID_PKCS_7_DATA = '1.2.840.113549.1.7.1';
  szOID_PKCS_7_SIGNED = '1.2.840.113549.1.7.2';
  szOID_PKCS_7_ENVELOPED = '1.2.840.113549.1.7.3';
  szOID_PKCS_7_SIGNEDANDENVELOPED = '1.2.840.113549.1.7.4';
  szOID_PKCS_7_DIGESTED = '1.2.840.113549.1.7.5';
  szOID_PKCS_7_ENCRYPTED = '1.2.840.113549.1.7.6';

  szOID_PKCS_9_CONTENT_TYPE = '1.2.840.113549.1.9.3';
  szOID_PKCS_9_MESSAGE_DIGEST = '1.2.840.113549.1.9.4';

//+-------------------------------------------------------------------------
//  Message types
//--------------------------------------------------------------------------

const
  CMSG_DATA = 1;
  CMSG_SIGNED = 2;
  CMSG_ENVELOPED = 3;
  CMSG_SIGNED_AND_ENVELOPED = 4;
  CMSG_HASHED = 5;
  CMSG_ENCRYPTED = 6;

//+-------------------------------------------------------------------------
//  Message Type Bit Flags
//--------------------------------------------------------------------------

  CMSG_ALL_FLAGS = (not ULONG(0));
  CMSG_DATA_FLAG = (1 shl CMSG_DATA);
  CMSG_SIGNED_FLAG = (1 shl CMSG_SIGNED);
  CMSG_ENVELOPED_FLAG = (1 shl CMSG_ENVELOPED);
  CMSG_SIGNED_AND_ENVELOPED_FLAG = (1 shl CMSG_SIGNED_AND_ENVELOPED);
  CMSG_HASHED_FLAG = (1 shl CMSG_HASHED);
  CMSG_ENCRYPTED_FLAG = (1 shl CMSG_ENCRYPTED);

type
  PCMSG_SIGNER_ENCODE_INFO = ^CMSG_SIGNER_ENCODE_INFO;
  CMSG_SIGNER_ENCODE_INFO = record
    cbSize: DWORD;
    pCertInfo: PCERT_INFO;
    hCryptProv: HCRYPTPROV;
    dwKeySpec: DWORD;
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvHashAuxInfo: PVOID;
    cAuthAttr: DWORD;
    rgAuthAttr: PCRYPT_ATTRIBUTE;
    cUnauthAttr: DWORD;
    rgUnauthAttr: PCRYPT_ATTRIBUTE;
  end;

type
  PCMSG_SIGNED_ENCODE_INFO = ^CMSG_SIGNED_ENCODE_INFO;
  CMSG_SIGNED_ENCODE_INFO = record
    cbSize: DWORD;
    cSigners: DWORD;
    rgSigners: PCMSG_SIGNER_ENCODE_INFO;
    cCertEncoded: DWORD;
    rgCertEncoded: PCERT_BLOB;
    cCrlEncoded: DWORD;
    rgCrlEncoded: PCRL_BLOB;
  end;

type
  PCMSG_ENVELOPED_ENCODE_INFO = ^CMSG_ENVELOPED_ENCODE_INFO;
  CMSG_ENVELOPED_ENCODE_INFO = record
    cbSize: DWORD;
    hCryptProv: HCRYPTPROV;
    ContentEncryptionAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvEncryptionAuxInfo: PVOID;
    cRecipients: DWORD;
    rgpRecipients: PPCERT_INFO; // pointer to array of PCERT_INFO
  end;

type
  PCMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO = ^CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO;
  CMSG_SIGNED_AND_ENVELOPED_ENCODE_INFO = record
    cbSize: DWORD;
    SignedInfo: CMSG_SIGNED_ENCODE_INFO;
    EnvelopedInfo: CMSG_ENVELOPED_ENCODE_INFO;
  end;

type
  PCMSG_HASHED_ENCODE_INFO = ^CMSG_HASHED_ENCODE_INFO;
  CMSG_HASHED_ENCODE_INFO = record
    cbSize: DWORD;
    hCryptProv: HCRYPTPROV;
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvHashAuxInfo: PVOID;
  end;

type
  PCMSG_ENCRYPTED_ENCODE_INFO = ^CMSG_ENCRYPTED_ENCODE_INFO;
  CMSG_ENCRYPTED_ENCODE_INFO = record
    cbSize: DWORD;
    ContentEncryptionAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvEncryptionAuxInfo: PVOID;
  end;


type
  PFN_CMSG_STREAM_OUTPUT = function(
    const pvArg: PVOID;
    pbData: PBYTE;
    cbData: DWORD;
    fFinal: BOOL): BOOL; stdcall;

const
  CMSG_INDEFINITE_LENGTH = ($FFFFFFFF);

type
  PCMSG_STREAM_INFO = ^CMSG_STREAM_INFO;
  CMSG_STREAM_INFO = record
    cbContent: DWORD;
    pfnStreamOutput: PFN_CMSG_STREAM_OUTPUT;
    pvArg: PVOID;
  end;

//+-------------------------------------------------------------------------
//  Open dwFlags
//--------------------------------------------------------------------------

const
  CMSG_BARE_CONTENT_FLAG = $00000001;
  CMSG_LENGTH_ONLY_FLAG = $00000002;
  CMSG_DETACHED_FLAG = $00000004;
  CMSG_AUTHENTICATED_ATTRIBUTES_FLAG = $00000008;
  CMSG_CONTENTS_OCTETS_FLAG = $00000010;
  CMSG_MAX_LENGTH_FLAG = $00000020;


function CryptMsgOpenToEncode(dwMsgEncodingType: DWORD;
  dwFlags: DWORD;
  dwMsgType: DWORD;
  pvMsgEncodeInfo: PVOID;
  pszInnerContentObjID: LPSTR; //OPTIONAL
  pStreamInfo: PCMSG_STREAM_INFO //OPTIONAL
  ): HCRYPTMSG; stdcall;

function CryptMsgCalculateEncodedLength(dwMsgEncodingType: DWORD;
  dwFlags: DWORD;
  dwMsgType: DWORD;
  pvMsgEncodeInfo: PVOID;
  pszInnerContentObjID: LPSTR; //OPTIONAL
  cbData: DWORD): DWORD; stdcall;

function CryptMsgOpenToDecode(dwMsgEncodingType: DWORD;
  dwFlags: DWORD;
  dwMsgType: DWORD;
  hCryptProv: HCRYPTPROV;
  pRecipientInfo: PCERT_INFO; //OPTIONAL
  pStreamInfo: PCMSG_STREAM_INFO //OPTIONAL
  ): HCRYPTMSG; stdcall;


function CryptMsgClose(hCryptMsg: HCRYPTMSG): BOOL; stdcall;

function CryptMsgUpdate(hCryptMsg: HCRYPTMSG;
  const pbData: PBYTE;
  cbData: DWORD;
  fFinal: BOOL): BOOL; stdcall;


function CryptMsgControl(hCryptMsg: HCRYPTMSG;
  dwFlags: DWORD;
  dwCtrlType: DWORD;
  pvCtrlPara: PVOID): BOOL; stdcall;

//+-------------------------------------------------------------------------
//  Message control types
//--------------------------------------------------------------------------

const
  CMSG_CTRL_VERIFY_SIGNATURE = 1;
  CMSG_CTRL_DECRYPT = 2;
  CMSG_CTRL_VERIFY_HASH = 5;
  CMSG_CTRL_ADD_SIGNER = 6;
  CMSG_CTRL_DEL_SIGNER = 7;
  CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR = 8;
  CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR = 9;
  CMSG_CTRL_ADD_CERT = 10;
  CMSG_CTRL_DEL_CERT = 11;
  CMSG_CTRL_ADD_CRL = 12;
  CMSG_CTRL_DEL_CRL = 13;

type
  PCMSG_CTRL_DECRYPT_PARA = ^CMSG_CTRL_DECRYPT_PARA;
  CMSG_CTRL_DECRYPT_PARA = record
    cbSize: DWORD;
    hCryptProv: HCRYPTPROV;
    dwKeySpec: DWORD;
    dwRecipientIndex: DWORD;
  end;

type
  PCMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA = ^CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA;
  CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA = record
    cbSize: DWORD;
    dwSignerIndex: DWORD;
    blob: CRYPT_DATA_BLOB;
  end;

type
  PCMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA = ^CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA;
  CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA = record
    cbSize: DWORD;
    dwSignerIndex: DWORD;
    dwUnauthAttrIndex: DWORD;
  end;


function CryptMsgVerifyCountersignatureEncoded(hCryptProv: HCRYPTPROV;
  dwEncodingType: DWORD;
  pbSignerInfo: PBYTE;
  cbSignerInfo: DWORD;
  pbSignerInfoCountersignature: PBYTE;
  cbSignerInfoCountersignature: DWORD;
  pciCountersigner: PCERT_INFO): BOOL; stdcall;


function CryptMsgCountersign(hCryptMsg: HCRYPTMSG;
  dwIndex: DWORD;
  cCountersigners: DWORD;
  rgCountersigners: PCMSG_SIGNER_ENCODE_INFO): BOOL; stdcall;

function CryptMsgCountersignEncoded(dwEncodingType: DWORD;
  pbSignerInfo: PBYTE;
  cbSignerInfo: DWORD;
  cCountersigners: DWORD;
  rgCountersigners: PCMSG_SIGNER_ENCODE_INFO;
  pbCountersignature: PBYTE;
  pcbCountersignature: PDWORD): BOOL; stdcall;


function CryptMsgGetParam(hCryptMsg: HCRYPTMSG;
  dwParamType: DWORD;
  dwIndex: DWORD;
  pvData: PVOID;
  pcbData: PDWORD): BOOL; stdcall;

//+-------------------------------------------------------------------------
//  Get parameter types and their corresponding data structure definitions.
//--------------------------------------------------------------------------

const
  CMSG_TYPE_PARAM = 1;
  CMSG_CONTENT_PARAM = 2;
  CMSG_BARE_CONTENT_PARAM = 3;
  CMSG_INNER_CONTENT_TYPE_PARAM = 4;
  CMSG_SIGNER_COUNT_PARAM = 5;
  CMSG_SIGNER_INFO_PARAM = 6;
  CMSG_SIGNER_CERT_INFO_PARAM = 7;
  CMSG_SIGNER_HASH_ALGORITHM_PARAM = 8;
  CMSG_SIGNER_AUTH_ATTR_PARAM = 9;
  CMSG_SIGNER_UNAUTH_ATTR_PARAM = 10;
  CMSG_CERT_COUNT_PARAM = 11;
  CMSG_CERT_PARAM = 12;
  CMSG_CRL_COUNT_PARAM = 13;
  CMSG_CRL_PARAM = 14;
  CMSG_ENVELOPE_ALGORITHM_PARAM = 15;
  CMSG_RECIPIENT_COUNT_PARAM = 17;
  CMSG_RECIPIENT_INDEX_PARAM = 18;
  CMSG_RECIPIENT_INFO_PARAM = 19;
  CMSG_HASH_ALGORITHM_PARAM = 20;
  CMSG_HASH_DATA_PARAM = 21;
  CMSG_COMPUTED_HASH_PARAM = 22;
  CMSG_ENCRYPT_PARAM = 26;
  CMSG_ENCRYPTED_DIGEST = 27;
  CMSG_ENCODED_SIGNER = 28;
  CMSG_ENCODED_MESSAGE = 29;

type
  PCMSG_SIGNER_INFO = ^CMSG_SIGNER_INFO;
  CMSG_SIGNER_INFO = record
    dwVersion: DWORD;
    Issuer: CERT_NAME_BLOB;
    SerialNumber: CRYPT_INTEGER_BLOB;
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    HashEncryptionAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    EncryptedHash: CRYPT_DATA_BLOB;
    AuthAttrs: CRYPT_ATTRIBUTES;
    UnauthAttrs: CRYPT_ATTRIBUTES;
  end;


type
  CMSG_ATTR = CRYPT_ATTRIBUTES;
  PCMSG_ATTR = ^CRYPT_ATTRIBUTES;

const
  CMSG_OID_GEN_ENCRYPT_KEY_FUNC = 'CryptMsgDllGenEncryptKey';

type
  PFN_CMSG_GEN_ENCRYPT_KEY = function(phCryptProv: PHCRYPTPROV;
    paiEncrypt: PCRYPT_ALGORITHM_IDENTIFIER;
    pvEncryptAuxInfo: PVOID;
    pPublicKeyInfo: PCERT_PUBLIC_KEY_INFO;
    phEncryptKey: PHCRYPTKEY
    ): BOOL; stdcall;

const
  CMSG_OID_EXPORT_ENCRYPT_KEY_FUNC = 'CryptMsgDllExportEncryptKey';

type
  PFN_CMSG_EXPORT_ENCRYPT_KEY = function(hCryptProv: HCRYPTPROV;
    hEncryptKey: HCRYPTKEY;
    pPublicKeyInfo: PCERT_PUBLIC_KEY_INFO;
    pbData: PBYTE;
    pcbData: PDWORD): BOOL; stdcall;

const
  CMSG_OID_IMPORT_ENCRYPT_KEY_FUNC = 'CryptMsgDllImportEncryptKey';

type
  PFN_CMSG_IMPORT_ENCRYPT_KEY = function(hCryptProv: HCRYPTPROV;
    dwKeySpec: DWORD;
    paiEncrypt: PCRYPT_ALGORITHM_IDENTIFIER;
    paiPubKey: PCRYPT_ALGORITHM_IDENTIFIER;
    pbEncodedKey: PBYTE;
    cbEncodedKey: DWORD;
    phEncryptKey: PHCRYPTKEY
    ): BOOL; stdcall;

type
  HCERTSTORE = PVOID;

type
  PCERT_CONTEXT = ^CERT_CONTEXT;
  CERT_CONTEXT = record
    dwCertEncodingType: DWORD;
    pbCertEncoded: PBYTE;
    cbCertEncoded: DWORD;
    pCertInfo: PCERT_INFO;
    hCertStore: HCERTSTORE;
  end;

type
  PCCERT_CONTEXT = ^CERT_CONTEXT;


type
  PCRL_CONTEXT = ^CRL_CONTEXT;
  CRL_CONTEXT = record
    dwCertEncodingType: DWORD;
    pbCrlEncoded: PBYTE;
    cbCrlEncoded: DWORD;
    pCrlInfo: PCRL_INFO;
    hCertStore: HCERTSTORE;
  end;

type
  PCCRL_CONTEXT = ^CRL_CONTEXT;


type
  PCTL_CONTEXT = ^CTL_CONTEXT;
  CTL_CONTEXT = record
    dwMsgAndCertEncodingType: DWORD;
    pbCtlEncoded: PBYTE;
    cbCtlEncoded: DWORD;
    pCtlInfo: PCTL_INFO;
    hCertStore: HCERTSTORE;
    hCryptMsg: HCRYPTMSG;
    pbCtlContent: PBYTE;
    cbCtlContent: DWORD;
  end;

type
  PCCTL_CONTEXT = ^CTL_CONTEXT;

const
  CERT_KEY_PROV_HANDLE_PROP_ID = 1;
  CERT_KEY_PROV_INFO_PROP_ID = 2;
  CERT_SHA1_HASH_PROP_ID = 3;
  CERT_MD5_HASH_PROP_ID = 4;
  CERT_HASH_PROP_ID = CERT_SHA1_HASH_PROP_ID;
  CERT_KEY_CONTEXT_PROP_ID = 5;
  CERT_KEY_SPEC_PROP_ID = 6;
  CERT_IE30_RESERVED_PROP_ID = 7;
  CERT_PUBKEY_HASH_RESERVED_PROP_ID = 8;
  CERT_ENHKEY_USAGE_PROP_ID = 9;
  CERT_CTL_USAGE_PROP_ID = CERT_ENHKEY_USAGE_PROP_ID;
  CERT_NEXT_UPDATE_LOCATION_PROP_ID = 10;
  CERT_FRIENDLY_NAME_PROP_ID = 11;
  CERT_PVK_FILE_PROP_ID = 12;
// Note, 32 - 34 are reserved for the CERT, CRL and CTL file element IDs.
  CERT_FIRST_RESERVED_PROP_ID = 13;

  CERT_LAST_RESERVED_PROP_ID = $00007FFF;
  CERT_FIRST_USER_PROP_ID = $00008000;
  CERT_LAST_USER_PROP_ID = $0000FFFF;

function IS_CERT_HASH_PROP_ID(X: DWORD): BOOL;

type
  PCRYPT_KEY_PROV_PARAM = ^CRYPT_KEY_PROV_PARAM;
  CRYPT_KEY_PROV_PARAM = record
    dwParam: DWORD;
    pbData: PBYTE;
    cbData: DWORD;
    dwFlags: DWORD;
  end;

type
  PCRYPT_KEY_PROV_INFO = ^CRYPT_KEY_PROV_INFO;
  CRYPT_KEY_PROV_INFO = record
    pwszContainerName: LPWSTR;
    pwszProvName: LPWSTR;
    dwProvType: DWORD;
    dwFlags: DWORD;
    cProvParam: DWORD;
    rgProvParam: PCRYPT_KEY_PROV_PARAM;
    dwKeySpec: DWORD;
  end;

const
  CERT_SET_KEY_PROV_HANDLE_PROP_ID = $00000001;
  CERT_SET_KEY_CONTEXT_PROP_ID = $00000001;

type
  PCERT_KEY_CONTEXT = ^CERT_KEY_CONTEXT;
  CERT_KEY_CONTEXT = record
    cbSize: DWORD; // sizeof(CERT_KEY_CONTEXT)
    hCryptProv: HCRYPTPROV;
    dwKeySpec: DWORD;
  end;

//+-------------------------------------------------------------------------
//  Certificate Store Provider Types
//--------------------------------------------------------------------------

const
  CERT_STORE_PROV_MSG = (LPCSTR(1));
  CERT_STORE_PROV_MEMORY = (LPCSTR(2));
  CERT_STORE_PROV_FILE = (LPCSTR(3));
  CERT_STORE_PROV_REG = (LPCSTR(4));

  CERT_STORE_PROV_PKCS7 = (LPCSTR(5));
  CERT_STORE_PROV_SERIALIZED = (LPCSTR(6));
  CERT_STORE_PROV_FILENAME_A = (LPCSTR(7));
  CERT_STORE_PROV_FILENAME_W = (LPCSTR(8));
  CERT_STORE_PROV_FILENAME = CERT_STORE_PROV_FILENAME_W;
  CERT_STORE_PROV_SYSTEM_A = (LPCSTR(9));
  CERT_STORE_PROV_SYSTEM_W = (LPCSTR(10));
  CERT_STORE_PROV_SYSTEM = CERT_STORE_PROV_SYSTEM_W;

  sz_CERT_STORE_PROV_MEMORY = 'Memory';
  sz_CERT_STORE_PROV_FILENAME_W = 'File';
  sz_CERT_STORE_PROV_FILENAME = sz_CERT_STORE_PROV_FILENAME_W;
  sz_CERT_STORE_PROV_SYSTEM_W = 'System';
  sz_CERT_STORE_PROV_SYSTEM = sz_CERT_STORE_PROV_SYSTEM_W;
  sz_CERT_STORE_PROV_PKCS7 = 'PKCS7';
  sz_CERT_STORE_PROV_SERIALIZED = 'Serialized';

//+-------------------------------------------------------------------------
//  Certificate Store verify/results flags
//--------------------------------------------------------------------------

  CERT_STORE_SIGNATURE_FLAG = $00000001;
  CERT_STORE_TIME_VALIDITY_FLAG = $00000002;
  CERT_STORE_REVOCATION_FLAG = $00000004;
  CERT_STORE_NO_CRL_FLAG = $00010000;
  CERT_STORE_NO_ISSUER_FLAG = $00020000;

//+-------------------------------------------------------------------------
//  Certificate Store open/property flags
//--------------------------------------------------------------------------

  CERT_STORE_NO_CRYPT_RELEASE_FLAG = $00000001;
  CERT_STORE_READONLY_FLAG = $00008000;

//+-------------------------------------------------------------------------
//  Certificate Store Provider flags are in the HiWord (0xFFFF0000)
//--------------------------------------------------------------------------

//+-------------------------------------------------------------------------
//  Certificate System Store Flag Values
//--------------------------------------------------------------------------
// Location of the system store in the registry:
//  HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE
  CERT_SYSTEM_STORE_LOCATION_MASK = $00030000;
  CERT_SYSTEM_STORE_CURRENT_USER = $00010000;
  CERT_SYSTEM_STORE_LOCAL_MACHINE = $00020000;

function CertOpenStore(lpszStoreProvider: LPCSTR;
  dwEncodingType: DWORD;
  hCryptProv: HCRYPTPROV;
  dwFlags: DWORD;
  const pvPara: PVOID): HCERTSTORE; stdcall;


// Handle returned by the store provider when opened.
type
  HCERTSTOREPROV = PVOID;

// Store Provider OID function's pszFuncName.
const
  CRYPT_OID_OPEN_STORE_PROV_FUNC = 'CertDllOpenStoreProv';

type
  PCERT_STORE_PROV_INFO = ^CERT_STORE_PROV_INFO;
  CERT_STORE_PROV_INFO = record
    cbSize: DWORD;
    cStoreProvFunc: DWORD;
    rgpvStoreProvFunc: PPVOID;
    hStoreProv: HCERTSTOREPROV;
    dwStoreProvFlags: DWORD;
  end;

type
  PFN_CERT_DLL_OPEN_STORE_PROV_FUNC = function(lpszStoreProvider: LPCSTR;
    dwEncodingType: DWORD;
    hCryptProv: HCRYPTPROV;
    dwFlags: DWORD;
    const pvPara: PVOID;
    hCertStore: HCERTSTORE;
    pStoreProvInfo: PCERT_STORE_PROV_INFO
    ): BOOL; stdcall;

const
  CERT_STORE_PROV_CLOSE_FUNC = 0;
  CERT_STORE_PROV_READ_CERT_FUNC = 1;
  CERT_STORE_PROV_WRITE_CERT_FUNC = 2;
  CERT_STORE_PROV_DELETE_CERT_FUNC = 3;
  CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC = 4;
  CERT_STORE_PROV_READ_CRL_FUNC = 5;
  CERT_STORE_PROV_WRITE_CRL_FUNC = 6;
  CERT_STORE_PROV_DELETE_CRL_FUNC = 7;
  CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC = 8;
  CERT_STORE_PROV_READ_CTL_FUNC = 9;
  CERT_STORE_PROV_WRITE_CTL_FUNC = 10;
  CERT_STORE_PROV_DELETE_CTL_FUNC = 11;
  CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC = 12;

type
  PFN_CERT_STORE_PROV_CLOSE = procedure(hStoreProv: HCERTSTOREPROV;
    dwFlags: DWORD); stdcall;

type
  PFN_CERT_STORE_PROV_READ_CERT = function(hStoreProv: HCERTSTOREPROV;
    pStoreCertContext: PCCERT_CONTEXT;
    dwFlags: DWORD;
    var ppProvCertContext: PCCERT_CONTEXT
    ): BOOL; stdcall;

const
  CERT_STORE_PROV_WRITE_ADD_FLAG = $1;

type
  PFN_CERT_STORE_PROV_WRITE_CERT = function(hStoreProv: HCERTSTOREPROV;
    pCertContext: PCCERT_CONTEXT;
    dwFlags: DWORD): BOOL; stdcall;

type
  PFN_CERT_STORE_PROV_DELETE_CERT = function(hStoreProv: HCERTSTOREPROV;
    pCertContext: PCCERT_CONTEXT;
    dwFlags: DWORD): BOOL; stdcall;

type
  PFN_CERT_STORE_PROV_SET_CERT_PROPERTY = function(hStoreProv: HCERTSTOREPROV;
    pCertContext: PCCERT_CONTEXT;
    dwPropId: DWORD;
    dwFlags: DWORD;
    const pvData: PVOID
    ): BOOL; stdcall;


type
  PFN_CERT_STORE_PROV_READ_CRL = function(hStoreProv: HCERTSTOREPROV;
    pStoreCrlContext: PCCRL_CONTEXT;
    dwFlags: DWORD;
    var ppProvCrlContext: PCCRL_CONTEXT
    ): BOOL; stdcall;


type
  PFN_CERT_STORE_PROV_WRITE_CRL = function(hStoreProv: HCERTSTOREPROV;
    pCrlContext: PCCRL_CONTEXT;
    dwFlags: DWORD): BOOL; stdcall;

type
  PFN_CERT_STORE_PROV_DELETE_CRL = function(hStoreProv: HCERTSTOREPROV;
    pCrlContext: PCCRL_CONTEXT;
    dwFlags: DWORD): BOOL; stdcall;

type
  PFN_CERT_STORE_PROV_SET_CRL_PROPERTY = function(hStoreProv: HCERTSTOREPROV;
    pCrlContext: PCCRL_CONTEXT;
    dwPropId: DWORD;
    dwFlags: DWORD;
    pvData: PVOID): BOOL; stdcall;


type
  PFN_CERT_STORE_PROV_READ_CTL = function(hStoreProv: HCERTSTOREPROV;
    pStoreCtlContext: PCCTL_CONTEXT;
    dwFlags: DWORD;
    var ppProvCtlContext: PCCTL_CONTEXT
    ): BOOL; stdcall;


type
  PFN_CERT_STORE_PROV_WRITE_CTL = function(hStoreProv: HCERTSTOREPROV;
    pCtlContext: PCCTL_CONTEXT;
    dwFlags: DWORD): BOOL; stdcall;


type
  PFN_CERT_STORE_PROV_DELETE_CTL = function(hStoreProv: HCERTSTOREPROV;
    pCtlContext: PCCTL_CONTEXT;
    dwFlags: DWORD): BOOL; stdcall;


type
  PFN_CERT_STORE_PROV_SET_CTL_PROPERTY = function(hStoreProv: HCERTSTOREPROV;
    pCtlContext: PCCTL_CONTEXT;
    dwPropId: DWORD;
    dwFlags: DWORD;
    const pvData: PVOID
    ): BOOL; stdcall;

//+-------------------------------------------------------------------------
//  Duplicate a cert store handle
//--------------------------------------------------------------------------

function CertDuplicateStore(hCertStore: HCERTSTORE): HCERTSTORE; stdcall;

const CERT_STORE_SAVE_AS_STORE = 1;
const CERT_STORE_SAVE_AS_PKCS7 = 2;

const CERT_STORE_SAVE_TO_FILE = 1;
const CERT_STORE_SAVE_TO_MEMORY = 2;
const CERT_STORE_SAVE_TO_FILENAME_A = 3;
const CERT_STORE_SAVE_TO_FILENAME_W = 4;
const CERT_STORE_SAVE_TO_FILENAME = CERT_STORE_SAVE_TO_FILENAME_W;


function CertSaveStore(hCertStore: HCERTSTORE;
  dwEncodingType: DWORD;
  dwSaveAs: DWORD;
  dwSaveTo: DWORD;
  pvSaveToPara: PVOID;
  dwFlags: DWORD): BOOL; stdcall;


const CERT_CLOSE_STORE_FORCE_FLAG = $00000001;
const CERT_CLOSE_STORE_CHECK_FLAG = $00000002;


function CertCloseStore(hCertStore: HCERTSTORE; dwFlags: DWORD): BOOL; stdcall;

function CertGetSubjectCertificateFromStore(hCertStore: HCERTSTORE;
  dwCertEncodingType: DWORD;
  pCertId: PCERT_INFO // Only the Issuer and SerialNumber
  ): PCCERT_CONTEXT; stdcall; // fields are used


function CertEnumCertificatesInStore(hCertStore: HCERTSTORE;
  pPrevCertContext: PCCERT_CONTEXT
  ): PCCERT_CONTEXT; stdcall;

function CertFindCertificateInStore(hCertStore: HCERTSTORE;
  dwCertEncodingType: DWORD;
  dwFindFlags: DWORD;
  dwFindType: DWORD;
  const pvFindPara: PVOID;
  pPrevCertContext: PCCERT_CONTEXT
  ): PCCERT_CONTEXT; stdcall;


const CERT_COMPARE_SHIFT = 16;
const CERT_COMPARE_ANY = 0;
const CERT_COMPARE_SHA1_HASH = 1;
const CERT_COMPARE_NAME = 2;
const CERT_COMPARE_ATTR = 3;
const CERT_COMPARE_MD5_HASH = 4;
const CERT_COMPARE_PROPERTY = 5;
const CERT_COMPARE_PUBLIC_KEY = 6;
const CERT_COMPARE_HASH = CERT_COMPARE_SHA1_HASH;
const CERT_COMPARE_NAME_STR_A = 7;
const CERT_COMPARE_NAME_STR_W = 8;
const CERT_COMPARE_KEY_SPEC = 9;
const CERT_COMPARE_ENHKEY_USAGE = 10;
const CERT_COMPARE_CTL_USAGE = CERT_COMPARE_ENHKEY_USAGE;

const CERT_FIND_ANY = (CERT_COMPARE_ANY shl CERT_COMPARE_SHIFT);
const CERT_FIND_SHA1_HASH = (CERT_COMPARE_SHA1_HASH shl CERT_COMPARE_SHIFT);
const CERT_FIND_MD5_HASH = (CERT_COMPARE_MD5_HASH shl CERT_COMPARE_SHIFT);
const CERT_FIND_HASH = CERT_FIND_SHA1_HASH;
const CERT_FIND_PROPERTY = (CERT_COMPARE_PROPERTY shl CERT_COMPARE_SHIFT);
const CERT_FIND_PUBLIC_KEY = (CERT_COMPARE_PUBLIC_KEY shl CERT_COMPARE_SHIFT);

const CERT_FIND_SUBJECT_NAME = (CERT_COMPARE_NAME shl CERT_COMPARE_SHIFT or CERT_INFO_SUBJECT_FLAG);
const CERT_FIND_SUBJECT_ATTR = (CERT_COMPARE_ATTR shl CERT_COMPARE_SHIFT or CERT_INFO_SUBJECT_FLAG);
const CERT_FIND_ISSUER_NAME = (CERT_COMPARE_NAME shl CERT_COMPARE_SHIFT or CERT_INFO_ISSUER_FLAG);
const CERT_FIND_ISSUER_ATTR = (CERT_COMPARE_ATTR shl CERT_COMPARE_SHIFT or CERT_INFO_ISSUER_FLAG);
const CERT_FIND_SUBJECT_STR_A = (CERT_COMPARE_NAME_STR_A shl CERT_COMPARE_SHIFT or CERT_INFO_SUBJECT_FLAG);
const CERT_FIND_SUBJECT_STR_W = (CERT_COMPARE_NAME_STR_W shl CERT_COMPARE_SHIFT or CERT_INFO_SUBJECT_FLAG);
const CERT_FIND_SUBJECT_STR = CERT_FIND_SUBJECT_STR_W;
const CERT_FIND_ISSUER_STR_A = (CERT_COMPARE_NAME_STR_A shl CERT_COMPARE_SHIFT or CERT_INFO_ISSUER_FLAG);
const CERT_FIND_ISSUER_STR_W = (CERT_COMPARE_NAME_STR_W shl CERT_COMPARE_SHIFT or CERT_INFO_ISSUER_FLAG);
const CERT_FIND_ISSUER_STR = CERT_FIND_ISSUER_STR_W;
const CERT_FIND_KEY_SPEC = (CERT_COMPARE_KEY_SPEC shl CERT_COMPARE_SHIFT);
const CERT_FIND_ENHKEY_USAGE = (CERT_COMPARE_ENHKEY_USAGE shl CERT_COMPARE_SHIFT);
const CERT_FIND_CTL_USAGE = CERT_FIND_ENHKEY_USAGE;
const CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG = $1;
const CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG = $2;
const CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG = $4;
const CERT_FIND_NO_ENHKEY_USAGE_FLAG = $8;
const CERT_FIND_OPTIONAL_CTL_USAGE_FLAG = CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG;
const CERT_FIND_EXT_ONLY_CTL_USAGE_FLAG = CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG;
const CERT_FIND_PROP_ONLY_CTL_USAGE_FLAG = CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG;
const CERT_FIND_NO_CTL_USAGE_FLAG = CERT_FIND_NO_ENHKEY_USAGE_FLAG;

function CertGetIssuerCertificateFromStore(hCertStore: HCERTSTORE;
  pSubjectContext: PCCERT_CONTEXT;
  pPrevIssuerContext: PCCERT_CONTEXT; //OPTIONAL
  pdwFlags: PDWORD): PCCERT_CONTEXT; stdcall;


function CertVerifySubjectCertificateContext(pSubject: PCCERT_CONTEXT;
  pIssuer: PCCERT_CONTEXT; //OPTIONAL
  pdwFlags: PDWORD): BOOL; stdcall;


function CertDuplicateCertificateContext(pCertContext: PCCERT_CONTEXT): PCCERT_CONTEXT; stdcall;

function CertCreateCertificateContext(dwCertEncodingType: DWORD;
  pbCertEncoded: PBYTE;
  cbCertEncoded: DWORD): PCCERT_CONTEXT; stdcall;

function CertFreeCertificateContext(pCertContext: PCCERT_CONTEXT): BOOL; stdcall;

function CertSetCertificateContextProperty(pCertContext: PCCERT_CONTEXT;
  dwPropId: DWORD;
  dwFlags: DWORD;
  pvData: PVOID): BOOL; stdcall;

function CertGetCertificateContextProperty(pCertContext: PCCERT_CONTEXT;
  dwPropId: DWORD;
  pvData: PVOID;
  pcbData: PDWORD): BOOL; stdcall;

function CertEnumCertificateContextProperties(pCertContext: PCCERT_CONTEXT;
  dwPropId: DWORD): DWORD; stdcall;

function CertGetCRLFromStore(hCertStore: HCERTSTORE;
  pIssuerContext: PCCERT_CONTEXT; //OPTIONAL
  pPrevCrlContext: PCCRL_CONTEXT;
  pdwFlags: PDWORD): PCCRL_CONTEXT; stdcall;

function CertDuplicateCRLContext(pCrlContext: PCCRL_CONTEXT): PCCRL_CONTEXT; stdcall;

function CertCreateCRLContext(dwCertEncodingType: DWORD;
  pbCrlEncoded: PBYTE;
  cbCrlEncoded: DWORD): PCCRL_CONTEXT; stdcall;

function CertFreeCRLContext(pCrlContext: PCCRL_CONTEXT): BOOL; stdcall;

function CertSetCRLContextProperty(pCrlContext: PCCRL_CONTEXT;
  dwPropId: DWORD;
  dwFlags: DWORD;
  const pvData: PVOID): BOOL; stdcall;

function CertGetCRLContextProperty(pCrlContext: PCCRL_CONTEXT;
  dwPropId: DWORD;
  pvData: PVOID;
  pcbData: PDWORD): BOOL; stdcall;

function CertEnumCRLContextProperties(pCrlContext: PCCRL_CONTEXT;
  dwPropId: DWORD): DWORD; stdcall;

const CERT_STORE_ADD_NEW = 1;
const CERT_STORE_ADD_USE_EXISTING = 2;
const CERT_STORE_ADD_REPLACE_EXISTING = 3;
const CERT_STORE_ADD_ALWAYS = 4;

function CertAddEncodedCertificateToStore(hCertStore: HCERTSTORE;
  dwCertEncodingType: DWORD;
  const pbCertEncoded: PBYTE;
  cbCertEncoded: DWORD;
  dwAddDisposition: DWORD;
  var ppCertContext: PCCERT_CONTEXT): BOOL; stdcall;

function CertAddCertificateContextToStore(hCertStore: HCERTSTORE;
  pCertContext: PCCERT_CONTEXT;
  dwAddDisposition: DWORD;
  var ppStoreContext: PCCERT_CONTEXT //OPTIONAL
  ): BOOL; stdcall;


const CERT_STORE_CERTIFICATE_CONTEXT = 1;
const CERT_STORE_CRL_CONTEXT = 2;
const CERT_STORE_CTL_CONTEXT = 3;
const CERT_STORE_ALL_CONTEXT_FLAG = (not ULONG(0));
const CERT_STORE_CERTIFICATE_CONTEXT_FLAG = (1 shl CERT_STORE_CERTIFICATE_CONTEXT);
const CERT_STORE_CRL_CONTEXT_FLAG = (1 shl CERT_STORE_CRL_CONTEXT);
const CERT_STORE_CTL_CONTEXT_FLAG = (1 shl CERT_STORE_CTL_CONTEXT);


function CertAddSerializedElementToStore(hCertStore: HCERTSTORE;
  pbElement: PBYTE;
  cbElement: DWORD;
  dwAddDisposition: DWORD;
  dwFlags: DWORD;
  dwContextTypeFlags: DWORD;
  pdwContextType: PDWORD;
  var ppvContext: array of PVOID): BOOL; stdcall;

function CertDeleteCertificateFromStore(pCertContext: PCCERT_CONTEXT): BOOL; stdcall;

function CertAddEncodedCRLToStore(hCertStore: HCERTSTORE;
  dwCertEncodingType: DWORD;
  pbCrlEncoded: PBYTE;
  cbCrlEncoded: DWORD;
  dwAddDisposition: DWORD;
  var ppCrlContext: PCCRL_CONTEXT
  ): BOOL; stdcall;

function CertAddCRLContextToStore(hCertStore: HCERTSTORE;
  pCrlContext: PCCRL_CONTEXT;
  dwAddDisposition: DWORD;
  var ppStoreContext: PCCRL_CONTEXT
  ): BOOL; stdcall;

function CertDeleteCRLFromStore(pCrlContext: PCCRL_CONTEXT): BOOL; stdcall;

function CertSerializeCertificateStoreElement(pCertContext: PCCERT_CONTEXT;
  dwFlags: DWORD;
  pbElement: PBYTE;
  pcbElement: PDWORD): BOOL; stdcall;

function CertSerializeCRLStoreElement(pCrlContext: PCCRL_CONTEXT;
  dwFlags: DWORD;
  pbElement: PBYTE;
  pcbElement: PDWORD): BOOL; stdcall;

function CertDuplicateCTLContext(pCtlContext: PCCTL_CONTEXT): PCCTL_CONTEXT; stdcall;

function CertCreateCTLContext(dwMsgAndCertEncodingType: DWORD;
  const pbCtlEncoded: PBYTE;
  cbCtlEncoded: DWORD): PCCTL_CONTEXT; stdcall;

function CertFreeCTLContext(pCtlContext: PCCTL_CONTEXT): BOOL; stdcall;

function CertSetCTLContextProperty(pCtlContext: PCCTL_CONTEXT;
  dwPropId: DWORD;
  dwFlags: DWORD;
  const pvData: PVOID): BOOL; stdcall;

function CertGetCTLContextProperty(pCtlContext: PCCTL_CONTEXT;
  dwPropId: DWORD;
  pvData: PVOID;
  pcbData: PDWORD): BOOL; stdcall;

function CertEnumCTLContextProperties(pCtlContext: PCCTL_CONTEXT;
  dwPropId: DWORD): DWORD; stdcall;

function CertEnumCTLsInStore(hCertStore: HCERTSTORE;
  pPrevCtlContext: PCCTL_CONTEXT
  ): PCCTL_CONTEXT; stdcall;

function CertFindSubjectInCTL(dwEncodingType: DWORD;
  dwSubjectType: DWORD;
  pvSubject: PVOID;
  pCtlContext: PCCTL_CONTEXT;
  dwFlags: DWORD): PCTL_ENTRY; stdcall;
// Subject Types:
//  CTL_ANY_SUBJECT_TYPE, pvSubject points to following CTL_ANY_SUBJECT_INFO.
//  CTL_CERT_SUBJECT_TYPE, pvSubject points to CERT_CONTEXT.
const CTL_ANY_SUBJECT_TYPE = 1;
const CTL_CERT_SUBJECT_TYPE = 2;

type
  PCTL_ANY_SUBJECT_INFO = ^CTL_ANY_SUBJECT_INFO;
  CTL_ANY_SUBJECT_INFO = record
    SubjectAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    SubjectIdentifier: CRYPT_DATA_BLOB;
  end;

function CertFindCTLInStore(hCertStore: HCERTSTORE;
  dwMsgAndCertEncodingType: DWORD;
  dwFindFlags: DWORD;
  dwFindType: DWORD;
  const pvFindPara: PVOID;
  pPrevCtlContext: PCCTL_CONTEXT): PCCTL_CONTEXT; stdcall;

const CTL_FIND_ANY = 0;
const CTL_FIND_SHA1_HASH = 1;
const CTL_FIND_MD5_HASH = 2;
const CTL_FIND_USAGE = 3;
const CTL_FIND_SUBJECT = 4;

type
  PCTL_FIND_USAGE_PARA = ^CTL_FIND_USAGE_PARA;
  CTL_FIND_USAGE_PARA = record
    cbSize: DWORD;
    SubjectUsage: CTL_USAGE; // optional
    ListIdentifier: CRYPT_DATA_BLOB; // optional
    pSigner: PCERT_INFO; // optional
  end;

const CTL_FIND_NO_LIST_ID_CBDATA = $FFFFFFFF;
const CTL_FIND_NO_SIGNER_PTR = (PCERT_INFO($FFFFFFFF));

const CTL_FIND_SAME_USAGE_FLAG = $1;

type
  PCTL_FIND_SUBJECT_PARA = ^CTL_FIND_SUBJECT_PARA;
  CTL_FIND_SUBJECT_PARA = record
    cbSize: DWORD;
    pUsagePara: PCTL_FIND_USAGE_PARA; // optional
    dwSubjectType: DWORD;
    pvSubject: PVOID;
  end;

function CertAddEncodedCTLToStore(hCertStore: HCERTSTORE;
  dwMsgAndCertEncodingType: DWORD;
  const pbCtlEncoded: PBYTE;
  cbCtlEncoded: DWORD;
  dwAddDisposition: DWORD;
  var ppCtlContext: PCCTL_CONTEXT //OPTIONAL
  ): BOOL; stdcall;

function CertAddCTLContextToStore(hCertStore: HCERTSTORE;
  pCtlContext: PCCTL_CONTEXT;
  dwAddDisposition: DWORD;
  var ppStoreContext: PCCTL_CONTEXT
  ): BOOL; stdcall;

function CertSerializeCTLStoreElement(pCtlContext: PCCTL_CONTEXT;
  dwFlags: DWORD;
  pbElement: PBYTE;
  pcbElement: PDWORD): BOOL; stdcall;

function CertDeleteCTLFromStore(pCtlContext: PCCTL_CONTEXT): BOOL; stdcall;

function CertGetEnhancedKeyUsage(pCertContext: PCCERT_CONTEXT;
  dwFlags: DWORD;
  pUsage: PCERT_ENHKEY_USAGE;
  pcbUsage: PDWORD): BOOL; stdcall;

function CertSetEnhancedKeyUsage(pCertContext: PCCERT_CONTEXT;
  pUsage: PCERT_ENHKEY_USAGE
  ): BOOL; stdcall;

function CertAddEnhancedKeyUsageIdentifier(pCertContext: PCCERT_CONTEXT;
  pszUsageIdentifier: LPCSTR
  ): BOOL; stdcall;


function CertRemoveEnhancedKeyUsageIdentifier(pCertContext: PCCERT_CONTEXT;
  pszUsageIdentifier: LPCSTR
  ): BOOL; stdcall;


function CryptMsgGetAndVerifySigner(hCryptMsg: HCRYPTMSG;
  cSignerStore: DWORD;
  var rghSignerStore: HCERTSTORE;
  dwFlags: DWORD;
  var ppSigner: PCCERT_CONTEXT;
  pdwSignerIndex: PDWORD): BOOL; stdcall;

const CMSG_TRUSTED_SIGNER_FLAG = $1;
const CMSG_SIGNER_ONLY_FLAG = $2;
const CMSG_USE_SIGNER_INDEX_FLAG = $4;

function CryptMsgSignCTL(dwMsgEncodingType: DWORD;
  pbCtlContent: PBYTE;
  cbCtlContent: DWORD;
  pSignInfo: PCMSG_SIGNED_ENCODE_INFO;
  dwFlags: DWORD;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD): BOOL; stdcall;
//+-------------------------------------------------------------------------
//  Encode the CTL and create a signed message containing the encoded CTL.
//--------------------------------------------------------------------------
function CryptMsgEncodeAndSignCTL(dwMsgEncodingType: DWORD;
  pCtlInfo: PCTL_INFO;
  pSignInfo: PCMSG_SIGNED_ENCODE_INFO;
  dwFlags: DWORD;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD): BOOL; stdcall;

//+=========================================================================
//  Certificate Verify CTL Usage Data Structures and APIs
//==========================================================================
type
  PHCERTSTORE = ^HCERTSTORE;

type
  PCTL_VERIFY_USAGE_PARA = ^CTL_VERIFY_USAGE_PARA;
  CTL_VERIFY_USAGE_PARA = record
    cbSize: DWORD;
    ListIdentifier: CRYPT_DATA_BLOB; // OPTIONAL
    cCtlStore: DWORD;
    rghCtlStore: PHCERTSTORE; // OPTIONAL
    cSignerStore: DWORD;
    rghSignerStore: PHCERTSTORE; // OPTIONAL
  end;

type
  PCTL_VERIFY_USAGE_STATUS = ^CTL_VERIFY_USAGE_STATUS;
  CTL_VERIFY_USAGE_STATUS = record
    cbSize: DWORD;
    dwError: DWORD;
    dwFlags: DWORD;
    ppCtl: PPCCTL_CONTEXT; // IN OUT OPTIONAL
    dwCtlEntryIndex: DWORD;
    ppSigner: PPCCERT_CONTEXT; // IN OUT OPTIONAL
    dwSignerIndex: DWORD;
  end;

const CERT_VERIFY_INHIBIT_CTL_UPDATE_FLAG = $1;
const CERT_VERIFY_TRUSTED_SIGNERS_FLAG = $2;
const CERT_VERIFY_NO_TIME_CHECK_FLAG = $4;
const CERT_VERIFY_ALLOW_MORE_USAGE_FLAG = $8;

const CERT_VERIFY_UPDATED_CTL_FLAG = $1;

function CertVerifyCTLUsage(dwEncodingType: DWORD;
  dwSubjectType: DWORD;
  pvSubject: PVOID;
  pSubjectUsage: PCTL_USAGE;
  dwFlags: DWORD;
  pVerifyUsagePara: PCTL_VERIFY_USAGE_PARA;
  pVerifyUsageStatus: PCTL_VERIFY_USAGE_STATUS
  ): BOOL; stdcall;


type
  PCERT_REVOCATION_PARA = ^CERT_REVOCATION_PARA;
  CERT_REVOCATION_PARA = record
    cbSize: DWORD;
    pIssuerCert: PCCERT_CONTEXT;
    cCertStore: DWORD;
    rgCertStore: PHCERTSTORE;
  end;


type
  PCERT_REVOCATION_STATUS = ^CERT_REVOCATION_STATUS;
  CERT_REVOCATION_STATUS = record
    cbSize: DWORD;
    dwIndex: DWORD;
    dwError: DWORD;
    dwReason: DWORD;
  end;

function CertVerifyRevocation(dwEncodingType: DWORD;
  dwRevType: DWORD;
  cContext: DWORD;
  rgpvContext: array of PVOID;
  dwFlags: DWORD;
  pRevPara: PCERT_REVOCATION_PARA;
  pRevStatus: PCERT_REVOCATION_STATUS
  ): BOOL; stdcall;
//+-------------------------------------------------------------------------
//  Revocation types
//--------------------------------------------------------------------------
const CERT_CONTEXT_REVOCATION_TYPE = 1;
const CERT_VERIFY_REV_CHAIN_FLAG = $1;


function CertCompareIntegerBlob(pInt1: PCRYPT_INTEGER_BLOB;
  pInt2: PCRYPT_INTEGER_BLOB
  ): BOOL; stdcall;

function CertCompareCertificate(dwCertEncodingType: DWORD;
  pCertId1: PCERT_INFO;
  pCertId2: PCERT_INFO): BOOL; stdcall;

function CertCompareCertificateName(dwCertEncodingType: DWORD;
  pCertName1: PCERT_NAME_BLOB;
  pCertName2: PCERT_NAME_BLOB): BOOL; stdcall;

function CertIsRDNAttrsInCertificateName(dwCertEncodingType: DWORD;
  dwFlags: DWORD;
  pCertName: PCERT_NAME_BLOB;
  pRDN: PCERT_RDN): BOOL; stdcall;

const CERT_UNICODE_IS_RDN_ATTRS_FLAG = $1;


function CertComparePublicKeyInfo(dwCertEncodingType: DWORD;
  pPublicKey1: PCERT_PUBLIC_KEY_INFO;
  pPublicKey2: PCERT_PUBLIC_KEY_INFO
  ): BOOL; stdcall;

function CertGetPublicKeyLength(dwCertEncodingType: DWORD;
  pPublicKey: PCERT_PUBLIC_KEY_INFO
  ): DWORD; stdcall;

function CryptVerifyCertificateSignature(hCryptProv: HCRYPTPROV;
  dwCertEncodingType: DWORD;
  const pbEncoded: PBYTE;
  cbEncoded: DWORD;
  pPublicKey: PCERT_PUBLIC_KEY_INFO
  ): BOOL; stdcall;

function CryptHashToBeSigned(hCryptProv: HCRYPTPROV;
  dwCertEncodingType: DWORD;
  const pbEncoded: PBYTE;
  cbEncoded: DWORD;
  pbComputedHash: PBYTE;
  pcbComputedHash: PDWORD): BOOL; stdcall;

function CryptHashCertificate(hCryptProv: HCRYPTPROV;
  Algid: ALG_ID;
  dwFlags: DWORD;
  const pbEncoded: PBYTE;
  cbEncoded: DWORD;
  pbComputedHash: PBYTE;
  pcbComputedHash: PDWORD): BOOL; stdcall;

function CryptSignCertificate(hCryptProv: HCRYPTPROV;
  dwKeySpec: DWORD;
  dwCertEncodingType: DWORD;
  const pbEncodedToBeSigned: PBYTE;
  cbEncodedToBeSigned: DWORD;
  pSignatureAlgorithm: PCRYPT_ALGORITHM_IDENTIFIER;
  const pvHashAuxInfo: PVOID;
  pbSignature: PBYTE;
  pcbSignature: PDWORD): BOOL; stdcall;

function CryptSignAndEncodeCertificate(hCryptProv: HCRYPTPROV;
  dwKeySpec: DWORD;
  dwCertEncodingType: DWORD;
  const lpszStructType: LPCSTR; // "to be signed"
  pvStructInfo: PVOID;
  pSignatureAlgorithm: PCRYPT_ALGORITHM_IDENTIFIER;
  const pvHashAuxInfo: PVOID;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD): BOOL; stdcall;


function CertVerifyTimeValidity(pTimeToVerify: PFILETIME;
  pCertInfo: PCERT_INFO): LONG; stdcall;


function CertVerifyCRLTimeValidity(pTimeToVerify: PFILETIME;
  pCrlInfo: PCRL_INFO): LONG; stdcall;

function CertVerifyValidityNesting(pSubjectInfo: PCERT_INFO;
  pIssuerInfo: PCERT_INFO): BOOL; stdcall;

function CertVerifyCRLRevocation(dwCertEncodingType: DWORD;
  pCertId: PCERT_INFO; // Only the Issuer and SerialNumber
  cCrlInfo: DWORD; // fields are used
  rgpCrlInfo: array of PCRL_INFO): BOOL; stdcall;

function CertAlgIdToOID(dwAlgId: DWORD): LPCSTR; stdcall;

function CertOIDToAlgId(pszObjId: LPCSTR): DWORD; stdcall;

function CertFindExtension(pszObjId: LPCSTR;
  cExtensions: DWORD;
  rgExtensions: array of CERT_EXTENSION): PCERT_EXTENSION; stdcall;

function CertFindAttribute(pszObjId: LPCSTR;
  cAttr: DWORD;
  rgAttr: array of CRYPT_ATTRIBUTE): PCRYPT_ATTRIBUTE; stdcall;

function CertFindRDNAttr(pszObjId: LPCSTR;
  pName: PCERT_NAME_INFO): PCERT_RDN_ATTR; stdcall;

function CertGetIntendedKeyUsage(dwCertEncodingType: DWORD;
  pCertInfo: PCERT_INFO;
  pbKeyUsage: PBYTE;
  cbKeyUsage: DWORD): BOOL; stdcall;


function CryptExportPublicKeyInfo(hCryptProv: HCRYPTPROV;
  dwKeySpec: DWORD;
  dwCertEncodingType: DWORD;
  pInfo: PCERT_PUBLIC_KEY_INFO;
  pcbInfo: PDWORD): BOOL; stdcall;

const CRYPT_OID_EXPORT_PUBLIC_KEY_INFO_FUNC = 'CryptDllExportPublicKeyInfoEx';

function CryptExportPublicKeyInfoEx(hCryptProv: HCRYPTPROV;
  dwKeySpec: DWORD;
  dwCertEncodingType: DWORD;
  pszPublicKeyObjId: LPSTR;
  dwFlags: DWORD;
  pvAuxInfo: PVOID;
  pInfo: PCERT_PUBLIC_KEY_INFO;
  pcbInfo: PDWORD): BOOL; stdcall;

function CryptImportPublicKeyInfo(hCryptProv: HCRYPTPROV;
  dwCertEncodingType: DWORD;
  pInfo: PCERT_PUBLIC_KEY_INFO;
  phKey: PHCRYPTKEY): BOOL; stdcall;

const CRYPT_OID_IMPORT_PUBLIC_KEY_INFO_FUNC = 'CryptDllImportPublicKeyInfoEx';

function CryptImportPublicKeyInfoEx(hCryptProv: HCRYPTPROV;
  dwCertEncodingType: DWORD;
  pInfo: PCERT_PUBLIC_KEY_INFO;
  aiKeyAlg: ALG_ID;
  dwFlags: DWORD;
  pvAuxInfo: PVOID;
  phKey: PHCRYPTKEY
  ): BOOL; stdcall;

function CryptHashPublicKeyInfo(hCryptProv: HCRYPTPROV;
  Algid: ALG_ID;
  dwFlags: DWORD;
  dwCertEncodingType: DWORD;
  pInfo: PCERT_PUBLIC_KEY_INFO;
  pbComputedHash: PBYTE;
  pcbComputedHash: PDWORD): BOOL; stdcall;

function CertRDNValueToStrA(dwValueType: DWORD;
  pValue: PCERT_RDN_VALUE_BLOB;
  psz: LPSTR; //OPTIONAL
  csz: DWORD): DWORD; stdcall;

function CertRDNValueToStrW(dwValueType: DWORD;
  pValue: PCERT_RDN_VALUE_BLOB;
  psz: LPWSTR; //OPTIONAL
  csz: DWORD): DWORD; stdcall;

function CertRDNValueToStr(dwValueType: DWORD;
  pValue: PCERT_RDN_VALUE_BLOB;
  psz: LPAWSTR; //OPTIONAL
  csz: DWORD): DWORD; stdcall;


//+-------------------------------------------------------------------------
//--------------------------------------------------------------------------
function CertNameToStrA(dwCertEncodingType: DWORD;
  pName: PCERT_NAME_BLOB;
  dwStrType: DWORD;
  psz: LPSTR; //OPTIONAL
  csz: DWORD): DWORD; stdcall;
//+-------------------------------------------------------------------------
//--------------------------------------------------------------------------
function CertNameToStrW(dwCertEncodingType: DWORD;
  pName: PCERT_NAME_BLOB;
  dwStrType: DWORD;
  psz: LPWSTR; //OPTIONAL
  csz: DWORD): DWORD; stdcall;

function CertNameToStr(dwCertEncodingType: DWORD;
  pName: PCERT_NAME_BLOB;
  dwStrType: DWORD;
  psz: LPAWSTR; //OPTIONAL
  csz: DWORD): DWORD; stdcall;

//+-------------------------------------------------------------------------
//  Certificate name string types
//--------------------------------------------------------------------------
const CERT_SIMPLE_NAME_STR = 1;
const CERT_OID_NAME_STR = 2;
const CERT_X500_NAME_STR = 3;

//+-------------------------------------------------------------------------
//  Certificate name string type flags OR'ed with the above types
//--------------------------------------------------------------------------
const CERT_NAME_STR_SEMICOLON_FLAG = $40000000;
const CERT_NAME_STR_NO_PLUS_FLAG = $20000000;
const CERT_NAME_STR_NO_QUOTING_FLAG = $10000000;
const CERT_NAME_STR_CRLF_FLAG = $08000000;
const CERT_NAME_STR_COMMA_FLAG = $04000000;


//+-------------------------------------------------------------------------
//--------------------------------------------------------------------------
function CertStrToNameA(dwCertEncodingType: DWORD;
  pszX500: LPCSTR;
  dwStrType: DWORD;
  pvReserved: PVOID;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD;
  var ppszError: array of LPCSTR): BOOL; stdcall; {--max-- iniziato qui}
//+-------------------------------------------------------------------------
//--------------------------------------------------------------------------
function CertStrToNameW(dwCertEncodingType: DWORD;
  pszX500: LPCWSTR;
  dwStrType: DWORD;
  pvReserved: PVOID;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD;
  var ppszError: array of LPWSTR): BOOL; stdcall;

function CertStrToName(dwCertEncodingType: DWORD;
  pszX500: LPAWSTR;
  dwStrType: DWORD;
  pvReserved: PVOID;
  pbEncoded: PBYTE;
  pcbEncoded: PDWORD;
  var ppszError: array of LPAWSTR): BOOL; stdcall;


type
  PFN_CRYPT_GET_SIGNER_CERTIFICATE = function(pvGetArg: PVOID;
    dwCertEncodingType: DWORD;
    pSignerId: PCERT_INFO; // Only the Issuer and SerialNumber
    hMsgCertStore: HCERTSTORE // fields have been updated
    ): PCCERT_CONTEXT; stdcall;


type
  PCRYPT_SIGN_MESSAGE_PARA = ^CRYPT_SIGN_MESSAGE_PARA;
  CRYPT_SIGN_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgEncodingType: DWORD;
    pSigningCert: PCCERT_CONTEXT;
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvHashAuxInfo: PVOID;
    cMsgCert: DWORD;
    rgpMsgCert: PPCCERT_CONTEXT; // pointer to array of PCCERT_CONTEXT
    cMsgCrl: DWORD;
    rgpMsgCrl: PPCCRL_CONTEXT; // pointer to array of PCCERT_CO
    cAuthAttr: DWORD;
    rgAuthAttr: PCRYPT_ATTRIBUTE;
    cUnauthAttr: DWORD;
    rgUnauthAttr: PCRYPT_ATTRIBUTE;
    dwFlags: DWORD;
    dwInnerContentType: DWORD;
  end;
const CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG = $1;


type
  PCRYPT_VERIFY_MESSAGE_PARA = ^CRYPT_VERIFY_MESSAGE_PARA;
  CRYPT_VERIFY_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgAndCertEncodingType: DWORD;
    hCryptProv: HCRYPTPROV;
    pfnGetSignerCertificate: PFN_CRYPT_GET_SIGNER_CERTIFICATE;
    pvGetArg: PVOID;
  end;

type
  PCRYPT_ENCRYPT_MESSAGE_PARA = ^CRYPT_ENCRYPT_MESSAGE_PARA;
  CRYPT_ENCRYPT_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgEncodingType: DWORD;
    hCryptProv: HCRYPTPROV;
    ContentEncryptionAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvEncryptionAuxInfo: PVOID;
    dwFlags: DWORD;
    dwInnerContentType: DWORD;
  end;

type
  PCRYPT_DECRYPT_MESSAGE_PARA = ^CRYPT_DECRYPT_MESSAGE_PARA;
  CRYPT_DECRYPT_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgAndCertEncodingType: DWORD;
    cCertStore: DWORD;
    rghCertStore: PHCERTSTORE;
  end;

type
  PCRYPT_HASH_MESSAGE_PARA = ^CRYPT_HASH_MESSAGE_PARA;
  CRYPT_HASH_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgEncodingType: DWORD;
    hCryptProv: HCRYPTPROV;
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvHashAuxInfo: PVOID;
  end;

type
  PCRYPT_KEY_SIGN_MESSAGE_PARA = ^CRYPT_KEY_SIGN_MESSAGE_PARA;
  CRYPT_KEY_SIGN_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgAndCertEncodingType: DWORD;
    hCryptProv: HCRYPTPROV;
    dwKeySpec: DWORD;
    HashAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
    pvHashAuxInfo: PVOID;
    PubKeyAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
  end;

type
  PCRYPT_KEY_VERIFY_MESSAGE_PARA = ^CRYPT_KEY_VERIFY_MESSAGE_PARA;
  CRYPT_KEY_VERIFY_MESSAGE_PARA = record
    cbSize: DWORD;
    dwMsgEncodingType: DWORD;
    hCryptProv: HCRYPTPROV;
  end;


function CryptSignMessage(pSignPara: PCRYPT_SIGN_MESSAGE_PARA;
  fDetachedSignature: BOOL;
  cToBeSigned: DWORD;
  const rgpbToBeSigned: array of PBYTE;
  rgcbToBeSigned: array of DWORD;
  pbSignedBlob: PBYTE;
  pcbSignedBlob: PDWORD): BOOL; stdcall;

function CryptVerifyMessageSignature(pVerifyPara: PCRYPT_VERIFY_MESSAGE_PARA;
  dwSignerIndex: DWORD;
  const pbSignedBlob: PBYTE;
  cbSignedBlob: DWORD;
  pbDecoded: PBYTE;
  pcbDecoded: DWORD;
  ppSignerCert: PCCERT_CONTEXT
  ): BOOL; stdcall;

function CryptGetMessageSignerCount(dwMsgEncodingType: DWORD;
  const pbSignedBlob: PBYTE;
  cbSignedBlob: DWORD): LONG; stdcall;

function CryptGetMessageCertificates(dwMsgAndCertEncodingType: DWORD;
  hCryptProv: HCRYPTPROV; // passed to CertOpenStore
  dwFlags: DWORD; // passed to CertOpenStore
  const pbSignedBlob: PBYTE;
  cbSignedBlob: DWORD): HCERTSTORE; stdcall;

function CryptVerifyDetachedMessageSignature(pVerifyPara: PCRYPT_VERIFY_MESSAGE_PARA;
  dwSignerIndex: DWORD;
  const pbDetachedSignBlob: PBYTE;
  cbDetachedSignBlob: DWORD;
  cToBeSigned: DWORD;
  const rgpbToBeSigned: array of PBYTE;
  rgcbToBeSigned: array of DWORD;
  ppSignerCert: PPCCERT_CONTEXT): BOOL; stdcall;

function CryptEncryptMessage(pEncryptPara: PCRYPT_ENCRYPT_MESSAGE_PARA;
  cRecipientCert: DWORD;
  rgpRecipientCert: array of PCCERT_CONTEXT;
  const pbToBeEncrypted: PBYTE;
  cbToBeEncrypted: DWORD;
  pbEncryptedBlob: PBYTE;
  pcbEncryptedBlob: PDWORD): BOOL; stdcall;

function CryptDecryptMessage(pDecryptPara: PCRYPT_DECRYPT_MESSAGE_PARA;
  const pbEncryptedBlob: PBYTE;
  cbEncryptedBlob: DWORD;
  pbDecrypted: PBYTE;
  pcbDecrypted: PDWORD;
  ppXchgCert: PPCCERT_CONTEXT): BOOL; stdcall;

function CryptSignAndEncryptMessage(pSignPara: PCRYPT_SIGN_MESSAGE_PARA;
  pEncryptPara: PCRYPT_ENCRYPT_MESSAGE_PARA;
  cRecipientCert: DWORD;
  rgpRecipientCert: array of PCCERT_CONTEXT;
  const pbToBeSignedAndEncrypted: PBYTE;
  cbToBeSignedAndEncrypted: DWORD;
  pbSignedAndEncryptedBlob: PBYTE;
  pcbSignedAndEncryptedBlob: PDWORD
  ): BOOL; stdcall;

function CryptDecryptAndVerifyMessageSignature(pDecryptPara: PCRYPT_DECRYPT_MESSAGE_PARA;
  pVerifyPara: PCRYPT_VERIFY_MESSAGE_PARA;
  dwSignerIndex: DWORD;
  const pbEncryptedBlob: PBYTE;
  cbEncryptedBlob: DWORD;
  pbDecrypted: PBYTE;
  pcbDecrypted: PDWORD;
  var ppXchgCert: array of PCCERT_CONTEXT;
  var ppSignerCert: array of PCCERT_CONTEXT
  ): BOOL; stdcall;

function CryptDecodeMessage(dwMsgTypeFlags: DWORD;
  pDecryptPara: PCRYPT_DECRYPT_MESSAGE_PARA;
  pVerifyPara: PCRYPT_VERIFY_MESSAGE_PARA;
  dwSignerIndex: DWORD;
  const pbEncodedBlob: PBYTE;
  cbEncodedBlob: DWORD;
  dwPrevInnerContentType: DWORD;
  pdwMsgType: PDWORD;
  pdwInnerContentType: PDWORD;
  pbDecoded: PBYTE;
  pcbDecoded: PDWORD;
  var ppXchgCert: array of PCCERT_CONTEXT;
  var ppSignerCert: array of PCCERT_CONTEXT
  ): BOOL; stdcall;

function CryptHashMessage(pHashPara: PCRYPT_HASH_MESSAGE_PARA;
  fDetachedHash: BOOL;
  cToBeHashed: DWORD;
  const rgpbToBeHashed: array of PBYTE;
  rgcbToBeHashed: array of DWORD;
  pbHashedBlob: PBYTE;
  pcbHashedBlob: PDWORD;
  pbComputedHash: PBYTE;
  pcbComputedHash: PDWORD): BOOL; stdcall;

function CryptVerifyMessageHash(pHashPara: PCRYPT_HASH_MESSAGE_PARA;
  pbHashedBlob: PBYTE;
  cbHashedBlob: DWORD;
  pbToBeHashed: PBYTE;
  pcbToBeHashed: PDWORD;
  pbComputedHash: PBYTE;
  pcbComputedHash: PDWORD): BOOL; stdcall;

function CryptVerifyDetachedMessageHash(pHashPara: PCRYPT_HASH_MESSAGE_PARA;
  pbDetachedHashBlob: PBYTE;
  cbDetachedHashBlob: DWORD;
  cToBeHashed: DWORD;
  rgpbToBeHashed: array of PBYTE;
  rgcbToBeHashed: array of DWORD;
  pbComputedHash: PBYTE;
  pcbComputedHash: PDWORD): BOOL; stdcall;

function CryptSignMessageWithKey(pSignPara: PCRYPT_KEY_SIGN_MESSAGE_PARA;
  const pbToBeSigned: PBYTE;
  cbToBeSigned: DWORD;
  pbSignedBlob: PBYTE;
  pcbSignedBlob: PDWORD): BOOL; stdcall;

function CryptVerifyMessageSignatureWithKey(pVerifyPara: PCRYPT_KEY_VERIFY_MESSAGE_PARA;
  pPublicKeyInfo: PCERT_PUBLIC_KEY_INFO;
  const pbSignedBlob: PBYTE;
  cbSignedBlob: DWORD;
  pbDecoded: PBYTE;
  pcbDecoded: PDWORD): BOOL; stdcall;


function CertOpenSystemStoreA(hProv: HCRYPTPROV;
  szSubsystemProtocol: LPCSTR): HCERTSTORE; stdcall;

function CertOpenSystemStoreW(hProv: HCRYPTPROV;
  szSubsystemProtocol: LPCWSTR): HCERTSTORE; stdcall;

function CertOpenSystemStore(hProv: HCRYPTPROV;
  szSubsystemProtocol: LPAWSTR): HCERTSTORE; stdcall;

function CertAddEncodedCertificateToSystemStoreA(szCertStoreName: LPCSTR;
  const pbCertEncoded: PBYTE;
  cbCertEncoded: DWORD): BOOL; stdcall;

function CertAddEncodedCertificateToSystemStoreW(szCertStoreName: LPCWSTR;
  const pbCertEncoded: PBYTE;
  cbCertEncoded: DWORD): BOOL; stdcall;

function CertAddEncodedCertificateToSystemStore(szCertStoreName: LPAWSTR;
  const pbCertEncoded: PBYTE;
  cbCertEncoded: DWORD): BOOL; stdcall;


type
  PCERT_CHAIN = ^CERT_CHAIN;
  CERT_CHAIN = record
    cCerts: DWORD; // number of certs in chain
    certs: PCERT_BLOB; // pointer to array of cert chain blobs representing the certs
    keyLocatorInfo: CRYPT_KEY_PROV_INFO; // key locator for cert
  end;


// WINCRYPT32API    This is not exported by crypt32, it is exported by softpub
function FindCertsByIssuer(pCertChains: PCERT_CHAIN;
  pcbCertChains: PDWORD;
  pcCertChains: PDWORD; // count of certificates chains returned
  pbEncodedIssuerName: PBYTE; // DER encoded issuer name
  cbEncodedIssuerName: DWORD; // count in bytes of encoded issuer name
  pwszPurpose: LPCWSTR; // "ClientAuth" or "CodeSigning"
  dwKeySpec: DWORD // only return signers supporting this keyspec
  ): HRESULT; stdcall;

//////////////////////////// VERSION 2 ////////////////////////////////////////////////////////////////////

implementation

{Macro inplementation}

function GET_ALG_CLASS(x: integer): integer;
begin
  Result := (x and (7 shl 13));
end;

function GET_ALG_TYPE(x: integer): integer;
begin
  Result := (x and (15 shl 9));
end;

function GET_ALG_SID(x: integer): integer;
begin
  Result := (x and (511));
end;

function RCRYPT_SUCCEEDED(rt: BOOL): BOOL;
begin
  Result := rt = CRYPT_SUCCEED;
end;

function RCRYPT_FAILED(rt: BOOL): BOOL;
begin
  Result := rt = CRYPT_FAILED;
end;

function GET_CERT_UNICODE_RDN_ERR_INDEX(X: integer): integer;
begin
  Result := ((X shr CERT_UNICODE_RDN_ERR_INDEX_SHIFT) and CERT_UNICODE_RDN_ERR_INDEX_MASK);
end;

function GET_CERT_UNICODE_ATTR_ERR_INDEX(X: integer): integer;
begin
  Result := ((X shr CERT_UNICODE_ATTR_ERR_INDEX_SHIFT) and CERT_UNICODE_ATTR_ERR_INDEX_MASK);
end;

function GET_CERT_UNICODE_VALUE_ERR_INDEX(X: integer): integer;
begin
  Result := (X and CERT_UNICODE_VALUE_ERR_INDEX_MASK);
end;

function GET_CERT_ALT_NAME_ENTRY_ERR_INDEX(X: DWORD): DWORD;
begin
  Result := ((X shr CERT_ALT_NAME_ENTRY_ERR_INDEX_SHIFT) and CERT_ALT_NAME_ENTRY_ERR_INDEX_MASK);
end;

function GET_CERT_ALT_NAME_VALUE_ERR_INDEX(X: DWORD): DWORD;
begin
  Result := (X and CERT_ALT_NAME_VALUE_ERR_INDEX_MASK);
end;

function GET_CRL_DIST_POINT_ERR_INDEX(X: DWORD): DWORD;
begin
  Result := ((X shr CRL_DIST_POINT_ERR_INDEX_SHIFT) and CRL_DIST_POINT_ERR_INDEX_MASK);
end;

function IS_CRL_DIST_POINT_ERR_CRL_ISSUER(X: DWORD): BOOL;
begin
  Result := (0 <> (X and CRL_DIST_POINT_ERR_CRL_ISSUER_BIT));
end;
///////////////////////////////////////version 2 /////////////////////////

function IS_CERT_RDN_CHAR_STRING(X: DWORD): BOOL;
begin
  Result := BOOL(X >= CERT_RDN_NUMERIC_STRING);
end;

function GET_CERT_ENCODING_TYPE(X: DWORD): DWORD;
begin
  Result := (X and CERT_ENCODING_TYPE_MASK);
end;

function GET_CMSG_ENCODING_TYPE(X: DWORD): DWORD;
begin
  Result := (X and CMSG_ENCODING_TYPE_MASK);
end;

function IS_CERT_HASH_PROP_ID(X: DWORD): BOOL;
begin
  if (X = CERT_SHA1_HASH_PROP_ID) or (X = CERT_MD5_HASH_PROP_ID) then
    Result := True
  else
    Result := False;
end;
{end Macro}

function CryptAcquireContextA; external ADVAPI32 name 'CryptAcquireContextA';
{$IFDEF UNICODE}
function CryptAcquireContext; external ADVAPI32 name 'CryptAcquireContextW';
{$ELSE}
function CryptAcquireContext; external ADVAPI32 name 'CryptAcquireContextA';
{$ENDIF}
function CryptAcquireContextW; external ADVAPI32 name 'CryptAcquireContextW';
function CryptReleaseContext; external ADVAPI32 name 'CryptReleaseContext';
function CryptGenKey; external ADVAPI32 name 'CryptGenKey';
function CryptDeriveKey; external ADVAPI32 name 'CryptDeriveKey';
function CryptDestroyKey; external ADVAPI32 name 'CryptDestroyKey';
function CryptSetKeyParam; external ADVAPI32 name 'CryptSetKeyParam';
function CryptGetKeyParam; external ADVAPI32 name 'CryptGetKeyParam';
function CryptSetHashParam; external ADVAPI32 name 'CryptSetHashParam';
function CryptGetHashParam; external ADVAPI32 name 'CryptGetHashParam';
function CryptSetProvParam; external ADVAPI32 name 'CryptSetProvParam';
function CryptGetProvParam; external ADVAPI32 name 'CryptGetProvParam';
function CryptGenRandom; external ADVAPI32 name 'CryptGenRandom';
function CryptGetUserKey; external ADVAPI32 name 'CryptGetUserKey';
function CryptExportKey; external ADVAPI32 name 'CryptExportKey';
function CryptImportKey; external ADVAPI32 name 'CryptImportKey';
function CryptEncrypt; external ADVAPI32 name 'CryptEncrypt';
function CryptDecrypt; external ADVAPI32 name 'CryptDecrypt';
function CryptCreateHash; external ADVAPI32 name 'CryptCreateHash';
function CryptHashData; external ADVAPI32 name 'CryptHashData';
function CryptHashSessionKey; external ADVAPI32 name 'CryptHashSessionKey';
function CryptDestroyHash; external ADVAPI32 name 'CryptDestroyHash';
function CryptSignHashA; external ADVAPI32 name 'CryptSignHashA';
function CryptSignHashW; external ADVAPI32 name 'CryptSignHashW';
function CryptSignHashU; external CRYPT32 name 'CryptSignHashU';
{$IFDEF UNICODE}
function CryptSignHash; external ADVAPI32 name 'CryptSignHashW';
{$ELSE}
function CryptSignHash; external ADVAPI32 name 'CryptSignHashA';
{$ENDIF}
function CryptVerifySignatureA; external ADVAPI32 name 'CryptVerifySignatureA';
function CryptVerifySignatureW; external ADVAPI32 name 'CryptVerifySignatureW';
{$IFDEF UNICODE}
function CryptVerifySignature; external ADVAPI32 name 'CryptVerifySignatureW';
{$ELSE}
function CryptVerifySignature; external ADVAPI32 name 'CryptVerifySignatureA';
{$ENDIF}
function CryptSetProviderW; external ADVAPI32 name 'CryptSetProviderW';
function CryptSetProviderA; external ADVAPI32 name 'CryptSetProviderA';
function CryptSetProviderU; external CRYPT32 name 'CryptSetProviderU';
{$IFDEF UNICODE}
function CryptSetProvider; external ADVAPI32 name 'CryptSetProviderW';
{$ELSE}
function CryptSetProvider; external ADVAPI32 name 'CryptSetProviderA';
{$ENDIF}

{$IFDEF NT5}
function CryptSetProviderExA; external ADVAPI32NT5 name 'CryptSetProviderExA'; //nt5 advapi32
function CryptSetProviderExW; external ADVAPI32NT5 name 'CryptSetProviderExW';
{$IFDEF UNICODE}
function CryptSetProviderEx; external ADVAPI32NT5 name 'CryptSetProviderExW';
{$ELSE}
function CryptSetProviderEx; external ADVAPI32NT5 name 'CryptSetProviderExA';
{$ENDIF} // !UNICODE

function CryptGetDefaultProviderA; external ADVAPI32NT5 name 'CryptGetDefaultProviderA'; //nt5 advapi32
function CryptGetDefaultProviderW; external ADVAPI32NT5 name 'CryptGetDefaultProviderW';
{$IFDEF UNICODE}
function CryptGetDefaultProvider; external ADVAPI32NT5 name 'CryptGetDefaultProviderW';
{$ELSE}
function CryptGetDefaultProvider; external ADVAPI32NT5 name 'CryptGetDefaultProviderA';
{$ENDIF} // !UNICODE

function CryptEnumProviderTypesA; external ADVAPI32NT5 name 'CryptEnumProviderTypesA'; //nt5 advapi32
function CryptEnumProviderTypesW; external ADVAPI32NT5 name 'CryptEnumProviderTypesW';
{$IFDEF UNICODE}
function CryptEnumProviderTypes; external ADVAPI32NT5 name 'CryptEnumProviderTypesW';
{$ELSE}
function CryptEnumProviderTypes; external ADVAPI32NT5 name 'CryptEnumProviderTypesA';
{$ENDIF} // !UNICODE

function CryptEnumProvidersA; external ADVAPI32NT5 name 'CryptEnumProvidersA'; //nt5 advapi32
function CryptEnumProvidersW; external ADVAPI32NT5 name 'CryptEnumProvidersW';

{$IFDEF UNICODE}
function CryptEnumProviders; external ADVAPI32NT5 name 'CryptEnumProvidersW';
{$ELSE}
function CryptEnumProviders; external ADVAPI32NT5 name 'CryptEnumProvidersA';
{$ENDIF} // !UNICODE
function CryptContextAddRef; external ADVAPI32NT5 name 'CryptContextAddRef'; //nt5 advapi32
function CryptDuplicateKey; external ADVAPI32NT5 name 'CryptDuplicateKey'; //nt5 advapi32
function CryptDuplicateHash; external ADVAPI32NT5 name 'CryptDuplicateHash'; //nt5 advapi32
{$ENDIF NT5}

function CryptEnumProvidersU; external CRYPT32 name 'CryptEnumProvidersU';
function CryptFormatObject; external CRYPT32 name 'CryptFormatObject';
function CryptEncodeObject; external CRYPT32 name 'CryptEncodeObject';
function CryptDecodeObject; external CRYPT32 name 'CryptDecodeObject';
function CryptInstallOIDFunctionAddress; external CRYPT32 name 'CryptInstallOIDFunctionAddress';
function CryptInitOIDFunctionSet; external CRYPT32 name 'CryptInitOIDFunctionSet';
function CryptGetOIDFunctionAddress; external CRYPT32 name 'CryptGetOIDFunctionAddress';
function CryptGetDefaultOIDDllList; external CRYPT32 name 'CryptGetDefaultOIDDllList';
function CryptGetDefaultOIDFunctionAddress; external CRYPT32 name 'CryptGetDefaultOIDFunctionAddress';
function CryptFreeOIDFunctionAddress; external CRYPT32 name 'CryptFreeOIDFunctionAddress';
function CryptRegisterOIDFunction; external CRYPT32 name 'CryptRegisterOIDFunction';
function CryptUnregisterOIDFunction; external CRYPT32 name 'CryptUnregisterOIDFunction';
function CryptRegisterDefaultOIDFunction; external CRYPT32 name 'CryptRegisterDefaultOIDFunction';
function CryptUnregisterDefaultOIDFunction; external CRYPT32 name 'CryptUnregisterDefaultOIDFunction';
function CryptSetOIDFunctionValue; external CRYPT32 name 'CryptSetOIDFunctionValue';
function CryptGetOIDFunctionValue; external CRYPT32 name 'CryptGetOIDFunctionValue';
function CryptEnumOIDFunction; external CRYPT32 name 'CryptEnumOIDFunction';
function CryptFindOIDInfo; external CRYPT32 name 'CryptFindOIDInfo';

function CryptRegisterOIDInfo; external CRYPT32 name 'CryptRegisterOIDInfo';
function CryptUnregisterOIDInfo; external CRYPT32 name 'CryptUnregisterOIDInfo';
function CryptMsgOpenToEncode; external CRYPT32 name 'CryptMsgOpenToEncode';
function CryptMsgCalculateEncodedLength; external CRYPT32 name 'CryptMsgCalculateEncodedLength';
function CryptMsgOpenToDecode; external CRYPT32 name 'CryptMsgOpenToDecode';
function CryptMsgClose; external CRYPT32 name 'CryptMsgClose';
function CryptMsgUpdate; external CRYPT32 name 'CryptMsgUpdate';
function CryptMsgControl; external CRYPT32 name 'CryptMsgControl';
function CryptMsgVerifyCountersignatureEncoded; external CRYPT32 name 'CryptMsgVerifyCountersignatureEncoded';
function CryptMsgCountersign; external CRYPT32 name 'CryptMsgCountersign';
function CryptMsgCountersignEncoded; external CRYPT32 name 'CryptMsgCountersignEncoded';
function CryptMsgGetParam; external CRYPT32 name 'CryptMsgGetParam';
function CertOpenStore; external CRYPT32 name 'CertOpenStore';
function CertDuplicateStore; external CRYPT32 name 'CertDuplicateStore';
function CertSaveStore; external CRYPT32 name 'CertSaveStore';
function CertCloseStore; external CRYPT32 name 'CertCloseStore';
function CertGetSubjectCertificateFromStore; external CRYPT32 name 'CertGetSubjectCertificateFromStore';
function CertEnumCertificatesInStore; external CRYPT32 name 'CertEnumCertificatesInStore';
function CertFindCertificateInStore; external CRYPT32 name 'CertFindCertificateInStore';
function CertGetIssuerCertificateFromStore; external CRYPT32 name 'CertGetIssuerCertificateFromStore';
function CertVerifySubjectCertificateContext; external CRYPT32 name 'CertVerifySubjectCertificateContext';
function CertDuplicateCertificateContext; external CRYPT32 name 'CertDuplicateCertificateContext';
function CertCreateCertificateContext; external CRYPT32 name 'CertCreateCertificateContext';
function CertFreeCertificateContext; external CRYPT32 name 'CertFreeCertificateContext';
function CertSetCertificateContextProperty; external CRYPT32 name 'CertSetCertificateContextProperty';
function CertGetCertificateContextProperty; external CRYPT32 name 'CertGetCertificateContextProperty';
function CertEnumCertificateContextProperties; external CRYPT32 name 'CertEnumCertificateContextProperties';
function CertGetCRLFromStore; external CRYPT32 name 'CertGetCRLFromStore';
function CertDuplicateCRLContext; external CRYPT32 name 'CertDuplicateCRLContext';
function CertCreateCRLContext; external CRYPT32 name 'CertCreateCRLContext';
function CertFreeCRLContext; external CRYPT32 name 'CertFreeCRLContext';
function CertSetCRLContextProperty; external CRYPT32 name 'CertSetCRLContextProperty';
function CertGetCRLContextProperty; external CRYPT32 name 'CertGetCRLContextProperty';
function CertEnumCRLContextProperties; external CRYPT32 name 'CertEnumCRLContextProperties';
function CertAddEncodedCertificateToStore; external CRYPT32 name 'CertAddEncodedCertificateToStore';
function CertAddCertificateContextToStore; external CRYPT32 name 'CertAddCertificateContextToStore';
function CertAddSerializedElementToStore; external CRYPT32 name 'CertAddSerializedElementToStore';
function CertDeleteCertificateFromStore; external CRYPT32 name 'CertDeleteCertificateFromStore';
function CertAddEncodedCRLToStore; external CRYPT32 name 'CertAddEncodedCRLToStore';
function CertAddCRLContextToStore; external CRYPT32 name 'CertAddCRLContextToStore';
function CertDeleteCRLFromStore; external CRYPT32 name 'CertDeleteCRLFromStore';
function CertSerializeCertificateStoreElement; external CRYPT32 name 'CertSerializeCertificateStoreElement';
function CertSerializeCRLStoreElement; external CRYPT32 name 'CertSerializeCRLStoreElement';
function CertDuplicateCTLContext; external CRYPT32 name 'CertDuplicateCTLContext';
function CertCreateCTLContext; external CRYPT32 name 'CertCreateCTLContext';
function CertFreeCTLContext; external CRYPT32 name 'CertFreeCTLContext';
function CertSetCTLContextProperty; external CRYPT32 name 'CertSetCTLContextProperty';
function CertGetCTLContextProperty; external CRYPT32 name 'CertGetCTLContextProperty';
function CertEnumCTLContextProperties; external CRYPT32 name 'CertEnumCTLContextProperties';
function CertEnumCTLsInStore; external CRYPT32 name 'CertEnumCTLsInStore';
function CertFindSubjectInCTL; external CRYPT32 name 'CertFindSubjectInCTL';
function CertFindCTLInStore; external CRYPT32 name 'CertFindCTLInStore';
function CertAddEncodedCTLToStore; external CRYPT32 name 'CertAddEncodedCTLToStore';
function CertAddCTLContextToStore; external CRYPT32 name 'CertAddCTLContextToStore';
function CertSerializeCTLStoreElement; external CRYPT32 name 'CertSerializeCTLStoreElement';
function CertDeleteCTLFromStore; external CRYPT32 name 'CertDeleteCTLFromStore';
function CertGetEnhancedKeyUsage; external CRYPT32 name 'CertGetEnhancedKeyUsage';
function CertSetEnhancedKeyUsage; external CRYPT32 name 'CertSetEnhancedKeyUsage';
function CertAddEnhancedKeyUsageIdentifier; external CRYPT32 name 'CertAddEnhancedKeyUsageIdentifier';
function CertRemoveEnhancedKeyUsageIdentifier; external CRYPT32 name 'CertRemoveEnhancedKeyUsageIdentifier';
function CryptMsgGetAndVerifySigner; external CRYPT32 name 'CryptMsgGetAndVerifySigner';
function CryptMsgSignCTL; external CRYPT32 name 'CryptMsgSignCTL';
function CryptMsgEncodeAndSignCTL; external CRYPT32 name 'CryptMsgEncodeAndSignCTL';
function CertVerifyCTLUsage; external CRYPT32 name 'CertVerifyCTLUsage';
function CertVerifyRevocation; external CRYPT32 name 'CertVerifyRevocation';
function CertCompareIntegerBlob; external CRYPT32 name 'CertCompareIntegerBlob';
function CertCompareCertificate; external CRYPT32 name 'CertCompareCertificate';
function CertCompareCertificateName; external CRYPT32 name 'CertCompareCertificateName';
function CertIsRDNAttrsInCertificateName; external CRYPT32 name 'CertIsRDNAttrsInCertificateName';
function CertComparePublicKeyInfo; external CRYPT32 name 'CertComparePublicKeyInfo';
function CertGetPublicKeyLength; external CRYPT32 name 'CertGetPublicKeyLength';
function CryptVerifyCertificateSignature; external CRYPT32 name 'CryptVerifyCertificateSignature';
function CryptHashToBeSigned; external CRYPT32 name 'CryptHashToBeSigned';
function CryptHashCertificate; external CRYPT32 name 'CryptHashCertificate';
function CryptSignCertificate; external CRYPT32 name 'CryptSignCertificate';
function CryptSignAndEncodeCertificate; external CRYPT32 name 'CryptSignAndEncodeCertificate';
function CertVerifyTimeValidity; external CRYPT32 name 'CertVerifyTimeValidity';
function CertVerifyCRLTimeValidity; external CRYPT32 name 'CertVerifyCRLTimeValidity';
function CertVerifyValidityNesting; external CRYPT32 name 'CertVerifyValidityNesting';
function CertVerifyCRLRevocation; external CRYPT32 name 'CertVerifyCRLRevocation';
function CertAlgIdToOID; external CRYPT32 name 'CertAlgIdToOID';
function CertOIDToAlgId; external CRYPT32 name 'CertOIDToAlgId';
function CertFindExtension; external CRYPT32 name 'CertFindExtension';
function CertFindAttribute; external CRYPT32 name 'CertFindAttribute';
function CertFindRDNAttr; external CRYPT32 name 'CertFindRDNAttr';
function CertGetIntendedKeyUsage; external CRYPT32 name 'CertGetIntendedKeyUsage';
function CryptExportPublicKeyInfo; external CRYPT32 name 'CryptExportPublicKeyInfo';
function CryptExportPublicKeyInfoEx; external CRYPT32 name 'CryptExportPublicKeyInfoEx';
function CryptImportPublicKeyInfo; external CRYPT32 name 'CryptImportPublicKeyInfo';
function CryptImportPublicKeyInfoEx; external CRYPT32 name 'CryptImportPublicKeyInfoEx';
function CryptHashPublicKeyInfo; external CRYPT32 name 'CryptHashPublicKeyInfo';
function CertRDNValueToStrA; external CRYPT32 name 'CertRDNValueToStrA';
function CertRDNValueToStrW; external CRYPT32 name 'CertRDNValueToStrW';
{$IFDEF UNICODE}
function CertRDNValueToStr; external CRYPT32 name 'CertRDNValueToStrW';
{$ELSE}
function CertRDNValueToStr; external CRYPT32 name 'CertRDNValueToStrA';
{$ENDIF} // !UNICODE
function CertNameToStrA; external CRYPT32 name 'CertNameToStrA';
function CertNameToStrW; external CRYPT32 name 'CertNameToStrW';
{$IFDEF UNICODE}
function CertNameToStr; external CRYPT32 name 'CertNameToStrW';
{$ELSE}
function CertNameToStr; external CRYPT32 name 'CertNameToStrA';
{$ENDIF} // !UNICODE
function CertStrToNameW; external CRYPT32 name 'CertStrToNameW';
function CertStrToNameA; external CRYPT32 name 'CertStrToNameA';
{$IFDEF UNICODE}
function CertStrToName; external CRYPT32 name 'CertStrToNameW';
{$ELSE}
function CertStrToName; external CRYPT32 name 'CertStrToNameA';
{$ENDIF} // !UNICODE
function CryptSignMessage; external CRYPT32 name 'CryptSignMessage';
//function CryptSignMessageWithKey; external CRYPT32 name 'CryptSignMessageWithKey';
function CryptVerifyMessageSignature; external CRYPT32 name 'CryptVerifyMessageSignature';
//function CryptVerifyMessageSignatureWithKey; external CRYPT32 name 'CryptVerifyMessageSignatureWithKey';
function CryptGetMessageSignerCount; external CRYPT32 name 'CryptGetMessageSignerCount';
function CryptGetMessageCertificates; external CRYPT32 name 'CryptGetMessageCertificates';
function CryptVerifyDetachedMessageSignature; external CRYPT32 name 'CryptVerifyDetachedMessageSignature';
function CryptEncryptMessage; external CRYPT32 name 'CryptEncryptMessage';
function CryptDecryptMessage; external CRYPT32 name 'CryptDecryptMessage';
function CryptSignAndEncryptMessage; external CRYPT32 name 'CryptSignAndEncryptMessage';
function CryptDecryptAndVerifyMessageSignature; external CRYPT32 name 'CryptDecryptAndVerifyMessageSignature';
function CryptDecodeMessage; external CRYPT32 name 'CryptDecodeMessage';
function CryptHashMessage; external CRYPT32 name 'CryptHashMessage';
function CryptVerifyMessageHash; external CRYPT32 name 'CryptVerifyMessageHash';
function CryptVerifyDetachedMessageHash; external CRYPT32 name 'CryptVerifyDetachedMessageHash';
function CryptSignMessageWithKey; external CRYPT32 name 'CryptSignMessageWithKey';
function CryptVerifyMessageSignatureWithKey; external CRYPT32 name 'CryptVerifyMessageSignatureWithKey';
function CertOpenSystemStoreA; external CRYPT32 name 'CertOpenSystemStoreA';
function CertOpenSystemStoreW; external CRYPT32 name 'CertOpenSystemStoreW';
{$IFDEF UNICODE}
function CertOpenSystemStore; external CRYPT32 name 'CertOpenSystemStoreW';
{$ELSE}
function CertOpenSystemStore; external CRYPT32 name 'CertOpenSystemStoreA';
{$ENDIF} // !UNICODE
function CertAddEncodedCertificateToSystemStoreA; external CRYPT32 name 'CertAddEncodedCertificateToSystemStoreA';
function CertAddEncodedCertificateToSystemStoreW; external CRYPT32 name 'CertAddEncodedCertificateToSystemStoreW';
{$IFDEF UNICODE}
function CertAddEncodedCertificateToSystemStore; external CRYPT32 name 'CertAddEncodedCertificateToSystemStoreW';
{$ELSE}
function CertAddEncodedCertificateToSystemStore; external CRYPT32 name 'CertAddEncodedCertificateToSystemStoreA';
{$ENDIF} // !UNICODE
function FindCertsByIssuer; external SOFTPUB name 'FindCertsByIssuer';
end.
Unit1 :
uses WCrypt2

procedure CryptFile(const SourceFileName, DestinationFileName, Password: string; ToCrypt: Boolean);
var
  hProv: HCRYPTPROV;
  hash: HCRYPTHASH;
  key: HCRYPTKEY;

  Buffer: PByte;
  len: dWord;
  fsIn, fsOut: TFileStream;
  IsEndOfFile: Boolean;
begin
  CryptAcquireContext(@hProv, nil, nil, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  CryptCreateHash(hProv, CALG_SHA, 0, 0, @hash);
  CryptHashData(hash, @Password[1], Length(Password), 0);
  CryptDeriveKey(hProv, CALG_RC4, hash, 0, @key);
  CryptDestroyHash(hash);

  fsIn := TFileStream.Create(SourceFileName, fmOpenRead or fmShareDenyWrite);
  fsOut := TFileStream.Create(DestinationFileName, fmCreate);
  try
    GetMem(Buffer, 512);

    repeat
      IsEndOfFile := (fsIn.Position >= fsIn.Size);
      if IsEndOfFile then break;

      len := fsIn.Read(Buffer^, 512);

      if ToCrypt then
        CryptEncrypt(key, 0, IsEndOfFile, 0, Buffer, @len, len)
      else
        CryptDecrypt(key, 0, IsEndOfFile, 0, Buffer, @len);
      fsOut.Write(Buffer^, len)
    until IsEndOfFile;
    FreeMem(Buffer, 512);
  finally
    fsIn.Free;
    fsOut.Free;
  end;

  CryptReleaseContext(hProv, 0);
end;
Beispiele :
procedure TForm1.Button1Click(Sender: TObject);
begin
  CryptFile('data.txt',      // Original File
            'encrypted.dat', // Crypt File
            Edit1.Text,      // Password
            True);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  CryptFile('encrypted.dat', // Decrypt File
            'data.txt',      // Original File
            Edit1.Text,      // Password
            False);
end;

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate