Xceed .NET Libraries Documentation
Welcome to Xceed Data Manipulation Compoents for .NET and .NET Standard / Basic Concepts / Zip and streaming capabilities / AES Encryption

AES Encryption

Xceed's implementation of AES encryption lets you incorporate industry standard strong encryption in your .NET applications.

Encryption method

The EncryptionMethod enumeration provides the following values, representing the kind of encryption used:

Value Description
Compatible The traditional ZIP encryption. This is a weak encryption method.
WinZipAES The WinZip AES encryption method. This is a strong encryption method.
Note: This encryption method is not currently available in Xceed's .NET Compact Framework products.
You can specify the implementation to be used for AES encryption. See Using alternative AES implementations under Advanced Concepts.
The length of the password is not limited. However, to preserve compatibility with other Zip compression utilities, it is recommended that you limit passwords to no greater than 80 characters. It is also advisable to only use ASCII characters because there is no accepted standard on how to encode non-ASCII characters in passwords.

Encrypting

The following code demonstrates how to use Xceed's AES encryption. WinZipAes is used as the encryption method, and the encryption strength is set to 256 bits:

public void EncryptExample()
{
  AbstractFile zipFile = new DiskFile( @"ZipFile.zip" );

  // If the zip file already exists
  if( zipFile.Exists )
  {
    // Delete it
    zipFile.Delete();
  }

  ZipArchive zip = new ZipArchive( zipFile );

  /* The length of the password is not limited. However, to preserve compatibility
  with other Zip compression utilities, it is recommended that you limit passwords
  to no greater than 80 characters.
  
  It is also advisable to only use ASCII characters because there is no
  accepted standard on how to encode non-ASCII characters in passwords. */
  string password = "MyPassword";

  zip.DefaultEncryptionMethod = EncryptionMethod.WinZipAes;
  zip.DefaultEncryptionStrength = 256;
  zip.DefaultEncryptionPassword = password;

  using( AutoBatchUpdate batch = new AutoBatchUpdate( zip ) )
  {
    AbstractFolder sourceFolder = new DiskFolder( @"D:\Temp\foo" );

    // Zip the contents of the source folder
    sourceFolder.CopyFilesTo( zip, true, true );
  }
}

Decrypting

Decryption is demonstrated in the following code. Note that it is not necessary to specify the encryption method or strength, as these are detected automatically.

public void DecryptExample()
{
  // Setup a zip file
  AbstractFile zipFile = new DiskFile( @"ZipFile.zip" );

  // If the zip file doesn't exist
  if( !zipFile.Exists )
  {
    // Fail
    return;
  }

  // Setup a destination folder
  AbstractFolder destinationFolder = new DiskFolder( @"D:\Temp\Unzip" );

  ZipArchive zip = new ZipArchive( zipFile );

  /* The length of the password is not limited. However, to preserve compatibility
  with other Zip compression utilities, it is recommended that you limit passwords
  to no greater than 80 characters.
  
  It is also advisable to only use ASCII characters because there is no
  accepted standard on how to encode non-ASCII characters in passwords. */

  // Set up the list of password possible for the items in this archive
  this.m_passwords = new string[]
  {
    "MyPassword",
    "wrong password",
    "fkEI-969=6kei$[BbZ \"6Iq- =[",
    "}8{)zM#$k//O?t~=iG'Si{AF\"S~\'/8@1n",
  };

  // Use our most likely password as the default
  zip.DefaultDecryptionPassword = this.m_passwords[ 0 ];

  // Subscribe to the events that will allow us to handle invalid passwords
  ZipEvents events = new ZipEvents();
  events.ItemProgression += new ItemProgressionEventHandler( OnItemProgression );
  events.ItemException += new ItemExceptionEventHandler( OnItemException );

  // Unzip the contents of the zip archive to the destination folder
  zip.CopyFilesTo( events, zip, destinationFolder, true, true );
}

private void OnItemProgression( object sender, ItemProgressionEventArgs e )
{
  /* We're about to process a new item */

  // Reset the password index
  this.m_passwordIndex = 0;
}

private void OnItemException( object sender, ItemExceptionEventArgs e )
{
  bool badPassword = false;

  // Get the archive object we passed through the user data
  ZipArchive zip = ( ZipArchive ) e.UserData;

  /* We will try to ascertain if we have an invalid password */

  InvalidDecryptionPasswordException invalidDecryptionPasswordException;
  FileSystemIOException fileSystemIOException;

  invalidDecryptionPasswordException = e.Exception as InvalidDecryptionPasswordException;
  fileSystemIOException = e.Exception as FileSystemIOException;

  // If the exception says that a bad password was supplied
  if( invalidDecryptionPasswordException != null )
  {
    badPassword = true;
  }
  // If we had an I/O error during decryption
  else if( fileSystemIOException != null )
  {
    ZippedFile zippedFile = e.CurrentItem as ZippedFile;

    // If we were reading from a zipped file encrypted in the 'compatible' method
    if( zippedFile != null && zippedFile.Encrypted &&
        zippedFile.EncryptionMethod.Equals( EncryptionMethod.Compatible ) )
    {
      /* It's possible the I/O error occurred because the password is invalid.
      The was the 'compatible' encryption is designed doesn't provide for 100%
      accurate bad password detection, unfortunately.
        
      Note that AES encryption has no such design flaw. */
      badPassword = true;
    }
  }

  // If we had a bad password
  if( badPassword )
  {
    // If we haven't gone through our password list
    if( this.m_passwordIndex < this.m_passwords.Length )
    {
      // Set the current password and move the index to the next password
      zip.DefaultDecryptionPassword = this.m_passwords[ this.m_passwordIndex++ ];

      // Retry unzipping the file
      e.Action = ItemExceptionAction.Retry;
    }
    else
    {
      // Skip the file
      e.Action = ItemExceptionAction.Ignore;
    }
  }
}

private string[] m_passwords;
private int m_passwordIndex;