Расширение класса KeyedHashAlgorithm

Криптографические классы, предоставляемые платформой .NET Framework, имеют широкие возможности расширения. В данном разделе приводится пример того, как можно расширить эти криптографические классы путем создания класса хэш-алгоритма с ключом, который реализует хэш-алгоритм MD5.

Хэш-алгоритм с ключом — это зависящая от ключа, однонаправленная хэш-функция, используемая в качестве кода подлинности сообщения. .NET Framework предоставляет два таких класса хэш-алгоритма с ключом (HMACSHA1 и MACTripleDES), которые являются производными от абстрактного класса KeyedHashAlgorithm Class. Если необходимо создать класс хэш-алгоритма с ключом, реализующий хэш-алгоритм, отличный от предоставляемых .NET Framework, можно создать новый класс, производный от KeyedHashAlgorithm и использующий необходимый алгоритм.

В следующем примере создается новый класс хэш-алгоритма с ключом, который использует хэш-алгоритм MD5. Поскольку этот класс наследуется от класса KeyedHashAlgorithm, он может быть легко использован с другими управляемыми криптографическими классами, такими как класс CryptoStream.

using System;
using System.Security.Cryptography;

public class TestHMACMD5 
{
    static private void PrintByteArray(Byte[] arr) 
    {
        int i;
        Console.WriteLine("Length: " + arr.Length);
        for (i=0; i<arr.Length; i++) 
        {
            Console.Write("{0:X}", arr[i]);
            Console.Write("    ");
            if ( (i+9)%8 == 0 ) Console.WriteLine();
        }
        if (i%8 != 0) Console.WriteLine();
    }
    public static void Main() 
    {
        // Create a key.
        byte[] key1 = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b};
        // Pass the key to the constructor of the HMACMD5 class.  
        HMACMD5 hmac1 = new HMACMD5(key1);

        // Create another key.
        byte[] key2 = System.Text.Encoding.ASCII.GetBytes("KeyString");     
        // Pass the key to the constructor of the HMACMD5 class.  
        HMACMD5 hmac2 = new HMACMD5(key2);

        // Encode a string into a byte array, create a hash of the array,
        // and print the hash to the screen.
        byte[] data1 = System.Text.Encoding.ASCII.GetBytes("Hi There");
        PrintByteArray(hmac1.ComputeHash(data1));

        // Encode a string into a byte array, create a hash of the array,
        // and print the hash to the screen.
        byte[] data2 = System.Text.Encoding.ASCII.GetBytes("This data will be hashed.");
        PrintByteArray(hmac2.ComputeHash(data2));
    }
}
public class HMACMD5 : KeyedHashAlgorithm 
{
    private MD5            hash1;
    private MD5            hash2;
    private bool            bHashing = false;

    private byte[]          rgbInner = new byte[64];
    private byte[]          rgbOuter = new byte[64];

    public HMACMD5 (byte[] rgbKey) 
    {
        HashSizeValue = 128;
        // Create the hash algorithms.
        hash1 = MD5.Create();
        hash2 = MD5.Create();
        // Get the key.
        if (rgbKey.Length > 64) 
        {
            KeyValue = hash1.ComputeHash(rgbKey);
            // No need to call Initialize; ComputeHash does it automatically.
        }
        else 
        {
            KeyValue = (byte[]) rgbKey.Clone();
        }
        // Compute rgbInner and rgbOuter.
        int i = 0;
        for (i=0; i<64; i++) 
        { 
            rgbInner[i] = 0x36;
            rgbOuter[i] = 0x5C;
        }
        for (i=0; i<KeyValue.Length; i++) 
        {
            rgbInner[i] ^= KeyValue[i];
            rgbOuter[i] ^= KeyValue[i];
        }        
    }    

    public override byte[] Key 
    {
        get { return (byte[]) KeyValue.Clone(); }
        set 
        {
            if (bHashing) 
            {
                throw new Exception("Cannot change key during hash operation");
            }
            if (value.Length > 64) 
            {
                KeyValue = hash1.ComputeHash(value);
                // No need to call Initialize; ComputeHash does it automatically.
            }
            else 
            {
                KeyValue = (byte[]) value.Clone();
            }
            // Compute rgbInner and rgbOuter.
            int i = 0;
            for (i=0; i<64; i++) 
            { 
                rgbInner[i] = 0x36;
                rgbOuter[i] = 0x5C;
            }
            for (i=0; i<KeyValue.Length; i++) 
            {
                rgbInner[i] ^= KeyValue[i];
                rgbOuter[i] ^= KeyValue[i];
            }
        }
    }
    public override void Initialize() 
    {
        hash1.Initialize();
        hash2.Initialize();
        bHashing = false;
    }
    protected override void HashCore(byte[] rgb, int ib, int cb) 
    {
        if (bHashing == false) 
        {
            hash1.TransformBlock(rgbInner, 0, 64, rgbInner, 0);
            bHashing = true;                
        }
        hash1.TransformBlock(rgb, ib, cb, rgb, ib);
    }

    protected override byte[] HashFinal() 
    {
        if (bHashing == false) 
        {
            hash1.TransformBlock(rgbInner, 0, 64, rgbInner, 0);
            bHashing = true;                
        }
        // Finalize the original hash.
        hash1.TransformFinalBlock(new byte[0], 0, 0);
        // Write the outer array.
        hash2.TransformBlock(rgbOuter, 0, 64, rgbOuter, 0);
        // Write the inner hash and finalize the hash.
        hash2.TransformFinalBlock(hash1.Hash, 0, hash1.Hash.Length);
        bHashing = false;
        return hash2.Hash;
    }        
}

В данном примере осуществляется расширение класса KeyedHashAlgorithm с целью использования хэш-алгоритма MD5 в классе HMACMD5. При выполнении вышеприведенного кода создаются два экземпляра класса HMACMD5 с передачей их конструкторам различных ключей. Затем осуществляется хэширование двух строк и вывод на консоль следующей информации.

Length: 16
92    94    72    7A    36    38    BB    1C
13    F4    8E    F8    15    8B    FC    9D
Length: 16
1    10    3A    9    C2    10    6E    E1
1    13    9B    7D    DA    EA    A3    EC
Была ли вам полезна эта информация?
(1500 символов осталось)
Спасибо за ваш отзыв

Добавления сообщества

ДОБАВИТЬ
Корпорация Майкрософт проводит интернет-опрос, чтобы выяснить ваше мнение о веб-сайте MSDN. Если вы желаете принять участие в этом интернет-опросе, он будет отображен при закрытии веб-сайта MSDN.

Вы хотите принять участие?
Показ:
© 2015 Microsoft