A volte ritornano... CAPICOM - parte 3 - Encryption

In crittografia l’informazione in chiaro viene chiamata “plaintext” mentre lo stesso dato cifrato viene denominato “ciphertext”.

L’encryption è la procedura che converte il paintext in ciphertext, il decription è la funzione inversa che converte il ciphertext in plaintext.
Con CAPICOM è possibile effettuare due distinte operazioni di encryption : a chiave segreta e a chiave pubblica. La prima viene chiamata anche cifratura a chiave simmetrica o “shared secret” utilizzabile tramite l’interfaccia IEncryptedData; la seconda utilizza nuovamente le funzionalità delle chiavi asimmetriche. Quest’ultima viene esposta tramite l’interfaccia IEnvelopedData.

IEncryptedData

La cifratura a chiave simmetrica ha la caratteristica di utilizzare la stessa chiave, detta anche session key, per cifrare e decifrare

 

image

 

Queste chiavi sono un numero random con dimensioni che possono variare da 40 a 2000 bit, spesso generate partendo da un hash. CAPICOM quando genera le chiavi di sessione tramite la cifratura a blocchi le calcola in CBC mode (cipher block chaining) con un Initialization vector (IV) uguale a zero. Infatti questa è la modalità di default della API CryptDeriveKey utilizzata appunto per la generazione delle session key non casuali.

IEncryptedData mette a disposizione due proprietà e tre metodi. Le due proprietà, Content e Algorithm indicano rispettivamente il testo da cifrare e l’algoritmo da utilizzare. Quest’ultimo inoltre permette di specificare anche la lunghezza della chiave. Tuttavia se il tipo di algoritmo o la lunghezza della chiave non è fornito dal CSP in uso, CAPICOM cerca nei restanti CSP Microsoft la disponibilità del servizio. Sulla documentazione MSDN trovate l’ordine di ricerca che CAPICOM effettua in questo caso.

I tre metodi, SetSecret, Encrypt e Decrypt permettono rispettivamente di impostare la password, cifrare e decifrare.

Il seguente esempio rappresenta il minimo codice per cifrare con l’algoritmo AES.

 

Dim enc As New CAPICOM.EncryptedData

Dim cipher As String

Dim secret as String

secret = “:P@assword@01#"

//ENCRYPTION

enc.Content = “WoW…This is a secret!!!!"

enc.Algorithm = CAPICOM_ENCRYPTION_ALGORITHM_AES

enc.SetSecret (secret)

cipher = enc.Encrypt(CAPICOM_ENCODE_BASE64)

//a questo punto cipher contiene il secret cifrato ed encodato in BASE64

//DECRYPTION

Dim plaintext As String

Dim dec As New CAPICOM.EncryptedData

dec.Algorithm = CAPICOM_ENCRYPTION_ALGORITHM_AES

dec.SetSecret (secret)

dec.Decrypt (cipher)

plaintext = dec.Content

 

Quindi, tramite l’interfaccia IEncryptedData, è possibile che n persone siano in grado di cifrare e decifrare i loro documenti con il solo vincolo di essere a conoscenza della chiave di sessione (shared secret appunto). Non sempre questa condizione può essere accettabile, soprattutto quando si rende necessario inviare la chiave di sessione tramite una infrastruttura non sicura come ad esempio Internet. La distribuzione delle chiavi in crittografia è sempre stato uno dei più grossi problemi da affrontare.

Prima di passare a IEnvelopedData facciamo un altro esempio:

image

Una volta premuto il tasto Encrypt si ottiene il seguente output:

MIGUBgkrBgEEAYI3WAOggYYwgYMGCisGAQQBgjdYAwGgdTBzAgMCAAECAmYCAgIA
gAQIRSuTnPybKWEEEDko8rnajaH9lHfFe4s8IvgESDkTa5RySG7MX4SXPI9KU1vk
xMG08Ne3tm7ziGYoL4PVaKruDNRUKz5ccRZrRKvlpwrl59L/ZwBVLYHfxfkhjae1
Oj3uY3zk2g==

che rappresenta il testo cifrato encodato in BASE64.

Come vedete il codice JScript per queste operazioni è molto semplice.

function btnEncryptData_onclick()
{
    // only attempt to has if data has been supploed
    if (txtPlainText.value != "" & pwdSecret.value != "")
    {
        // instantiate the CAPICOM objects
        var EncryptedData = new ActiveXObject("CAPICOM.EncryptedData");
                   
        // clear the cipher text
        txtCipherText.value = "";
                   
        // Setup the Algorithm object based off of the users choice
        EncryptedData.Algorithm.KeyLength = rdoKeyLength.value;
        EncryptedData.Algorithm.Name = rdoAlgorithm.value;

        // Set the secret to be used when deriving the key
        EncryptedData.SetSecret(pwdSecret.value,CAPICOM_SECRET_PASSWORD);
                   
        // Provide the Encrypted Data object with the text to encrypt
        EncryptedData.Content = txtPlainText.value;
                   
        // Encrypt the data and return it in Base64 to the txtCipherText object
        try
        {
           txtCipherText.value = EncryptedData.Encrypt(CAPICOM_ENCODE_BASE64);
        }
        catch (e)
          {
             alert(e.description);
          }
          // clear the plain text
          txtPlainText.value = "";
          // clean up
          EncryptedData = null;
         }
}
 

mentre la funzione di Decrypt :

function btnDecryptData_onclick()
{
     // only attempt to has if data has been supploed
     if (txtCipherText.value != "" & pwdSecret.value != "")
      {
      // instantiate the CAPICOM objects
      var EncryptedData = new ActiveXObject("CAPICOM.EncryptedData");
                   
      // clear the cipher text
      txtPlainText.value = "";
                   
      // The EncryptedData object stores the encryption algorith and key length
      // allong with the CipherText so that the all the relying party needs to know
      // is the password that was used to derive the secret key.
                   
      // Set the secret to be used when deriving the secret key
      EncryptedData.SetSecret(pwdSecret.value,CAPICOM_SECRET_PASSWORD);
                   
      // dencrypt the data in the txtCipherText field
      try
      {
         EncryptedData.Decrypt(txtCipherText.value);
      }
      catch (e)
      {
        alert(e.description);
      }
                   
    // set the data to the txtPlainText field
    txtPlainText.value = EncryptedData.Content;

    // clear the cipher text
    txtCipherText.value = "";

    // clean up
    EncryptedData = null;
   }
}

Può risultare utile la funzione JScript per determinare se CAPICOM è installato in locale:

function IsCAPICOMInstalled()
{
  if(typeof(oCAPICOM) == "object")
     {
         if( (oCAPICOM.object != null) )
          {
             // We found CAPICOM!
             return true;
          }
      }
}

Come diceva un mio amico : Semplice ma funzionale :-)

In un prossimo post parlerò di un problemino di compatibilità con il resto del mondo di IEncryptedData e ovviamente come risolverlo!!

 

IEnvelopedData

Il secondo metodo di cifratura esposto da IEnvelopedData combina la cifratura simmetrica con quella asimmetrica. Innanzitutto CAPICOM internamente genera una session key con la quale cifra il documento (1) . La session key viene a sua volta cifrata con la chiave pubblica presente nel certificato di uno o più destinatari (2) ed infine il pacchetto PKCS#7 risultante contiene il documento cifrato e uno copia della chiave di sessione cifrata per ogni destinatario (3) rendendo di fatto sicuro l’invio della chiave e del documento tramite qualsiasi infrastruttura. A questo punto per il destinatario del documento è semplice decodificare il messaggio: deve decriptare la session key con la propria chiave privata e successivamente può riottenere il documento in chiaro.

image

 

Con CAPICOM  non è necessario preoccuparsi dei dettagli crittografici in quanto l’interfaccia IEnvelopedData espone tre proprietà : Content, Algorithm e Recipients. Analogamente all’interfaccia IEncryptedData la proprietà Content indica il testo in chiaro che dovrà essere inviato, mentre Algorithm rappresenta l’algoritmo di encryption. Recipients è una collection di destinatari identificati tramite il loro certificato. I metodi Encrypt e Decrypt sono autoesplicativi. Il contenuto del messaggio da inviare contiene le seguenti informazioni: le chiavi di sessione cifrate, il messaggio criptato e i certificati di tutti i destinatari.

Sebbene nella documentazione non sia espressamente dichiarato, il formato del file generato da IEnvelopedData è lo standard PKCS#7.

La modalità di verifica dell’interfaccia IEnvelopedData avviene tramite il metodo Decrypt il quale verifica che nello store MY dei certificati installati localmente sia presente un certificato contenuto nel messaggio. In questo contesto è opportuno precisare che IEnvelopedData non è il formato S/MIME e che è necessario scrivere del codice custom che estende le funzioni di CAPICOM con i requirements della specifica S/MIME.

 

--Mario