. NET combines the original independent API and SDK into a framework, which is very beneficial to program developers. It adapted the CryptoAPI into the. NET System. Security. Cryptography namespace, freeing the cryptographic service from the mysteries of the SDK platform and turning it into a simple. NET namespace. As the entire framework component is shared, the cryptographic service is easier to implement. Now you only need to learn about the features of the System. Security. Cryptography namespace and the classes used for specific solutions.
Encryption and decryption algorithms
The System. Security. Cryptography namespace contains classes that implement Security solutions, such as data encryption and decryption, key management, data integrity verification, and data tampering. This article focuses on encryption and decryption.
Encryption and decryption algorithms are classified into symmetric and asymmetric algorithms. Symmetric algorithms use the same key and initialization vector when encrypting and decrypting data. typical algorithms include DES, TripleDES, and Rijndael. They are suitable for keys that do not need to be transmitted, it is mainly used to encrypt local documents or data. Asymmetric algorithms have two different keys: public keys and private keys. Public Keys are transmitted over the network and used to encrypt data, while private keys are used to decrypt data. Asymmetric algorithms include RSA and DSA, which are mainly used to encrypt network data.
Encrypt and decrypt local documents
The following example uses the Rijndael symmetric algorithm to encrypt and decrypt local text.
Symmetric algorithms encrypt data when data passes through. Therefore, you must first create a normal stream (such as an I/O Stream ). This article uses the FileStream class to read text files into byte arrays, and also uses this class as the output mechanism.
Next, define the corresponding object variables. When defining the object variable of the SymmetricAlgorithm abstract class, we can specify any symmetric encryption algorithm provider. The Code uses the Rijndael algorithm, but it is easy to change to the DES or TripleDES algorithm .. NET uses a powerful random key to set the instance of the provider. It is dangerous to select your own key. It is a better choice to accept the key generated by the computer, the code in this article uses a computer-generated key.
Next, the algorithm instance provides an object for actual data transmission. Each algorithm has two methods: CreateEncryptor and CreateDecryptor. They return the objects that implement the ICryptoTransform interface.
Finally, the source file is read using the ReadBytes method of BinaryReader, which returns a byte array. BinaryReader reads the input stream of the source file and calls the ReadBytes method when used as a parameter of the CryptoStream. Write method. The specified CryptoStream instance is told that it should operate on the lower-layer stream. this object will execute data transmission, regardless of whether the stream is intended to read or write.
The following is the source code snippet for encrypting and decrypting a text file:
Namespace com. billdawson. crypto
{
Class TextFileCrypt
{
Public static void Main (string [] args)
{
String file = args [0];
String tempfile = Path. GetTempFileName ();
// Open the specified file
FileStream fsIn = File. Open (file, FileMode. Open,
FileAccess. Read );
FileStream fsOut = File. Open (tempfile, FileMode. Open,
FileAccess. Write );
// Define symmetric algorithm object instances and interfaces
Repeated ricalgorithm symm = new RijndaelManaged ();
ICryptoTransform transform = symm. CreateEncryptor ();
CryptoStream cstream = new CryptoStream (fsOut, transform,
RyptoStreamMode. Write );
BinaryReader br = new BinaryReader (fsIn );
// Read the source file to cryptostream
Cstream. Write (br. ReadBytes (int) fsIn. Length), 0, (int) fsIn. Length );
Cstream. FlushFinalBlock ();
Cstream. Close ();
FsIn. Close ();
FsOut. Close ();
Console. WriteLine ("created encrypted file {0}", tempfile );
Console. WriteLine ("will now decrypt and show contents ");
// Reverse operation -- decrypts the temporary file encrypted just now
FsIn = File. Open (tempfile, FileMode. Open, FileAccess. Read );
Transform = symm. CreateDecryptor ();
Cstream = new CryptoStream (fsIn, transform,
CryptoStreamMode. Read );
StreamReader sr = new StreamReader (cstream );
Console. WriteLine ("decrypted file text:" + sr. ReadToEnd ());
FsIn. Close ();
}
}
}
Source Document Encrypt Network Data
If I only want to see a document, I will not simply send it to you via email. I will encrypt it using symmetric algorithms; if someone intercepts it, they will not be able to read this document because they do not have a unique key for encryption. But you do not have a key. I need to give you a key in some way so that you can decrypt the document, but you cannot take the risk of the key and document being intercepted.
Asymmetric algorithms are a solution. The two keys used by these algorithms have the following relationship: Information encrypted with a public key can only be decrypted by the corresponding private key. Therefore, I first asked you to send me your public key. Someone may intercept it while sending it to me, but it doesn't matter, because they can only use this key to encrypt your information. I used your public key to encrypt the document and sent it to you. You use a private key to decrypt this document. This is the only key that can be decrypted and is not transmitted over the network.
Asymmetric algorithms are more costly and slow than symmetric algorithms. Therefore, we do not want to encrypt all information using asymmetric algorithms in online conversations. Instead, we use symmetric algorithms. In the following example, asymmetric encryption is used to encrypt symmetric keys. Then we use symmetric encryption. In fact, the security Interface Layer (SSL) is used to establish a server and install the security interface layer? BR> the example is a TCP program, which can be divided into the server side and the client side. The workflow on the server side is as follows:
Receives the public key from the client.
Use a public key to encrypt future symmetric keys.
Send the encrypted symmetric key to the client.
Send the Information encrypted with this symmetric key to the client.
The Code is as follows:
Namespace com. billdawson. crypto
{
Public class CryptoServer
{
Private const int RSA_KEY_SIZE_BITS = 1024;
Private const int RSA_KEY_SIZE_BYTES = 252;
Private const int TDES_KEY_SIZE_BITS = 192;
Public static void Main (string [] args)
{
Int port;
String msg;
TcpListener listener;
TcpClient client;
SymmetricAlgorithm symm;
RSACryptoServiceProvider rsa;
// Obtain the port
Try
{
Port = Int32.Parse (args [0]);
Msg = args [1];
}
Catch
{
Console. WriteLine (USAGE );
Return;
}
// Create a listener
Try
{
Listener = new TcpListener (port );
Listener. Start ();
Console. WriteLine ("Listening on port {0}...", port );
Client = listener. AcceptTcpClient ();
Console. WriteLine ("connection ....");
}
Catch (Exception e)
{
Console. WriteLine (e. Message );
Console. WriteLine (e. StackTrace );
Return;
}
Try
{
Rsa = new RSACryptoServiceProvider ();
Rsa. KeySize = RSA_KEY_SIZE_BITS;
// Obtain the public key of the Client
Rsa. ImportParameters (getClientPublicKey (client ));
Symm = new TripleDESCryptoServiceProvider ();
Symm. KeySize = TDES_KEY_SIZE_BITS;
// Use the public key of the client to encrypt the symmetric key and send it to the client.
Encryptandsend1_rickey (client, rsa, symm );
// Use symmetric keys to encrypt and send information
EncryptAndSendSecretMessage (client, symm, msg );
}
Catch (Exception e)
{
Console. WriteLine (e. Message );
Console. WriteLine (e. StackTrace );
}
Finally
{
Try
{
Client. Close ();
Listener. Stop ();
}
Catch
{
// Error
}
Console. WriteLine ("Server exiting ...");
}
}
Private static RSAParameters getClientPublicKey (TcpClient client)
{
// Obtain the serialized public key from the byte stream, and convert it to the instance of the writing class through a string
Byte [] buffer = new byte [RSA_KEY_SIZE_BYTES];
NetworkStream ns = client. GetStream ();
MemoryStream MS = new MemoryStream ();
BinaryFormatter bf = new BinaryFormatter ();
RSAParameters result;
Int len = 0;
Int totalLen = 0;
While (totalLen
(Len = ns. Read (buffer, 0, buffer. Length)> 0)
{
TotalLen + = len;
Ms. Write (buffer, 0, len );
}
Ms. Position = 0;
Result = (RSAParameters) bf. Deserialize (MS );
Ms. Close ();
Return result;
}
Private static void encryptandsend1_rickey (
TcpClient client,
RSACryptoServiceProvider rsa,
SymmetricAlgorithm symm)
{
// Use the public key of the client to encrypt the symmetric key
Byte [] symKeyEncrypted;
Byte [] symIVEncrypted;
NetworkStream ns = client. GetStream ();
SymKeyEncrypted = rsa. Encrypt (symm. Key, false );
SymIVEncrypted = rsa. Encrypt (symm. IV, false );
Ns. Write (symKeyEncrypted, 0, symKeyEncrypted. Length );
Ns. Write (symIVEncrypted, 0, symIVEncrypted. Length );
}
Private static void encryptAndSendSecretMessage (TcpClient client,
SymmetricAlgorithm symm,
String secretMsg)
{
// Use the symmetric key and initialize the vector encryption information and send it to the client.
Byte [] msgAsBytes;
NetworkStream ns = client. GetStream ();
ICryptoTransform transform =
Symm. CreateEncryptor (symm. Key, symm. IV );
CryptoStream cstream =
New CryptoStream (ns, transform, CryptoStreamMode. Write );
MsgAsBytes = Encoding. ASCII. GetBytes (secretMsg );
Cstream. Write (msgAsBytes, 0, msgAsBytes. Length );
Cstream. FlushFinalBlock ();
}
}
Source Document
The client's workflow is:
Create and send a public key to the server.
The server receives the encrypted symmetric key.
Decrypt the symmetric key and use it as a private asymmetric key.
Receives and decrypts information using asymmetric keys.
The Code is as follows:
Namespace com. billdawson. crypto
{
Public class CryptoClient
{
Private const int RSA_KEY_SIZE_BITS = 1024;
Private const int RSA_KEY_SIZE_BYTES = 252;
Private const int TDES_KEY_SIZE_BITS = 192;
Private const int TDES_KEY_SIZE_BYTES = 128;
Private const int TDES_IV_SIZE_BYTES = 128;
Public static void Main (string [] args)
{
Int port;
String host;
TcpClient client;
SymmetricAlgorithm symm;
RSACryptoServiceProvider rsa;
If (args. Length! = 2)
{
Console. WriteLine (USAGE );
Return;
}
Try
{
Host = args [0];
Port = Int32.Parse (args [1]);
}
Catch
{
Console. WriteLine (USAGE );
Return;
}
Try // connect
{
Client = new TcpClient ();
Client. Connect (host, port );
}
Catch (Exception e)
{
Console. WriteLine (e. Message );
Console. Write (e. StackTrace );
Return;
}
Try
{
Console. WriteLine ("Connected. Sending public key .");
Rsa = new RSACryptoServiceProvider ();
Rsa. KeySize = RSA_KEY_SIZE_BITS;
SendPublicKey (rsa. ExportParameters (false), client );
Symm = new TripleDESCryptoServiceProvider ();
Symm. KeySize = TDES_KEY_SIZE_BITS;
MemoryStream MS = getRestOfMessage (client );
ExtractSymmetricKeyInfo (rsa, symm, MS );
ShowSecretMessage (symm, MS );
}
Catch (Exception e)
{
Console. WriteLine (e. Message );
Console. Write (e. StackTrace );
}
Finally
{
Try
{
Client. Close ();
}
Catch {// Error
}
}
}
Private static void sendPublicKey (
RSAParameters key,
TcpClient client)
{
NetworkStream ns = client. GetStream ();
BinaryFormatter bf = new BinaryFormatter ();
Bf. Serialize (ns, key );
}
Private static MemoryStream getRestOfMessage (TcpClient client)
{
// Obtain the encrypted symmetric key, initial vector, and secret information. Public RSA keys for symmetric keys
// Encryption. Secret information is encrypted using Symmetric keys.
MemoryStream MS = new MemoryStream ();
NetworkStream ns = client. GetStream ();
Byte [] buffer = new byte [1024];
Int len = 0;
// Write NetStream data to the memory stream
While (len = ns. Read (buffer, 0, buffer. Length)> 0)
{
Ms. Write (buffer, 0, len );
}
Ms. Position = 0;
Return MS;
}
Private static void extractpolicrickeyinfo (
RSACryptoServiceProvider rsa,
SymmetricAlgorithm symm,
MemoryStream msOrig)
{
MemoryStream MS = new MemoryStream ();
// Obtain the TDES key-it is encrypted by the public RSA key and decrypted using the private key
Byte [] buffer = new byte [TDES_KEY_SIZE_BYTES];
MsOrig. Read (buffer, 0, buffer. Length );
Symm. Key = rsa. Decrypt (buffer, false );
// Obtain the TDES initialization Vector
Buffer = new byte [TDES_IV_SIZE_BYTES];
MsOrig. Read (buffer, 0, buffer. Length );
Symm. IV = rsa. Decrypt (buffer, false );
}
Private static void showSecretMessage (
SymmetricAlgorithm symm,
MemoryStream msOrig)
{
// All data in the memory stream is encrypted.
Byte [] buffer = new byte [1024];
Int len = msOrig. Read (buffer, 0, buffer. Length );
MemoryStream MS = new MemoryStream ();
ICryptoTransform transform =
Symm. CreateDecryptor (symm. Key, symm. IV );
CryptoStream cstream = new CryptoStream (MS, transform,
CryptoStreamMode. Write );
Cstream. Write (buffer, 0, len );
Cstream. FlushFinalBlock ();
// The memory stream is currently in the form of decryption information and byte. It is converted to a string.
Ms. Position = 0;
Len = ms. Read (buffer, 0, (int) ms. Length );
Ms. Close ();
String msg = Encoding. ASCII. GetString (buffer, 0, len );
Console. WriteLine ("The host sent me this secret message :");
Console. WriteLine (msg );
}
}
}
Conclusion
It is suitable for encrypting local data using symmetric algorithms. We can select multiple algorithms to keep code generic. when data is encrypted using a specific CryptoStream, the algorithm encrypts the data using a conversion object. To send data over the network, encrypt the symmetric key with the public asymmetric key received.
This article only involves some services in the System. Security. Cryptography namespace. Although the article ensures that only one private key can decrypt the encrypted information of the corresponding public key, it does not guarantee who sent the public key, and the sender may also be false. You need to use a class that handles digital certificates to deal with this risk.
Source Document