C# 實現的 AES 加密算法

bdnp 9年前發布 | 2K 次閱讀 C# 算法

using System;
using System.IO;
using System.Security.Cryptography;

// // Sample encrypt/decrypt functions // Parameter checks and error handling // are ommited for better readability // @author:Ashwin Kumar // Date : 12/3/2008 public class AESEncryptionUtility { static int Main(string[] args) { if (args.Length < 2) { Console.WriteLine("Usage: AESEncryptionUtility infile outFile"); return 1; } string infile = args[0]; string outfile = args[1]; //string keyfile = args[2]; //var key = File.ReadAllBytes(keyfile); Encrypt(infile,outfile,"test"); Decrypt(outfile,"_decrypted"+infile,"test"); return 0;

}

// Encrypt a byte array into a byte array using a key and an IV
public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
{
    // Create a MemoryStream to accept the encrypted bytes
    MemoryStream ms = new MemoryStream();
    // Create a symmetric algorithm.
    // We are going to use Rijndael because it is strong and
    // available on all platforms.
    // You can use other algorithms, to do so substitute the
    // next line with something like
    //      TripleDES alg = TripleDES.Create();
    Rijndael alg = Rijndael.Create();
    // Now set the key and the IV.
    // We need the IV (Initialization Vector) because
    // the algorithm is operating in its default
    // mode called CBC (Cipher Block Chaining).
    // The IV is XORed with the first block (8 byte)
    // of the data before it is encrypted, and then each
    // encrypted block is XORed with the
    // following block of plaintext.
    // This is done to make encryption more secure.
    // There is also a mode called ECB which does not need an IV,
    // but it is much less secure.
    alg.Key = Key;
    alg.IV = IV;
    // Create a CryptoStream through which we are going to be
    // pumping our data.
    // CryptoStreamMode.Write means that we are going to be
    // writing data to the stream and the output will be written
    // in the MemoryStream we have provided.
    CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
    // Write the data and make it do the encryption
    cs.Write(clearData, 0, clearData.Length);
    // Close the crypto stream (or do FlushFinalBlock).
    // This will tell it that we have done our encryption and
    // there is no more data coming in,
    // and it is now a good time to apply the padding and
    // finalize the encryption process.
    cs.Close();
    // Now get the encrypted data from the MemoryStream.
    // Some people make a mistake of using GetBuffer() here,
    // which is not the right way.
    byte[] encryptedData = ms.ToArray();
    return encryptedData;
}

// Encrypt a string into a string using a password
//    Uses Encrypt(byte[], byte[], byte[])
public static string Encrypt(string clearText, string Password)
{
    // First we need to turn the input string into a byte array.
    byte[] clearBytes =
      System.Text.Encoding.Unicode.GetBytes(clearText);
    // Then, we need to turn the password into Key and IV
    // We are using salt to make it harder to guess our key
    // using a dictionary attack -
    // trying to guess a password by enumerating all possible words.
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
    // Now get the key/IV and do the encryption using the
    // function that accepts byte arrays.
    // Using PasswordDeriveBytes object we are first getting
    // 32 bytes for the Key
    // (the default Rijndael key length is 256bit = 32bytes)
    // and then 16 bytes for the IV.
    // IV should always be the block size, which is by default
    // 16 bytes (128 bit) for Rijndael.
    // If you are using DES/TripleDES/RC2 the block size is
    // 8 bytes and so should be the IV size.
    // You can also read KeySize/BlockSize properties off
    // the algorithm to find out the sizes.
    byte[] encryptedData = Encrypt(clearBytes,
             pdb.GetBytes(32), pdb.GetBytes(16));

    // Now we need to turn the resulting byte array into a string.
    // A common mistake would be to use an Encoding class for that.
    //It does not work because not all byte values can be
    // represented by characters.
    // We are going to be using Base64 encoding that is designed
    //exactly for what we are trying to do.
    return Convert.ToBase64String(encryptedData);
}

// Encrypt bytes into bytes using a password
//    Uses Encrypt(byte[], byte[], byte[])
public static byte[] Encrypt(byte[] clearData, string Password)
{
    // We need to turn the password into Key and IV.
    // We are using salt to make it harder to guess our key
    // using a dictionary attack -
    // trying to guess a password by enumerating all possible words.
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

    // Now get the key/IV and do the encryption using the function
    // that accepts byte arrays.
    // Using PasswordDeriveBytes object we are first getting
    // 32 bytes for the Key
    // (the default Rijndael key length is 256bit = 32bytes)
    // and then 16 bytes for the IV.
    // IV should always be the block size, which is by default
    // 16 bytes (128 bit) for Rijndael.
    // If you are using DES/TripleDES/RC2 the block size is 8
    // bytes and so should be the IV size.
    // You can also read KeySize/BlockSize properties off the
    // algorithm to find out the sizes.
    return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16));
}

// Encrypt a file into another file using a password
public static void Encrypt(string fileIn,
            string fileOut, string Password)
{
    // First we are going to open the file streams
    FileStream fsIn = new FileStream(fileIn,
        FileMode.Open, FileAccess.Read);
    FileStream fsOut = new FileStream(fileOut,
        FileMode.OpenOrCreate, FileAccess.Write);
    // Then we are going to derive a Key and an IV from the
    // Password and create an algorithm
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
    Rijndael alg = Rijndael.Create();
    alg.Key = pdb.GetBytes(32);
    alg.IV = pdb.GetBytes(16);
    // Now create a crypto stream through which we are going
    // to be pumping data.
    // Our fileOut is going to be receiving the encrypted bytes.
    CryptoStream cs = new CryptoStream(fsOut,
        alg.CreateEncryptor(), CryptoStreamMode.Write);

    // Now will will initialize a buffer and will be processing
    // the input file in chunks.
    // This is done to avoid reading the whole file (which can
    // be huge) into memory.
    int bufferLen = 4096;
    byte[] buffer = new byte[bufferLen];
    int bytesRead;
    do {
        // read a chunk of data from the input file
        bytesRead = fsIn.Read(buffer, 0, bufferLen);
        // encrypt it
        cs.Write(buffer, 0, bytesRead);
    } while(bytesRead != 0);
    // close everything
    // this will also close the unrelying fsOut stream
    cs.Close();
    fsIn.Close();
}

// Decrypt a byte array into a byte array using a key and an IV
public static byte[] Decrypt(byte[] cipherData,
                            byte[] Key, byte[] IV)
{
    // Create a MemoryStream that is going to accept the
    // decrypted bytes
    MemoryStream ms = new MemoryStream();
    // Create a symmetric algorithm.
    // We are going to use Rijndael because it is strong and
    // available on all platforms.
    // You can use other algorithms, to do so substitute the next
    // line with something like
    //     TripleDES alg = TripleDES.Create();
    Rijndael alg = Rijndael.Create();
    // Now set the key and the IV.
    // We need the IV (Initialization Vector) because the algorithm
    // is operating in its default
    // mode called CBC (Cipher Block Chaining). The IV is XORed with
    // the first block (8 byte)
    // of the data after it is decrypted, and then each decrypted
    // block is XORed with the previous
    // cipher block. This is done to make encryption more secure.
    // There is also a mode called ECB which does not need an IV,
    // but it is much less secure.
    alg.Key = Key;
    alg.IV = IV;
    // Create a CryptoStream through which we are going to be
    // pumping our data.
    // CryptoStreamMode.Write means that we are going to be
    // writing data to the stream
    // and the output will be written in the MemoryStream
    // we have provided.
    CryptoStream cs = new CryptoStream(ms,
        alg.CreateDecryptor(), CryptoStreamMode.Write);
    // Write the data and make it do the decryption
    cs.Write(cipherData, 0, cipherData.Length);
    // Close the crypto stream (or do FlushFinalBlock).
    // This will tell it that we have done our decryption
    // and there is no more data coming in,
    // and it is now a good time to remove the padding
    // and finalize the decryption process.
    cs.Close();
    // Now get the decrypted data from the MemoryStream.
    // Some people make a mistake of using GetBuffer() here,
    // which is not the right way.
    byte[] decryptedData = ms.ToArray();
    return decryptedData;
}

// Decrypt a string into a string using a password
//    Uses Decrypt(byte[], byte[], byte[])
public static string Decrypt(string cipherText, string Password)
{
    // First we need to turn the input string into a byte array.
    // We presume that Base64 encoding was used
    byte[] cipherBytes = Convert.FromBase64String(cipherText);
    // Then, we need to turn the password into Key and IV
    // We are using salt to make it harder to guess our key
    // using a dictionary attack -
    // trying to guess a password by enumerating all possible words.
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65,
        0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
    // Now get the key/IV and do the decryption using
    // the function that accepts byte arrays.
    // Using PasswordDeriveBytes object we are first
    // getting 32 bytes for the Key
    // (the default Rijndael key length is 256bit = 32bytes)
    // and then 16 bytes for the IV.
    // IV should always be the block size, which is by
    // default 16 bytes (128 bit) for Rijndael.
    // If you are using DES/TripleDES/RC2 the block size is
    // 8 bytes and so should be the IV size.
    // You can also read KeySize/BlockSize properties off
    // the algorithm to find out the sizes.
    byte[] decryptedData = Decrypt(cipherBytes,
       pdb.GetBytes(32), pdb.GetBytes(16));
    // Now we need to turn the resulting byte array into a string.
    // A common mistake would be to use an Encoding class for that.
    // It does not work
    // because not all byte values can be represented by characters.
    // We are going to be using Base64 encoding that is
    // designed exactly for what we are trying to do.
    return System.Text.Encoding.Unicode.GetString(decryptedData);
}

// Decrypt bytes into bytes using a password
//    Uses Decrypt(byte[], byte[], byte[])
public static byte[] Decrypt(byte[] cipherData, string Password)
{
    // We need to turn the password into Key and IV.
    // We are using salt to make it harder to guess our key
    // using a dictionary attack -
    // trying to guess a password by enumerating all possible words.
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
    // Now get the key/IV and do the Decryption using the
    //function that accepts byte arrays.
    // Using PasswordDeriveBytes object we are first getting
    // 32 bytes for the Key
    // (the default Rijndael key length is 256bit = 32bytes)
    // and then 16 bytes for the IV.
    // IV should always be the block size, which is by default
    // 16 bytes (128 bit) for Rijndael.
    // If you are using DES/TripleDES/RC2 the block size is
    // 8 bytes and so should be the IV size.
    // You can also read KeySize/BlockSize properties off the
    // algorithm to find out the sizes.
    return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16));
}

// Decrypt a file into another file using a password
public static void Decrypt(string fileIn,
            string fileOut, string Password)
{
    // First we are going to open the file streams
    FileStream fsIn = new FileStream(fileIn,
                FileMode.Open, FileAccess.Read);
    FileStream fsOut = new FileStream(fileOut,
                FileMode.OpenOrCreate, FileAccess.Write);
    // Then we are going to derive a Key and an IV from
    // the Password and create an algorithm
    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
        new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
        0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
    Rijndael alg = Rijndael.Create();
    alg.Key = pdb.GetBytes(32);
    alg.IV = pdb.GetBytes(16);
    // Now create a crypto stream through which we are going
    // to be pumping data.
    // Our fileOut is going to be receiving the Decrypted bytes.
    CryptoStream cs = new CryptoStream(fsOut,
        alg.CreateDecryptor(), CryptoStreamMode.Write);
    // Now will will initialize a buffer and will be
    // processing the input file in chunks.
    // This is done to avoid reading the whole file (which can be
    // huge) into memory.
    int bufferLen = 4096;
    byte[] buffer = new byte[bufferLen];
    int bytesRead;
    do {
        // read a chunk of data from the input file
        bytesRead = fsIn.Read(buffer, 0, bufferLen);
        // Decrypt it
        cs.Write(buffer, 0, bytesRead);
    } while(bytesRead != 0);
    // close everything
    cs.Close(); // this will also close the unrelying fsOut stream
    fsIn.Close();
}

}</pre>

 本文由用戶 bdnp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!