MAC'ler, karmalar ve imzalar

Bu makalede ileti kimlik doğrulama kodlarının (MAC), karmaların ve imzaların WinUI uygulamalarında iletinin kurcalandığını algılamak için nasıl kullanılabileceğini anlatılmaktadır.

İleti kimlik doğrulama kodları (MAC)

Şifreleme, yetkisiz bir kişinin iletiyi okumasını önlemeye yardımcı olur, ancak bu kişinin iletiyle oynamasını engellemez. Değiştirilmiş bir ileti, değişiklik sadece saçmalıkla sonuçlanmasa bile, gerçek maliyetlere sahip olabilir. İleti kimlik doğrulama kodu (MAC), ileti manipülasyonunu önlemeye yardımcı olur. Örneğin, şu senaryoyu inceleyin:

  • Bob ve Alice gizli bir anahtar paylaştı ve kullanmak için bir MAC işlevi üzerinde anlaştılar.
  • Bob bir ileti oluşturur ve MAC değerini almak için iletiyi ve gizli anahtarı bir MAC işlevine girer.
  • Bob , [şifrelenmemiş] iletisini ve MAC değerini bir ağ üzerinden Alice'e gönderir.
  • Alice, MAC işlevinin girişi olarak gizli anahtarı ve iletiyi kullanır. Oluşturulan MAC değerini Bob tarafından gönderilen MAC değeriyle karşılaştırır. Bunlar aynıysa, ileti aktarım sırasında değiştirilmemiştir.

Bob ve Alice arasındaki konuşmaya kulak misafiri olan üçüncü taraf Eve'in iletiyi etkili bir şekilde işleyemeyeceğini unutmayın. Eve'nin özel anahtara erişimi yoktur ve dolayısıyla üzerinde oynanan iletinin Alice için meşru görünmesini sağlayacak bir MAC değeri oluşturamaz.

İleti kimlik doğrulama kodu oluşturmak yalnızca özgün iletinin değiştirilmemesini ve paylaşılan gizli anahtar kullanılarak ileti karmasının bu özel anahtara erişimi olan biri tarafından imzalanmasını sağlar.

Kullanılabilir MAC algoritmalarını listelemek ve simetrik anahtar oluşturmak için MacAlgorithmProvider'ı kullanabilirsiniz. MAC değerini oluşturan gerekli şifrelemeyi gerçekleştirmek için CryptographicEngine sınıfında statik yöntemler kullanabilirsiniz.

Dijital imzalar, özel anahtar iletisi kimlik doğrulama kodlarının (NIC) ortak anahtar eşdeğeridir. MAC'ler ileti alıcısının iletim sırasında iletinin değiştirilmediğini doğrulamasını sağlamak için özel anahtarlar kullansa da, imzalar özel/ortak anahtar çifti kullanır.

Bu örnek kod, karma ileti kimlik doğrulama kodu (HMAC) oluşturmak için MacAlgorithmProvider sınıfının nasıl kullanılacağını gösterir.

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.");
            }
        }
    }
}

Hashes

Şifreleme karma işlevi rastgele uzun bir veri bloğu alır ve sabit boyutlu bir bit dizesi döndürür. Karma işlevler genellikle verileri imzalarken kullanılır. Çoğu ortak anahtar imzası işlemi işlem açısından yoğun olduğundan, bir ileti karması imzalamak (şifrelemek) genellikle özgün iletiyi imzalamaktan daha verimlidir. Aşağıdaki yordam, basitleştirilmiş olsa da yaygın bir senaryoyu temsil eder:

  • Alice'in ortak/özel anahtar çifti var ve Bob'a imzalı bir ileti göndermek istiyor.
  • Alice bir mesaj oluşturur ve bir karma işlevi kullanarak mesajın karmasını hesaplar.
  • Alice özel anahtarını kullanarak karmayı imzalar ve [şifrelenmemiş] iletisini ve imzayı bir ağ üzerinden Bob'a gönderir.
  • Bob, alınan iletinin karmasını aynı karma işlevini kullanarak hesaplar. Ardından imzanın doğruluğunu doğrulamak için Alice'in ortak anahtarını kullanır ve bunu hesaplanan karma değeriyle karşılaştırır. Bunlar aynıysa, ileti aktarım sırasında değiştirilmedi ve Alice'ten geldi.

Alice'in şifrelenmemiş bir ileti gönderdiğini unutmayın. Yalnızca hash şifrelendi. Yordam yalnızca özgün iletinin değiştirilmemesini ve Alice'in ortak anahtarını kullanarak ileti karmasının Alice'in özel anahtarına (büyük olasılıkla Alice) erişimi olan biri tarafından imzalanmasını sağlar.

Kullanılabilir karma algoritmalarını listelemek ve bir CryptographicHash değeri oluşturmak için HashAlgorithmProvider sınıfını kullanabilirsiniz.

Dijital imzalar, özel anahtar iletisi kimlik doğrulama kodlarının (NIC) ortak anahtar eşdeğeridir. MAC'ler ileti alıcısının iletim sırasında iletinin değiştirilmediğini doğrulamasını sağlamak için özel anahtarlar kullanırken, imzalar özel/ortak anahtar çifti kullanır.

CryptographicHash nesnesi, her kullanım için nesneyi yeniden oluşturmak zorunda kalmadan farklı verileri art arda karma yapmak için kullanılabilir. Append yöntemi, karması oluşturulacak bir tampon belleğe yeni veriler ekler. GetValueAndReset yöntemi verileri karma hale getirir ve nesneyi başka bir kullanım için sıfırlar. Bu, aşağıdaki örnek tarafından gösterilmiştir.

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);
}

Dijital imzalar

Dijital imzalar, özel anahtar iletisi kimlik doğrulama kodlarının (NIC) ortak anahtar eşdeğeridir. MAC'ler ileti alıcısının iletim sırasında iletinin değiştirilmediğini doğrulamasını sağlamak için özel anahtarlar kullanırken, imzalar özel/ortak anahtar çifti kullanır.

Ancak çoğu ortak anahtar imzası işlemi işlem açısından yoğun olduğundan, bir ileti karması imzalamak (şifrelemek) genellikle özgün iletiyi imzalamaktan daha verimlidir. Gönderen bir ileti karması oluşturur, imzalar ve hem imzayı hem de (şifrelenmemiş) iletiyi gönderir. Alıcı, mesaj üzerinde bir hash hesaplar, imzanın şifresini çözer ve elde edilen imzayı hash değeriyle karşılaştırır. Eşleşirse, alıcı iletinin gönderenden geldiğinden ve iletim sırasında değiştirilmediğinden oldukça emin olabilir.

İmzalama yalnızca özgün iletinin değiştirilmemesini ve gönderenin ortak anahtarını kullanarak ileti karmasının özel anahtara erişimi olan biri tarafından imzalanmasını sağlar.

Kullanılabilir imza algoritmalarını listelemek ve bir anahtar çifti oluşturmak veya içeri aktarmak için Bir AsymmetricKeyAlgorithmProvider nesnesi kullanabilirsiniz. İletiyi imzalamak veya imzayı doğrulamak için CryptographicHash sınıfında statik yöntemler kullanabilirsiniz.