Click here to Skip to main content
Click here to Skip to main content

Strong and Fast Data Encryption with the CAST-128 Algorithm

By , 27 May 2006
Rate this:
Please Sign up or sign in to vote.

Sample Image - CastEncryptor_Image.png

Introduction

Yes, I know, the Rijndael now is the best and generally used (AES) encryption algorithm. Other algorithms are less common and non-standard. Using Rijndael with a 256-bit encryption key makes me sure that my data won't be broken and read by an unauthorized person in the next thousand of years or, more probably, next 1000000... years. But, what if I don't need to hide my data from everybody forever? It is quite enough to maintain my encrypted data within the next 50-60 years or so. To tell the truth, it is almost improbable that one day somebody will be able to break a message encrypted with a key of 128 bits in length if the whole encryption schema won't have a flaw. So, it is the same for most of the applications whether you use an algorithm with 256-bit key or 128-bit key. Both are practically unbreakable. Why don't I like the strongest ciphers? There are two main reasons: the performance, and the usability. The third reason is a little subjective. I prefer easy and comprehensible (for non-mathematicians) algorithms.

This article describes a class which allows to encrypt and decrypt data with the CAST-128 algorithm. This algorithm belongs to the class of encryption algorithms known as Feistel ciphers. It has good resistance to differential and other cryptanalyses, and possesses a number of other desirable cryptographic properties (such as an absence of weak and semi-weak keys). The author of this cipher is Carlisle Adams (Canada). See RFC 2144 for more information on this algorithm.

On the above picture, you can observe the demo application for the CastEncryptor assembly. As you can see, CAST-128 is three times faster than a AES-256 cipher on the .NET 2.0 platform. Also, CAST-128 is two times faster than the reduced version of the Rijndael algorithm working with a 128-bit key (AES-128). It is also much faster than the unmanaged implementation of the TripleDES algorithm (by the TripleDESCryptoServiceProvider class). As for usability, I think it is easier to manipulate keys of 128 bits in length because they are more human readable and can be represented by a value of the System.Guid type. Although it may not be fully correct cryptographically, you can generate new encryption keys with the Guid.NewGuid() method, and the subsequent transformation to a byte array with the Guid.ToByteArray() method. I don't like using text passwords (even hashed with SHA or RipeMD) as encryption keys because such a string contains little unpredictable information.

Using CastEncryptor

Let's see how to use this tool to encrypt some data. Here is the method that accepts binary array, generates an encryption key as a new GUID value, schedules an internal key, then generates an ordinary initial vector and uses all this information for encrypting the binary array in the CBC mode:

public byte[] EncryptMyData(byte[] plainData, out byte[] encryptionKey)
{
    encryptionKey = Guid.NewGuid().ToByteArray();
    int[] scheduledKey = AcedCast5.ScheduleKey(encryptionKey);
    long iv = AcedCast5.GetOrdinaryIV(scheduledKey);
    byte[] result = (byte[])plainData.Clone();
    AcedCast5.EncryptCBC(scheduledKey, result, 0, result.Length, iv);
    AcedCast5.ClearKey(scheduledKey);
    return result;
}

We create a copy of the plainData array before passing it into the EncryptCBC method. This is necessary because this method encrypts data in-place. After use, we should clear the internal key (scheduledKey) for more security. The following is the method for decrypting binary data with the specified decryption key:

public byte[] DecryptMyData(byte[] encryptedData, byte[] decryptionKey)
{
    int[] scheduledKey = AcedCast5.ScheduleKey(decryptionKey);
    long iv = AcedCast5.GetOrdinaryIV(scheduledKey);
    byte[] result = (byte[])encryptedData.Clone();
    AcedCast5.DecryptCBC(scheduledKey, result, 0, result.Length, iv);
    AcedCast5.ClearKey(scheduledKey);
    return result;
}

This implementation of the CAST-128 algorithm has some shortcomings, nevertheless, or rather distinctive features. First of all, it does not support the ICryptoTransform interface. So, it can not be used with the CryptoStream class. The reason for such incompatibility was an attempt to provide maximum performance. I think, instead of supporting the ICryptoTransform interface, it would be better to create separate stream classes (for encryption and decryption, or writing and reading) which work the same way as the CryptoStream class and use internally the AcedCast5 class. Though, I have felt no need for such stream classes yet.

This encryption engine supports the Cipher Block Chaining (CBC) mode. Here, there is another shortcoming. This implementation has no support for padding messages which have not enough bytes to fill the last block. The block size in the CAST-128 algorithm is 8 bytes. The length of the encrypted/decrypted range of the source byte array must be a multiple of the block size. For example, if the length of the plainData array in the above code will not be divisible by 8, the EncryptCBC method throws an ArgumentException. The padding problem is imposed on the developer who uses the EncryptCBC and DecryptCBC methods, because I don't know the perfect solution to this problem.

AcedCast5 Class

public sealed class AcedCast5

This class provides methods for the encryption/decryption of binary data with the CAST-128 encryption algorithm. This implementation of the CAST-128 algorithm conforms to RFC 2144. The only supported encryption modes are ECB and CBC.

There is a restriction for the CBC mode: the length of the input array must be a multiple of the encryption block size (8 bytes).

The key size for this algorithm is 128 bits. The source 16-byte encryption/ decryption key (the keyBytes argument) must be transformed (scheduled) into the internal 128-byte key, with the ScheduleKey method. All the other methods, except ScheduleKey, work with such an internal key. At the end of work, you should pass that internal key into the ClearKey method to wipe it out for more safety.

In a multithreaded application, you should synchronize calls to the methods of this class.

public static int[] ScheduleKey(byte[] keyBytes)

This method creates and returns an internal key which should be used with other methods of this class. That key depends on the source 16-byte key passed in the keyBytes argument. You should clear the internal key at the end of the encryption/decryption session, passing the key to the ClearKey method.

public static void ScheduleKey(byte[] keyBytes, int[] key)

This method is the same as the previous method but allows to reuse an existent 128-byte internal key to avoid memory reallocation. In the key parameter, you should pass an array of 32 values of the System.Int32 type.

public static void EncryptECB(int[] key, byte[] bytes, int offset)

This method encrypts with the CAST-128 algorithm, the eight bytes of the bytes array, starting from the element with the offset index. The internal key (see the ScheduleKey method) must be passed in the key argument.

public static void DecryptECB(int[] key, byte[] bytes, int offset)

This method decrypts with the CAST-128 algorithm, the 8 bytes of the bytes array, starting from the element with the offset index. The internal key (see the ScheduleKey method) must be passed in the key argument.

public static long GetOrdinaryIV(int[] key)

This method generates an ordinary initial vector for an encryption or decryption process, with the specified key. This method encrypts an empty (filled with zeros) block with the current key. The result can be used as an initial vector. This is more secure than using a zero-filled initial vector.

public static long EncryptCBC(int[] key, 
       byte[] bytes, int offset, int length, long iv)

This method encrypts a fragment of the bytes array of length bytes in length, starting from the element with the offset index. The value of the length argument must be a multiple of 8. This method implements the CBC mode. The internal encryption key is passed in the key parameter. Here, the iv argument passes the initial vector. The method returns a new initial vector which can be used for encryption of the next data block.

public static long DecryptCBC(int[] key, byte[] bytes, 
       int offset, int length, long iv)

This method decrypts a fragment of the bytes array of length bytes in length, starting from the element with the offset index. The value of the length argument must be a multiple of 8. This method implements the CBC mode. The internal decryption key is passed in the key parameter. Here, the iv argument passes the initial vector. The method returns a new initial vector which can be used for decryption of the next data block.

public static void ClearKey(int[] key)

This method clears the internal key passed with the key parameter. It is assumed that the key is generated using the ScheduleKey method.

Conclusion

I hope you will find this article useful. It is quite possible that one day I will create a wrapper for the AcedCast5 class inherited from the Stream class, or you may do that yourself Smile | :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Andrey Dryazgov
Software Developer
Russian Federation Russian Federation
No Biography provided

Comments and Discussions

 
QuestionCAST-128 implementation is compatible with others? PinmemberKU27-Dec-13 20:50 
AnswerRe: CAST-128 implementation is compatible with others? PinprofessionalAndrey Dryazgov28-Dec-13 0:18 
GeneralRe: CAST-128 implementation is compatible with others? PinmemberKU28-Dec-13 1:59 
Question8 byte block size constraints PinmemberJeff Lucifer8-Dec-13 21:56 
QuestionQuestion PinmemberDisactive8-Dec-12 14:41 
AnswerRe: Question PinmemberAndrey Dryazgov15-Jun-13 7:52 
GeneralRe: Question PinmemberDisactive15-Jun-13 17:35 
GeneralRe: Question PinmemberAndrey Dryazgov15-Jun-13 17:56 
GeneralRe: Question PinmemberDisactive17-Jun-13 4:26 
QuestionDecryption in ECB mode doesn't give the correct value PinmemberShyam Chebrolu7-Oct-10 14:12 
GeneralDecryption PinmemberHHashim25-Jan-07 8:18 
GeneralRe: Decryption PinmemberAndrey Dryazgov25-Jan-07 8:42 
GeneralRe: Decryption PinmemberHHashim25-Jan-07 11:16 
GeneralA correction about using the Guid.NewGuid() for generating encryption keys PinmemberAndrey Dryazgov13-Jun-06 13:03 
GeneralRe: A correction about using the Guid.NewGuid() for generating encryption keys PinmemberSubMash4-Jan-08 9:52 
GeneralTime to break encryption Pinmemberteglsbo27-May-06 9:19 
GeneralRe: Time to break encryption PinmemberEd.Poore28-May-06 0:47 
GeneralRe: Time to break encryption Pinmemberaxelriet28-May-06 12:37 
GeneralRe: Time to break encryption Pinmemberteglsbo29-May-06 1:05 
GeneralRe: Time to break encryption Pinmemberaxelriet29-May-06 5:43 
GeneralRe: Time to break encryption Pinmemberpmichaud30-Jan-07 8:05 
GeneralRe: Time to break encryption PinmemberRi Qen-Sin3-Dec-07 15:45 
GeneralRe: Time to break encryption PinmemberAsgalium11-Mar-08 5:27 
These cyphers are certainly unbreakable if our future technology will be like our current technology as we know it.
I think that the acceleration in technological discoveries that we are seeing now will provide us with "shortcuts" to bypass these brute force attacks and crack all these protections.
 
Let's say we will be using Quantum Computing to break them, just as an example, but I'm sure that there will be other discoveries that we just can't even imagine.
 
All in all I think that all these calculations about millions or billions of years are just nonsense.
 
The reality is that those kind of symmetrical key cyphers will be reasonably unbreakable for the next 10-20 years. And that is enough for most sensitive data. We can't know what kind of calculator we will have in 30 years, quantic, molecular, organic, photonic, spintronic...
 
http://en.wikipedia.org/wiki/Quantum_computer

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140415.2 | Last Updated 27 May 2006
Article Copyright 2006 by Andrey Dryazgov
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid