Поделиться через


Коды аутентификации сообщений, хэши и подписи

В этой статье описывается, как коды проверки подлинности сообщений (MACs), хэши и подписи можно использовать в приложениях универсальная платформа Windows (UWP) для обнаружения изменения сообщений.

Коды проверки подлинности сообщений (MACs)

Шифрование помогает предотвратить несанкционированное чтение сообщения, но это не препятствует тому, чтобы пользователь не несанкционированно перенаправлял сообщение. Измененное сообщение, даже если изменение не приводит ни к чему, кроме енсенса, может иметь реальные затраты. Код проверки подлинности сообщений (MAC) помогает предотвратить изменение сообщений. Давайте рассмотрим следующий пример:

  • Боб и Алиса делятся секретным ключом и согласны с функцией MAC использовать.
  • Боб создает сообщение и вводит сообщение и секретный ключ в функцию MAC для получения значения MAC.
  • Боб отправляет сообщение [незашифровано] и значение MAC в Алису по сети.
  • Алиса использует секретный ключ и сообщение в качестве входных данных для функции MAC. Она сравнивает созданное значение MAC со значением MAC, отправленным Бобом. Если они одинаковы, сообщение не было изменено при передаче.

Обратите внимание, что Ева, сторонняя сторона перехватывает разговор между Бобом и Алиса, не может эффективно управлять сообщением. Ева не имеет доступа к закрытому ключу и не может, следовательно, создать значение MAC, которое приведет к незаконному отображению сообщения Алиса.

Создание кода проверки подлинности сообщения гарантирует, что исходное сообщение не было изменено и, используя общий секретный ключ, хэш сообщения был подписан кем-то с доступом к этому закрытому ключу.

Можно использовать MacAlgorithmProvider для перечисления доступных алгоритмов MAC и создания симметричного ключа. Статические методы можно использовать в классе CryptographicEngine для выполнения необходимого шифрования, создающего значение MAC.

Цифровые подписи являются эквивалентом открытого ключа кодов проверки подлинности сообщений закрытого ключа (MACs). Хотя MACs используют закрытые ключи, чтобы разрешить получателю сообщения убедиться, что сообщение не было изменено во время передачи, подписи используют пару закрытых и открытых ключей.

В этом примере кода показано, как использовать класс MacAlgorithmProvider для создания кода проверки подлинности хэшированного сообщения (HMAC).

using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;

namespace SampleMacAlgorithmProvider
{
    sealed partial class MacAlgProviderApp : Application
    {
        public MacAlgProviderApp()
        {
            // Initialize the application.
            this.InitializeComponent();

            // Initialize the hashing process.
            String strMsg = "This is a message to be authenticated";
            String strAlgName = MacAlgorithmNames.HmacSha384;
            IBuffer buffMsg;
            CryptographicKey hmacKey;
            IBuffer buffHMAC;

            // Create a hashed message authentication code (HMAC)
            this.CreateHMAC(
                strMsg,
                strAlgName,
                out buffMsg,
                out hmacKey,
                out buffHMAC);

            // Verify the HMAC.
            this.VerifyHMAC(
                buffMsg,
                hmacKey,
                buffHMAC);
        }

        void CreateHMAC(
            String strMsg,
            String strAlgName,
            out IBuffer buffMsg,
            out CryptographicKey hmacKey,
            out IBuffer buffHMAC)
        {
            // Create a MacAlgorithmProvider object for the specified algorithm.
            MacAlgorithmProvider objMacProv = MacAlgorithmProvider.OpenAlgorithm(strAlgName);

            // Demonstrate how to retrieve the name of the algorithm used.
            String strNameUsed = objMacProv.AlgorithmName;

            // Create a buffer that contains the message to be signed.
            BinaryStringEncoding encoding = BinaryStringEncoding.Utf8;
            buffMsg = CryptographicBuffer.ConvertStringToBinary(strMsg, encoding);

            // Create a key to be signed with the message.
            IBuffer buffKeyMaterial = CryptographicBuffer.GenerateRandom(objMacProv.MacLength);
            hmacKey = objMacProv.CreateKey(buffKeyMaterial);

            // Sign the key and message together.
            buffHMAC = CryptographicEngine.Sign(hmacKey, buffMsg);

            // Verify that the HMAC length is correct for the selected algorithm
            if (buffHMAC.Length != objMacProv.MacLength)
            {
                throw new Exception("Error computing digest");
            }
         }

        public void VerifyHMAC(
            IBuffer buffMsg,
            CryptographicKey hmacKey,
            IBuffer buffHMAC)
        {
            // The input key must be securely shared between the sender of the HMAC and 
            // the recipient. The recipient uses the CryptographicEngine.VerifySignature() 
            // method as follows to verify that the message has not been altered in transit.
            Boolean IsAuthenticated = CryptographicEngine.VerifySignature(hmacKey, buffMsg, buffHMAC);
            if (!IsAuthenticated)
            {
                throw new Exception("The message cannot be verified.");
            }
        }
    }
}

хэш-коды;

Функция криптографического хэша принимает произвольный блок данных и возвращает битовую строку фиксированного размера. Хэш-функции обычно используются при подписи данных. Так как большинство операций подписи открытого ключа являются вычислительными, обычно более эффективно подписывать (шифровать) хэш сообщения, чем подписывать исходное сообщение. Следующая процедура представляет собой распространенный, хотя и упрощенный сценарий:

  • Боб и Алиса делятся секретным ключом и согласны с функцией MAC использовать.
  • Боб создает сообщение и вводит сообщение и секретный ключ в функцию MAC для получения значения MAC.
  • Боб отправляет сообщение [незашифровано] и значение MAC в Алису по сети.
  • Алиса использует секретный ключ и сообщение в качестве входных данных для функции MAC. Она сравнивает созданное значение MAC со значением MAC, отправленным Бобом. Если они одинаковы, сообщение не было изменено при передаче.

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

Класс HashAlgorithmProvider можно использовать для перечисления доступных хэш-алгоритмов и создания значения CryptographicHash.

Цифровые подписи являются эквивалентом открытого ключа кодов проверки подлинности сообщений закрытого ключа (MACs). В то время как MACs используют закрытые ключи для проверки того, что сообщение не было изменено во время передачи, подписи используют пару закрытого и открытого ключа.

Объект CryptographicHash можно использовать для многократного хэш-хэша разных данных без необходимости повторного создания объекта для каждого использования. Метод Append добавляет новые данные в буфер для хэширования. Метод GetValueAndReset хэширует данные и сбрасывает объект для другого использования. Это показано в следующем примере.

public void SampleReusableHash()
{
    // Create a string that contains the name of the hashing algorithm to use.
    String strAlgName = HashAlgorithmNames.Sha512;

    // Create a HashAlgorithmProvider object.
    HashAlgorithmProvider objAlgProv = HashAlgorithmProvider.OpenAlgorithm(strAlgName);

    // Create a CryptographicHash object. This object can be reused to continually
    // hash new messages.
    CryptographicHash objHash = objAlgProv.CreateHash();

    // Hash message 1.
    String strMsg1 = "This is message 1.";
    IBuffer buffMsg1 = CryptographicBuffer.ConvertStringToBinary(strMsg1, BinaryStringEncoding.Utf16BE);
    objHash.Append(buffMsg1);
    IBuffer buffHash1 = objHash.GetValueAndReset();

    // Hash message 2.
    String strMsg2 = "This is message 2.";
    IBuffer buffMsg2 = CryptographicBuffer.ConvertStringToBinary(strMsg2, BinaryStringEncoding.Utf16BE);
    objHash.Append(buffMsg2);
    IBuffer buffHash2 = objHash.GetValueAndReset();

    // Hash message 3.
    String strMsg3 = "This is message 3.";
    IBuffer buffMsg3 = CryptographicBuffer.ConvertStringToBinary(strMsg3, BinaryStringEncoding.Utf16BE);
    objHash.Append(buffMsg3);
    IBuffer buffHash3 = objHash.GetValueAndReset();

    // Convert the hashes to string values (for display);
    String strHash1 = CryptographicBuffer.EncodeToBase64String(buffHash1);
    String strHash2 = CryptographicBuffer.EncodeToBase64String(buffHash2);
    String strHash3 = CryptographicBuffer.EncodeToBase64String(buffHash3);
}

Цифровые подписи

Цифровые подписи являются эквивалентом открытого ключа кодов проверки подлинности сообщений закрытого ключа (MACs). В то время как MACs используют закрытые ключи для проверки того, что сообщение не было изменено во время передачи, подписи используют пару закрытого и открытого ключа.

Так как большинство операций подписи открытого ключа являются вычислительными, однако обычно более эффективно подписывать (шифровать) хэш сообщения, чем подписывать исходное сообщение. Отправитель создает хэш сообщения, подписывает его и отправляет как подпись, так и сообщение (незашифрованное). Получатель вычисляет хэш по сообщению, расшифровывает подпись и сравнивает расшифрованную подпись со значением хэша. Если они соответствуют, получатель может быть достаточно уверен, что сообщение сделал, на самом деле, исходит от отправителя и не было изменено во время передачи.

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

Объект AsymmetricKeyAlgorithmProvider можно использовать для перечисления доступных алгоритмов подписи и создания или импорта пары ключей. Статические методы можно использовать в классе CryptographicHash для подписи сообщения или проверки подписи.