Cryptography Example

A handle to a cryptographic service provider (CSP) is obtained using the GetCryptoProvider function. This returns a variable that contains a small wrapper for the CSP handle. The wrapper is necessary to ensure the CSP handle is correctly released when it is no longer referenced.

Calling the GenerateKey function creates a variable that contains a handle to a key. The variable may be copied which generates a duplicate of the key.

Properties of the key may be read and set using the GetKeyParam and SetKeyParam functions respectively.

To transfer secret session keys, the ExportKey and ImportKey functions are used.

Data is encrypted and decrypted using the Encrypt and Decrypt functions.

Example:

[
{ Variables and Constants for CSP } 
   CSP; 
   CSPFail; 
   Constant CRYPT_EXPORTABLE = 0x00000001;
   Container = "VTS"; 
   Constant PROV_DSS_DH = 13; 
   Constant CRYPT_NEWKEYSET = 8; 
   Constant NTE_BAD_KEYSET = 0x80090016; 
{ Items for key generation } 
   Key1; 
   Key2; 
   Constant CALG_DH_EPHEM = 0xAA02; 
   Constant KEY_SIZE = 512; 
   Constant CRYPT_PREGEN = 0x00000040; 
{ Items for key parameter set } 
   Constant KP_PERMISSIONS = 6; 
{ Items for key parameter get/set } 
   KeyP; 
   KeyG; 
   Constant KP_P = 11 { DSS/Diffie-Hellman P value }; 
   Constant KP_G = 12 { DSS/Diffie-Hellman G value }; 
   Constant KP_Q = 13 { DSS Q value }; 
   Constant KP_X = 14 { Diffie-Hellman X value }; 
   Constant KP_Y = 15 { Y value }; 
{ Items for export/import } 
   PubKey1; 
   PubKey2; 
   Constant PUBLICKEYBLOB = 0x6; 
   Key3; 
   Key4; 
{ Algorithm conversion } 
   Constant KP_ALGID = 7; 
   Constant CALG_RC4 = 0x6801; 
{ Variables for encryption / decryption } 
   PlainText1 = "abcdefghijklmnopqrstuvwxyz0123456789"; 
   CipherText1; 
   PlainText2; 
]
Init [
   If 1 Main; 
   [ 
      { Get the CSP } 
      CSP = GetCryptoProvider(PROV_DSS_DH, Invalid, Container, Invalid, CSPFail); 
      IfThen(CSPFail == NTE_BAD_KEYSET, 
      { Not used this container before, make a new one } 
         CSP = GetCryptoProvider(PROV_DSS_DH, Invalid, Container, CRYPT_NEWKEYSET, CSPFail); 
      ); 

      { Make a key } 
      Key1 = GenerateKey(CSP, CALG_DH_EPHEM,  KEY_SIZE << 16 || CRYPT_EXPORTABLE); 

      { Get the key parameters } 
      KeyG = GetKeyParam(Key1, KP_G); 
      KeyP = GetKeyParam(Key1, KP_P); 

      { Make another key using the parameters } 
      Key2 = GenerateKey(CSP, CALG_DH_EPHEM, (KEY_SIZE << 16) || CRYPT_PREGEN); 
      SetKeyParam(Key2, KP_G, KeyG); 
      SetKeyParam(Key2, KP_P, KeyP); 
      SetKeyParam(Key2, KP_X); 

      { Export the public keys from both keys, and import to each other } 
      PubKey1 = ExportKey(Key1, PUBLICKEYBLOB); 
      PubKey2 = ExportKey(Key2, PUBLICKEYBLOB); 
      Key3 = ImportKey(CSP, PUBLICKEYBLOB, PubKey1, Key2); 
      Key4 = ImportKey(CSP, PUBLICKEYBLOB, PubKey2, Key1); 

      { Now convert the shared secret key to the bulk encryption key } 
      SetKeyParam(Key3, KP_ALGID, CALG_RC4); 
      SetKeyParam(Key4, KP_ALGID, CALG_RC4); 

      { Now use the keys to encrypt and decrypt some data } 
      CipherText1 = Encrypt(Key3, PlainText1, 1, 0, 0); 
      PlainText2 = Decrypt(Key4, CipherText1, 1, 0, 0); 
   ] 
]

The sample code demonstrates instantiating a CSP, generating two public / private key pairs, exporting the public parts of the keys, importing the public keys to create two new keys that have a shared secret, converting the resulting keys to a symmetric key and encrypting and decrypting data. For the sake of clarity, error handling is not shown.

Some points to note are:

  • Many parameters to the Cryptography functions and statements are constants that are defined in WinCrypt. The functions and statements do not interpret these values, but pass them directly to the CryptoAPI. This enables all the current and any new features of the CryptoAPI to be used without having to modify engine code if the parameters were directly interpreted.
  • The GetCryptoProvider function returns a value that represents a handle to the required CSP.
  • As the CSP isn't named, the actual CSP returned will depend on the OS and version of Internet Explorer. For this reason it's recommended that key sizes and other variable parameters are explicitly set.
  • GenerateKey is a function that returns a value holds the generated Key.
  • GetKeyParam and SetKeyParam are used to read and write to parameters of a Key.
  • The public part of Key1 is exported to a text variable that is returned by ExportKey, which is then imported into Key2 producing Key3 using ImportKey. A similar operation is performed to produce Key4. Key3 and Key4 now contain a shared secret.
  • The keys containing the shared secret are converted to a symmetric key using SetKeyParam.
  • Encrypt returns a text string that is the ciphertext of the plaintext string passed as a parameter. Decrypt returns a text string that is the plaintext of the ciphertext string passed as a parameter.
  • A variable containing a CSP handle has a type of 36 and if printed will display the textual name of the CSP.
  • A variable containing a Key handle has a type of 37 and if printed will display the hexadecimal value of the algorithm ID of the key.

Decrypt

DeriveKey Encrypt
ExportKey GetCryptoProvider GenerateKey
GetKeyParam ImportKey SetKeyParam