Microsoft CryptoAPI encryption technology (1)

Source: Internet
Author: User

Microsoft CryptoAPI encryption technology (1)
Author: cuick

Download sample source code

In this age of information explosion, we have to be vigilant against information security. Encryption, as a way to ensure data information security, has attracted more and more attention.
Next, I will share my superficial understanding of Microsoft CryptoAPI with you. What's wrong with this.

I. encryption method:

At the beginning, computer research was intended to crack the German password, and people did not think of the information revolution brought by computers today. With the development of computers and the enhancement of computing power, cryptography has made great progress. Generally, there are the following forms.
1. public key encryption technology
Different keys are used for encryption and decryption. They are called "public keys" and "private keys" respectively ". As the name suggests, the "Private Key" cannot be known to others, and the "Public Key" can be made public. The two must be paired and the data encrypted with the public key must be unbound with the corresponding private key. This technology is highly secure and widely used, but its efficiency is too low.
2. symmetric key encryption technology
The same key must be used for encryption and decryption. In this way, the key must be known only by both parties. Otherwise, the key is not secure. This technology is not highly secure but highly efficient.
3. Public and symmetric key encryption technology
Public key encryption technology exchanges high security at the cost of speed, while symmetric encryption exchanges low security for high performance. Therefore, another common encryption method is to combine the above two technologies.
Use symmetric encryption algorithms to encrypt data, and then use a more secure but less efficient public key encryption algorithm to encrypt symmetric keys.
4. digital signature and authentication
It is to sign the encrypted data so that the recipient can know the source of the encrypted data and whether the data has been changed.

Ii. CryptoAPI

Microsoft's CryptoAPI is a recommended encryption API for PKI. It provides application developers with standard encryption interfaces when using encryption, authentication, and other security services in Win32 environments. CryptoAPI is located between the application and the CSP (Cryptographic Service Provider) (see figure 1 ).

The Programming Model of CryptoAPI is similar to that of the Windows Graphics Device Interface GDI. The encryption service provider CSP is equivalent to the graphics device driver, and the encryption hardware (optional) is equivalent to the graphics hardware, the applications at the upper layer are similar. They do not need to deal directly with the device drivers and hardware.

CryptoAPI consists of five parts: simple message functions, low-level message functions, and base cryptographic functions), certificate codec functions (certificate encode/decode functions) and certificate library management functions (certificate store functions ). Among them, the first three can be used to encrypt or sign sensitive information to ensure the privacy of the network transmission confidence. The second two can ensure the authentication in network information exchange through the use of certificates.

Iii. CSP

You may be confused about CSPs. In fact, CSP is an independent module that implements encryption. It can be implemented by software or hardware. However, it must comply with the CryptoAPI specifications.

Each CSP has a name and a type. The name of each CSP is unique, so that the corresponding CSP can be found by CryptoAPI. There are currently nine CSP types, and they are still growing. The following table lists the supported key exchange algorithms, signature algorithms, symmetric encryption algorithms, and hash algorithms.
(Table 1)

CSP type Exchange Algorithm Signature Algorithm Symmetric encryption algorithm Hash Algorithm
Prov_rsa_full RSA RSA RC2
RC4
MD5
Sha
Prov_rsa_sig None RSA None MD5
Sha
Prov_rsa_schannel RSA RSA RC4
Des
Triple DES
MD5
Sha
Prov_dss DSS None DSS MD5
Sha
Prov_dss_dh DH DSS Cylink_mek MD5
Sha
Prov_dh_schannel DH DSS Des
Triple DES
MD5
Sha
Prov_fortezza KEA DSS Skipjack Sha
Prov_ms_exchange RSA RSA Cast MD5
Prov_ssl RSA RSA Varies Varies

As shown in figure 1, each CSP has a keystore used to store keys. Each keystore contains one or more key containers ). Each key container contains all key pairs belonging to a specific user. Each key container is assigned a unique name. CSP permanently saves each key container before destroying the key container, including the public/private key pairs in each key container (see figure 2 ).

4. Create a key container and obtain the CSP handle.

So many things are just theoretical. I will introduce the use of Microsoft CryptoAPI in detail later.

We have mentioned that each CSP has a name and a type, and the name must be unique. Therefore, you can obtain a CSP by name and type. However, if you want to encrypt the key, you must enter it? Right, put it in the key container. (Someone may ask, what is the use of the password library? In fact, the keystore already exists when CSP is installed. It corresponds to CSP .) However, the key container does not exist at the beginning and needs to be created by the user. The following code implements the above functions (CSP is the password container ).

If (cryptacquirecontext (
& Hcryptprov, // return the CSP handle
Username, // password container name
Null, // use the default CSP name when null (Microsoft RSA base provider)
Prov_rsa_full, // CSP type
0) // flag values
{
// The key container named "username" exists, so we have obtained the CSP handle.
Printf ("a crypto context with the % s key container/N", username );
Printf ("has been acquired./n ");
}
Else // if the key container does not exist, we need to create this key container
{
If (cryptacquirecontext (
& Hcryptprov,
Username,
Null,
Prov_rsa_full,
Crypt_newkeyset) // create a secret container named Username
{
// The key container is successfully created and the CSP handle is obtained.
Printf ("a new key container has been created./N ");
}
Else
{
Handleerror ("cocould not create a new key container./N ");
}
} // End of else

Now, we have created the key container and obtained the CSP handle. We can also understand that we get a CSP handle and it is bound to a key container named username. Hey hey ......

All subsequent encryption and decryption operations will be performed on this CSP.
You can delete the secret container as follows.
Cryptacquirecontext (& hcryptprov, username, null, prov_rsa_full, crypt_deletekeyset );

V. An example of file encryption

Someone must have started to say, "How to encrypt and decrypt so much nonsense !" Don't worry. It will be helpful to know some principles first.

Let's take a look at a piece of file encryption code.

# Include <stdio. h>
# Include <windows. h>
# Include <wincrypt. h>
# Define my_encoding_type (pkcs_7_asn_encoding | x509_asn_encoding)
# Define keylength 0x00800000
Void handleerror (char * s );

//--------------------------------------------------------------------
// These additional # define statements are required.
# Define encrypt_algorithm calg_rc4
# Define encrypt_block_size 8

// Declare the function encryptfile. The Function Definition
// Follows main.

Bool encryptfile (
Pchar szsource,
Pchar szdestination,
Pchar szpassword );

//--------------------------------------------------------------------
// Begin main.

Void main (void)
{
Char szsource [100];
Char szdestination [100];
Char szpassword [100];


Printf ("encrypt a file./n ");
Printf ("enter the name of the file to be encrypted :");
Scanf ("% s", szsource );
Printf ("enter the name of the output file :");
Scanf ("% s", szdestination );
Printf ("enter the password :");
Scanf ("% s", szpassword );

//--------------------------------------------------------------------
// Call encryptfile to do the actual encryption.

If (encryptfile (szsource, szdestination, szpassword ))
{
Printf ("encryption of the file % s was a success./N", szsource );
Printf ("the encrypted data is in file % S./N", szdestination );
}
Else
{
Handleerror ("error Encrypting File! ");
}
} // End of main

//--------------------------------------------------------------------
// Code for the function encryptfile called by main.

Static bool encryptfile (
Pchar szsource,
Pchar szdestination,
Pchar szpassword)
//--------------------------------------------------------------------
// Parameters passed are:
// Szsource, the name of the input, a plaintext file.
// Szdestination, the name of the output, an encrypted file to be
// Created.
// Szpassword, the password.
{
//--------------------------------------------------------------------
// Declare and initialize local variables.

File * hsource;
File * hdestination;

Hcryptprov;
Hcryptkey hkey;
Hcrypthash hhash;

Pbyte pbbuffer;
DWORD dwblocklen;
DWORD dwbufferlen;
DWORD dwcount;

//--------------------------------------------------------------------
// Open source file.
If (hsource = fopen (szsource, "rb "))
{
Printf ("the source plaintext file, % s, is open./N", szsource );
}
Else
{
Handleerror ("error opening source plaintext file! ");
}

//--------------------------------------------------------------------
// Open destination file.
If (hdestination = fopen (szdestination, "WB "))
{
Printf ("Destination File % s is open./N", szdestination );
}
Else
{
Handleerror ("error opening destination ciphertext file! ");
}

// Obtain a CSP handle
If (cryptacquirecontext (
& Hcryptprov,
Null, // null indicates that the default key container is used, and the default key container name
// Enter the User Login Name
Null,
Prov_rsa_full,
0 ))
{
Printf ("A Cryptographic provider has been acquired./N ");
}
Else
{
If (cryptacquirecontext (
& Hcryptprov,
Null,
Null,
Prov_rsa_full,
Crypt_newkeyset) // create a key container
{
// The key container is successfully created and the CSP handle is obtained.
Printf ("a new key container has been created./N ");
}
Else
{
Handleerror ("cocould not create a new key container./N ");
}

}

//--------------------------------------------------------------------
// Create a session key)
// The session key is also called a symmetric key and used for symmetric encryption algorithms.
// (Note: A session refers to calling a function from cryptacquirecontext to calling a function.
// The phase during cryptreleasecontext. The session key can only exist in one session process)

//--------------------------------------------------------------------
// Create a hash object.
If (cryptcreatehash (
Hcryptprov,
Calg_md5,
0,
0,
& Hhash ))
{
Printf ("A hash object has been created./N ");
}
Else
{
Handleerror ("error during cryptcreatehash! /N ");
}

//--------------------------------------------------------------------
// Generate a hash using the entered password
If (crypthashdata (
Hhash,
(Byte *) szpassword,
Strlen (szpassword ),
0 ))
{
Printf ("the password has been added to the hash./N ");
}
Else
{
Handleerror ("error during crypthashdata./N ");
}

//--------------------------------------------------------------------
// Generate a session key through hashes
If (cryptderivekey (
Hcryptprov,
Encrypt_algorithm,
Hhash,
Keylength,
& Hkey ))
{
Printf ("an encryption key is derived from the password hash./N ");
}
Else
{
Handleerror ("error during cryptderivekey! /N ");
}
//--------------------------------------------------------------------
// Destroy the hash object.

Cryptdestroyhash (hhash );
Hhash = NULL;

//--------------------------------------------------------------------
// The session key is now ready.

//--------------------------------------------------------------------
// Because the encryption algorithm is encrypted by the encrypt_block_size block, it is encrypted
// The data length must be an integer multiple of encrypt_block_size. Calculate the encrypted
// Data length.

Dwblocklen = 1000-1000% encrypt_block_size;

//--------------------------------------------------------------------
// Determine the block size. If a block cipher is used,
// It must have room for an extra block.

If (encrypt_block_size> 1)
Dwbufferlen = dwblocklen + encrypt_block_size;
Else
Dwbufferlen = dwblocklen;

//--------------------------------------------------------------------
// Allocate memory.
If (pbbuffer = (byte *) malloc (dwbufferlen ))
{
Printf ("memory has been allocated for the buffer./N ");
}
Else
{
Handleerror ("out of memory./N ");
}
//--------------------------------------------------------------------
// In A do loop, encrypt the source file and write to the source file.

Do
{

//--------------------------------------------------------------------
// Read up to dwblocklen bytes from the source file.
Dwcount = fread (pbbuffer, 1, dwblocklen, hsource );
If (ferror (hsource ))
{
Handleerror ("error reading plaintext! /N ");
}

//--------------------------------------------------------------------
// Encrypt data
If (! Cryptencrypt (
Hkey, // key
0, // if the data is hashed and encrypted at the same time,
// Hash object
Feof (hsource), // if it is the last encrypted block, enter true. If not.
// Enter false. Here, you can determine whether the object is at the end of the file.
// The last part.
0, // Reserved
Pbbuffer, // input encrypted data and output encrypted data
& Dwcount, // the actual length of the input encrypted data, and the length of the output encrypted data
Dwbufferlen) // the size of pbbuffer.
{
Handleerror ("error during cryptencrypt./N ");
}

//--------------------------------------------------------------------
// Write data to the destination file.

Fwrite (pbbuffer, 1, dwcount, hdestination );
If (ferror (hdestination ))
{
Handleerror ("error writing ciphertext .");
}

}
While (! Feof (hsource ));
//--------------------------------------------------------------------
// End the do loop when the last block of the source file has been
// Read, encrypted, and written to the destination file.

//--------------------------------------------------------------------
// Close files.

If (hsource)
Fclose (hsource );
If (hdestination)
Fclose (hdestination );

//--------------------------------------------------------------------
// Free memory.

If (pbbuffer)
Free (pbbuffer );

//--------------------------------------------------------------------
// Destroy session key.

If (hkey)
Cryptdestroykey (hkey );

//--------------------------------------------------------------------
// Destroy hash object.

If (hhash)
Cryptdestroyhash (hhash );

//--------------------------------------------------------------------
// Release provider handle.

If (hcryptprov)
Cryptreleasecontext (hcryptprov, 0 );
Return (true );
} // End of encryptfile

//--------------------------------------------------------------------
// This example uses the function handleerror, a simple error
// Handling function, to print an error message to the standard error
// (Stderr) file and exit the program.
// For most applications, replace this function with one
// That does more extensive error reporting.

Void handleerror (char * s)
{
Fprintf (stderr, "An error occurred in running the program./N ");
Fprintf (stderr, "% s/n", S );
Fprintf (stderr, "error Number % x./N", getlasterror ());
Fprintf (stderr, "program terminating./N ");
Exit (1 );
} // End of handleerror

The above Code comes from msdn and is modified. The comment is already very detailed, so I will not go into details here,
Decryption is similar to encryption. You can read the code on your own.

This time I write so much, many people may think that I am well known and easy to write. Don't take it easy. Hey, there will be some in-depth and practical technologies.

Refer:
Msdn chapters.
(Note: If the Code cannot be compiled, add the macro definition: _ win32_winnt = 0x0400)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.