Block Versus Stream Algorithms

In the preceding chapter, where I described how to generate encryption keys, I mentioned some encryption algorithms that were labeled as either block or stream algorithms. You might be wondering what the difference is between these two types of encryption algorithms. Why would you want to use one over the other?

A block algorithm encrypts data in fixed size chunks. The block size is usually specified by the algorithm being used. Because these algorithms need to encrypt a block of data that is a specific size, the original data is often padded with additional random data. This additional data increases the amount of data so that it is the same size as the block size of the algorithm.

A stream algorithm encrypts data one byte at a time. The data is streamed through the encryption algorithm, each byte being encrypted as it passes through. Stream algorithms usually are much faster than block algorithms, but also are not as secure. Stream algorithms are also better at handling noise in the transfer of encrypted data. If one byte is garbled in the transfer, only one byte will be garbled when decrypted by a stream algorithm, whereas the entire block would be garbled when decrypted by a block algorithm.

So which type of algorithm is better? The answer depends on your specific needs. If you need encryption speed more than you need maximum security, you might prefer a stream algorithm. On the other hand, if you are trying to squeeze every last ounce of security from your encryption, you'll probably want to use a block algorithm.

Salt Values: What Are They and Why Use Them?

In the preceding chapter, when looking at the functions for deriving or generating encryption keys, you may have noticed some option flags for including or not including salt in the key. No, I'm not talking about seasoning some food; I'm talking about cryptographic salt.

Cryptographic salt is a string of random values added to the encryption key to create a longer key. With Microsoft's Base Cryptographic Provider, the generated session keys are 40 bits in length. The salt values it uses are 88 bits long, making a total key length of 128 bits.

So why use salt values? Salt values can be changed throughout a communication session, so any two identical blocks of information will not be encrypted the same. Having two identical encrypted blocks of data is often an indicator that the content is the same, thus making these blocks very attractive to someone trying to break the encryption. By changing the salt value, you can prevent this situation by making sure that no two blocks of identical data are encrypted into identical encrypted blocks.

The next question is how to use salt values. If they are part of the encryption key, how can you change them and still exchange encrypted data? Well, one of the key aspects of salt values is that they can be exchanged in cleartext without jeopardizing key security. So, you can generate a new salt value, use it to encrypt a block of data, and then send the salt value with the encrypted block of data to the recipient. The recipient can then take the new salt value and use it with the session key to decrypt the encrypted data.

Generating Salt Values

When you need to generate a salt value, or when you need to generate a new initialization value for use when generating a new key, you can use the CryptGenRandom function. This function is declared as follows:

 Public Declare Function CryptGenRandom Lib "advapi32.dll" ( _
     ByVal hProv As Long, ByVal dwLen As Long, _
     ByVal pbBuffer As String) As Long

The first parameter (hProv) for the CryptGenRandom function is the handle for the CSP. This handle was acquired with the CryptAcquireContext function. The second parameter (dwLen) is the number of bytes of salt, or initialization data, to be generated.

The third parameter (pbBuffer) is the string buffer into which the salt values will be placed. Just as with the encryption function, you need to allocate the string by using the String function to hold the random values generated.

Note

The CryptGenRandom function generates cryptographically random data. This type of data is different from normal random data that is generated from the Visual Basic Rnd function. The data generated by the Visual Basic Rnd function is not truly random but is generated by a formula in which the rest of the sequence can be predicted when any generated value is known. Cryptographically random data uses other sources of randomness. Sometimes this randomness comes from user input latency; other times, it comes from electronic "noise" or hardware-generated "jitter." Some researchers have even used lava lamps as sources of randomness for use in generating cryptographically random data. The method that is used to generate random data is dependent on the CSP being used.


You could use the CryptGenRandom function as in the following code:

Dim sSaltValue As String
Dim lDataSize As Long

lDataSize = 88
'--- Size the target string for the size specified, filling it with
'--- null characters
sSaltValue = String(lDataSize, vbNullChar)
'--- Generate the Salt Value
If Not CBool(CryptGenRandom(m_lHCryptProv, lDataSize, sSaltValue)) Then
    '--- Error Handling
End If
					

Extracting Salt Values from Session Keys

So, now you know how to generate salt values, either by themselves or as you are creating the encryption key. What you don't know yet, though, is how to extract the current salt value from the key or how to add a new salt value to the key. You can start by extracting the current salt value from the session key.

Among other things, you can get the salt value from a session key by using the CryptGetKeyParam function. This function is declared as follows:

 Public Declare Function CryptGetKeyParam Lib "advapi32.dll" ( _ 
     ByVal hKey As Long, ByVal dwParam As Long, _
     ByVal pbData As String, pdwDataLen As Long, _
     ByVal dwFlags As Long) As Long

An alternative declaration you might also want to use for getting numeric values is as follows:

 Public Declare Function CryptGetKeyDWParam Lib "advapi32.dll" _ 
     Alias "CryptGetKeyParam" (ByVal hKey As Long, _
     ByVal dwParam As Long, pbData As Long, _
     pdwDataLen As Long, ByVal dwFlags As Long) As Long

In this function, the first parameter (hKey) is the handle for an encryption key that was created using either CryptGenKey or CryptDeriveKey (both covered in the preceding chapter). The second parameter (dwParam) specifies what value you want to retrieve from the key object. The possible values for this parameter are listed in Table 4.1.

Table 4.1. CryptGetKeyParam Parameter Values
Key Type Constant Value Function Version Description
All KP_SALT 2 1st Indicates that you want to get the actual salt value currently being used by the key object.
All KP_ PERMISSIONS 6 2nd Indicates that you want a long value containing the set of current permission flags. (The possible permission values are listed in Table 4.2.)
All KP_ALGID 7 2nd Indicates that you want to retrieve the algorithm information from the key object. This value was passed in as the second parameter in the CryptGenKey function.
All KP_BLOCKLEN 8 2nd Indicates that you want to retrieve the block length used by the encryption key. If the key handle is for a Stream algorithm, the resulting value is zero (0).
All KP_KEYLEN 9 2nd Indicates that you want the actual length of the key.
DSS KP_P 11 1st Indicates that you want the prime modulus P from the DSS key.
DSS KP_Q 13 1st Indicates that you want the prime Q from the DSS key.
DSS KP_G 12 1st Indicates that you want the generator G from the DSS key.
Block KP_EFFECTIVE_KEYLEN 19 2nd Indicates that you want the effective key length of an RC2 key.
Block KP_IV 1 1st Indicates that you want the current initialization vector.
Block KP_PADDING 3 2nd Indicates that you want to get the padding method being used by the key. The possible padding modes are listed in Table 4.3.
Block KP_MODE 4 2nd Indicates that you want to get the current cipher mode. The possible modes are listed in Table 4.4.
Block KP_MODE_BITS 5 2nd Indicates that you want the number of bits that are processed per cycle when the OFB or CFB modes are used.

Note

Key parameters labeled as All are available for use with all encryption keys. Parameters labeled as DSS are available only with DSS algorithms. Parameters labeled as Block are available with block algorithms only.


DSS

DSS stands for Digital Signature Standard. This is a standard that specifies the Digital Signature Algorithm (DSA) as it's signing algorithm, and the Secure Hash Algorithm (SHA-1) algorithm as it's message hash algorithm. This is a set of algorithms that can only be used for signing messages, and cannot be used for encrypting data.


The third parameter (pbData) is the variable into which the value requested will be placed. With the first version of the function, it is a string variable that you need to have sized prior to calling this function. If you are using the second version of this function, the variable is a long into which the value is placed. Depending on which parameter you passed in the second parameter (dwParam), the value returned in this parameter may be one of the values listed in Tables 4.2, 4.3, or 4.4.

The fourth parameter (pdwDataLen) is a long variable into which is placed the size of the value in the third parameter. Initially, it needs to be the length of the sized string for the first version of the function, and 4 for the second version.

The fifth parameter (dwFlags) is reserved for future use, so you should always pass zero (0) for this value.

As with most Crypto API functions, this one returns a long Boolean variable that you can check by using the CBool function. As I stated in the previous chapter, in order to keep from repeating myself ad nauseum, assume that all of these Crypto API functions return a C++ Boolean value, and I'll point out to you when they return something different.

Table 4.2. CryptGetKeyParam Permission Flags
Flag Value Description
CRYPT_ENCRYPT &H1 Allows encryption
CRYPT_DECRYPT &H2 Allows decryption
CRYPT_EXPORT &H4 Allows a key to be exported
CRYPT_READ &H8 Allows values to be read
CRYPT_WRITE &H10 Allows values to be set
CRYPT_MAC &H20 Allows MACs to be used with the key

Table 4.3. CryptGetKeyParam Padding Mode
Flag Value Description
PKCS5_PADDING 1 PKCS 5 (section 6.2) padding method
RANDOM_PADDING 2 Random padding method
ZERO_PADDING 3 No padding

Table 4.4. CryptGetKeyParam Cipher Modes
Flag Value Description
CRYPT_MODE_CBC 1 Cipher block chaining
CRYPT_MODE_ECB 2 Electronic codebook
CRYPT_MODE_OFB 3 Output feedback mode
CRYPT_MODE_CFB 4 Cipher feedback mode

Setting Salt Values in Session Keys

Now that you know how to get the current salt value, as well as a few other pieces of information from an encryption key, you probably want to know how to do the reverse and set some of these values (especially the salt value). You do so by using the CryptSetKeyParam function. This function is declared as follows:

 Public Declare Function CryptSetKeyParam Lib "advapi32.dll" ( _
     ByVal hKey As Long, ByVal dwParam As Long, _
     ByVal pbData As String, ByVal dwFlags As Long) As Long

As you can probably guess, a second way to declare this function is as follows:

 Public Declare Function CryptSetKeyDWParam Lib "advapi32.dll" _
     Alias "CryptSetKeyParam" (ByVal hKey As Long, _
     ByVal dwParam As Long, pbData As Long, _
     ByVal dwFlags As Long) As Long

Using this second version, you can set the numeric value and option flag parameters.

The first parameter (hKey) for this function is the handle to the encryption key object. The second parameter (dwParam) is a flag that specifies what aspect of the key is being set. The possible values are listed in Table 4.5.

Table 4.5. CryptSetKeyParam Parameter Values
Key Type Constant Value Function Version Description
All KP_SALT 2 1st Indicates that you are setting the salt value currently being used by the key object.
All KP_ PERMISSIONS 6 2nd Indicates that you are passing a new set of permission flags. (The possible permission values are listed in Table 4.2.)
All KP_ALGID 7 2nd Indicates that you are updating the algorithm for the key object. This constant is usually used only while in negotiation for an acceptable session key algorithm.
Block KP_EFFECTIVE _KEYLEN 19 2nd Indicates that you are setting the effective key length of an RC2 key.
Block KP_IV 1 1st Indicates that you are setting the initialization vector.
Block KP_PADDING 3 2nd Indicates that you are setting the padding method to be used by the key. The possible padding modes are listed in Table 4.3.
Block KP_MODE 4 2nd Indicates that you are setting the current cipher mode. The possible modes are listed in Table 4.4.
Block KP_MODE_BITS 5 2nd Indicates that you are setting the number of bits that are processed per cycle when the OFB or CFB modes are used.

The third parameter (pbData) for this function is the value to be set. Depending on which version of the function you are using, it may be either a string or a long variable.

The fourth parameter (dwFlags) is a set of flags used if you are setting the KP_ALGID value for the key. The possible values for this flag are listed in Table 3.8 in the preceding chapter. Otherwise, you should pass zero (0) for this value.

You also can use another set of key parameter values. However, they don't lend themselves to use with Visual Basic because the parameter being set requires a third version of the CryptSetKeyParam function, as follows:

						
Type CRYPT_INTEGER_BLOB
    cbData As Long
    pbData As Long
End Type

Public Declare Function CryptSetKeyBParam Lib "advapi32.dll" _
    Alias "CryptSetKeyParam" (ByVal hKey As Long, _
    ByVal dwParam As Long, pbData As CRYPT_INTEGER_BLOB, _
    ByVal dwFlags As Long) As Long

The pbData member of the CRYPT_INTEGER_BLOB type is a pointer to a string containing the value to be set. To use this version of the CryptSetKeyParam function, you need to build a C DLL that allows you to pass it a string variable and have it return the pointer value. The other member of the CRYPT_INTEGER_BLOB type, the cbData member, is the length of the string that is pointed to by the pbData member. The parameter values that require this version of the function are listed in Table 4.6.

Tip

If you really wanted to use this third version of this function, you could use the StrPtr function to get a string pointer to the string variable, but then you'd have problems with switching between ANSI and UNICODE strings. You'd be better off copying your string data into a byte array, and then passing a pointer to the first element in the array using the VarPtr function.

If you are unfamiliar with the StrPtr and VarPtr functions, it's because they are undocumented functions in Visual Basic. You'll get a good look at how to use these functions in a couple of chapters.


Table 4.6. CryptSetKeyParam Parameter Values
Key Type Constant Value Description
All KP_SALT_EX 10 Indicates that you are setting the salt value currently being used by the key object.
DSS KP_P 11 Indicates that you are setting the prime modulus P for the DSS key.
DSS KP_Q 13 Indicates that you are setting the prime Q for the DSS key.
DSS KP_G 12 Indicates that you are setting the generator G for the DSS key.
DSS KP_X 14 Indicates that you are setting the X value for the DSS key. The P, Q, and G values must already be set before you set this value.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset