簡體   English   中英

手動解密使用MachineKey.Protect加密的數據

[英]Manually decrypt data encrypted with MachineKey.Protect

我正在嘗試手動解密使用MachineKey.Protect()加密的數據。 我正在使用AES和SHA1算法。

        // unencrypted input in HEX: 010203
        // AES key in HEX: CCA0DC9874B3F9E679E0A576F77EDF9B121CAB2F9A363A4EAF99976F7B51FA89
        // want to decrypt this: A738E5F98920E37AB14C5F4332D4C7F0EC683680AAA0D34B806E75DECF04B7A3DB651E688B563F77BA107FB15990C88FB8023386

這是一個例子。

        // Some input data
        var input = new byte[] { 1, 2, 3 };

        // this just works fine
        var protectedData = System.Web.Security.MachineKey.Protect(input, "ApplicationCookie", "v1");

        // protectedData  in hex: A738E5F98920E37AB14C5F4332D4C7F0EC683680AAA0D34B806E75DECF04B7A3DB651E688B563F77BA107FB15990C88FB8023386

        // works
        var unprotectedInput = System.Web.Security.MachineKey.Unprotect(protectedData, "ApplicationCookie", "v1");

        // now lets do it manually
        // in web.config machineKey is configured: AES and SHA1

        var algorithm = new AesManaged();
        algorithm.Padding = PaddingMode.PKCS7;
        algorithm.Mode = CipherMode.CBC;
        algorithm.KeySize = 256;
        algorithm.BlockSize = 128;
        var validationAlgorithm = new HMACSHA1();

        // this is the key from web.config
        var key = HexToBinary("CCA0DC9874B3F9E679E0A576F77EDF9B121CAB2F9A363A4EAF99976F7B51FA89");

        using (SymmetricAlgorithm encryptionAlgorithm = algorithm)
        {
            encryptionAlgorithm.Key = key;
            int offset = encryptionAlgorithm.BlockSize / 8; //16
            int buffer1Count = validationAlgorithm.HashSize / 8; // 20
            int count = checked(protectedData.Length - offset - buffer1Count); // 16
            byte[] numArray = new byte[offset];
            Buffer.BlockCopy((Array)protectedData, 0, (Array)numArray, 0, numArray.Length);
            encryptionAlgorithm.IV = numArray; // in HEX: A738E5F98920E37AB14C5F4332D4C7F0
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (ICryptoTransform decryptor = encryptionAlgorithm.CreateDecryptor())
                {
                    using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(protectedData, offset, count);

                        // Padding is invalid and cannot be removed.
                        cryptoStream.FlushFinalBlock();
                        var result = memoryStream.ToArray();
                    }
                }
            }
        }

我收到一個異常(填充不正確)。

我不知道還有什么嘗試...

這是MachineKey.Protect的代碼, https: //msdn.microsoft.com/cs-cz/library/system.web.security.machinekey.protect( v = vs.110).aspx

    public byte[] Protect(byte[] clearData)
    {
      // this is AESManaged
      using (SymmetricAlgorithm encryptionAlgorithm = this._cryptoAlgorithmFactory.GetEncryptionAlgorithm())
      {
        // this is our key
        encryptionAlgorithm.Key = this._encryptionKey.GetKeyMaterial();
        if (this._predictableIV)
          encryptionAlgorithm.IV = CryptoUtil.CreatePredictableIV(clearData, encryptionAlgorithm.BlockSize);
        else
          encryptionAlgorithm.GenerateIV();
        byte[] iv = encryptionAlgorithm.IV;
        using (MemoryStream memoryStream = new MemoryStream())
        {
          memoryStream.Write(iv, 0, iv.Length);
          using (ICryptoTransform encryptor = encryptionAlgorithm.CreateEncryptor())
          {
            using (CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Write))
            {
              cryptoStream.Write(clearData, 0, clearData.Length);
              cryptoStream.FlushFinalBlock();
              using (KeyedHashAlgorithm validationAlgorithm = this._cryptoAlgorithmFactory.GetValidationAlgorithm())
              {
                validationAlgorithm.Key = this._validationKey.GetKeyMaterial();
                byte[] hash = validationAlgorithm.ComputeHash(memoryStream.GetBuffer(), 0, checked ((int) memoryStream.Length));
                memoryStream.Write(hash, 0, hash.Length);
                return memoryStream.ToArray();
              }
            }
          }
        }
      }
    }

解密密鑰錯誤。

MachineKey.Protect / UnProtect()在使用密鑰之前先對其進行修改。

它正在做這樣的事情:

            public static byte[] DeriveKey(byte[] key, int keySize, string primaryPurpose, params string[] specificPurposes)
            {
                var secureUtf8Encoding = new UTF8Encoding(false, true);
                var hash = new HMACSHA512(key);

                using (hash)
                {
                    var label = secureUtf8Encoding.GetBytes(primaryPurpose);

                    byte[] context;

                    using (var memoryStream = new MemoryStream())
                    {
                        using (var binaryWriter = new BinaryWriter(memoryStream, secureUtf8Encoding))
                        {
                            foreach (var str in specificPurposes)
                                binaryWriter.Write(str);
                            context = memoryStream.ToArray();
                        }
                    }

                    return DeriveKeyImpl(hash, label, context, keySize);
                }
            }

            public static byte[] DeriveKeyImpl(HMAC hmac, byte[] label, byte[] context, int keyLengthInBits)
            {
                int count1 = label != null ? label.Length : 0;
                int count2 = context != null ? context.Length : 0;
                byte[] buffer = new byte[checked(4 + count1 + 1 + count2 + 4)];
                if (count1 != 0)
                    Buffer.BlockCopy((Array)label, 0, (Array)buffer, 4, count1);
                if (count2 != 0)
                    Buffer.BlockCopy((Array)context, 0, (Array)buffer, checked(5 + count1), count2);
                WriteUInt32ToByteArrayBigEndian(checked((uint)keyLengthInBits), buffer, checked(5 + count1 + count2));
                int dstOffset = 0;
                int val1 = keyLengthInBits / 8;
                byte[] numArray = new byte[val1];
                uint num = 1;
                while (val1 > 0)
                {
                    WriteUInt32ToByteArrayBigEndian(num, buffer, 0);
                    byte[] hash = hmac.ComputeHash(buffer);
                    int count3 = Math.Min(val1, hash.Length);
                    Buffer.BlockCopy((Array)hash, 0, (Array)numArray, dstOffset, count3);
                    checked { dstOffset += count3; }
                    checked { val1 -= count3; }
                    checked { ++num; }
                }
                return numArray;
            }

指定正確的目的非常重要。 對於標准MachineKey.Protect,主要原因是“ User.MachineKey.Protect”。 此示例的密鑰大小為256(以位為單位)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM