65.9K
CodeProject 正在变化。 阅读更多。
Home

使用高级加密标准 (AES) 和安全断言标记语言 (SAML) 进行 Web 安全

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.99/5 (26投票s)

2019 年 4 月 3 日

CPOL

13分钟阅读

viewsIcon

83779

downloadIcon

800

在 Web 上传输用户信息时获得更安全通道的最佳方法。

密码学

网络上大多数问题都与安全有关,因为需要在网络上保存和传输敏感数据。因此,我们必须在其上提供一个安全的系统。在网络上建立安全连接最流行和实用的方法是密码学技术。密码学技术是加密和解密数据的过程,以确保数据安全。例如,在下面的图中,Bob想将数据发送给Alice。这些数据被称为消息,是密码学过程的输入参数。然后,一个特定的密钥与加密函数一起添加到此消息中,生成密文,即我们加密的消息,因此这条消息会通过网络,而黑客正在等待抢劫这些数据。

在另一阶段,Alice等待接收Bob的消息,在那一侧,有一个解密函数,它使用相同的密钥来解密消息。这个密钥与Bob那边的密钥是完全相同的。因此,解密函数使用相同的密钥和密文(加密密钥)将生成解密后的消息给Alice,最终Alice将收到Bob的消息。这个过程被称为对称加密。

这个过程中最大的问题是提供一个强大而复杂的密钥。因为加密和解密算法在互联网上都可以找到,并且使用几乎相似的步骤和函数来加密数据,所以更改这些算法是无用的,因为黑客可以很容易地找到它们。因此,我们必须专注于生成强大的密钥来保护机密数据。

  1. 密码学是任何安全问题的强大而绝妙的工具。
  2. 但密码学不适合普通用户采取行动伤害自己,尤其是对于社交攻击者。
  3. 密码学需要创新新的方法,因为使用旧的加密系统就像不使用它一样糟糕。
  4. 如果密码学实现不当,则无法正确满足您的要求。
一些安全通信解决方案
  1. Web流量:HTTPS -> 安全套接字层 (SSL/TLS)
  2. 无线流量:GSM:802.11 或 WPA2:蓝牙
  3. 磁盘文件加密

高级加密标准 (AES)

AES是使用相同密钥的密码学技术之一,基于Rijndael密码算法。AES基于替换和置换函数,并使用复杂的方法生成强大且几乎不可破解的密钥,这是我们通过网络传输敏感数据的目标。

在第一步,AES将128位密钥扩展为十多个密钥,每个密钥都有128位长度,生成的密钥构建变体循环。消息作为输入参数将与这些密钥混合。AES仅在K0中使用“AddRoundKey”函数,在Kn中使用“SubBytes”、“Shiftrows”和“AddRoundKey”,而在AES的K2到Kn-1中则使用所有四个函数“AddRoundKey”、“SubBytes”、“Shiftrows”和“AddRoundKey”。最终,消息或明文将经过这些复杂的函数,转换为加密消息或密文。

AES使用这种模式的逆运算从加密消息生成相同的消息。AES将消息文本和密钥转换为四乘四的矩阵,因为使用矩阵形式比原始形式更容易处理。请看下图,以便更清晰地想象AES算法内部发生的事情。

AddRoundKey

此函数通过XOR函数混合Ki,j和Mi,j。这意味着AES从消息和密钥中提取第i行和第j列,并对这些对应的行和列应用XOR函数,生成Ci,j。在下面的图片中,XOR将被应用于蓝色密钥和红色消息以生成橙色密文。

SubBytes

此函数从具有特定模式和步骤的替换表中查找Mi,j的替换,并将其替换为M~i,j。这意味着AES从消息中提取第i行和第j列,并对消息矩阵的每一行和每一列应用替换函数,生成密文矩阵Ci,j

MixColumns

有一个固定的矩阵C,它会影响消息矩阵。在第一步,它不会改变第一行,但会将第二行向左移,并将第三行向左移,同时对其应用XOR函数。

Shift Rows

此函数提取消息矩阵,并且不改变该矩阵的第一行。之后,对于第二行,向左移动一个单元格,使M1,0被替换为M1,3。对于第三行,向左移动两个单元格,对于第四行,向左移动三个单元格。

我画了下面的图片来更深入地了解AES内部的操作。有DES和3DES算法,它们几乎与AES相似,区别在于3DES是168位的,比AES多一些比特,但它只使用置换函数来生成密钥,而AES同时使用置换和替换函数,并且比3DES耗时更少。

我的网络安全解决方案

我想提出一个包含身份验证和授权部分的解决方案,用于识别用户。身份验证通过获取用户名和密码来确定用户声明是否正确。有一个解决方案可以将此部分设置为两步验证,首先是获取密码,其次是生物识别。在这种情况下,如果有人窃取了用户的密码,黑客就无法访问该用户的个人资料。

下一部分是授权,它与权限管理有关,并确定特定角色是否有权访问和查看特定部分。例如,在这里(在电子健康系统EHealth Care System中),医生有权访问其患者的健康信息,并阅读或写入EHR。

第三部分是密码学技术(AES)。如上所述,AES使用不同的函数来加密数据以防止黑客。因此,数据库中的数据可以以加密文本而不是明文的形式保存,以提高安全性。

我的解决方案的更多描述

我的解决方案是使用生物识别信息,并将其与密钥混合,以生成更强大、更安全的AES密钥。这个生物识别密钥可以从指纹或角膜识别中提取。如今,通过iPhone等手机可以捕捉指纹,这些数据可以转换为第二个密钥矩阵,并与密钥混合,我们就拥有了强大的密钥。这些识别信息始终存在于我们身边,我们不会忘记它们,黑客也无法获取它们,因此这是一个保持数据机密性的好解决方案。

如何使用和实现代码

首先,打开Visual Studio 2013 -> 文件(菜单) -> 新建项目 -> ASP.NET MVC -> 空控制器 -> 添加新控制器

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;

namespace WebSecurity.Controllers
{
    public class AESController : Controller
    {
        //
        // GET: /AES/

        public ActionResult Index()
        {
            ViewData["Encrypted"] = TempData["TEncrypted"];
            ViewData["Decrypted"] = TempData["TDecrypted"];
            return View();
        }

        //txtforEN is PlainText
        //Key is Public Secret Key 
        [HttpPost]
        public ActionResult Encryption(string Text, string Key)
        {
            // Convert String to Byte

            byte[] MsgBytes = Encoding.UTF8.GetBytes(Text);
            byte[] KeyBytes = Encoding.UTF8.GetBytes(Key);

            // Hash the password with SHA256
            //Secure Hash Algorithm
            //Operation And, Xor, Rot,Add (mod 232),Or, Shr
            //block size 1024
            //Rounds 80
            //rotation operator , rotates point1 to point2 by theta1=> p2=rot(t1)p1
            //SHR shift to right
            KeyBytes = SHA256.Create().ComputeHash(KeyBytes);

            byte[] bytesEncrypted = AES_Encryption(MsgBytes, KeyBytes);

            string encryptionText = Convert.ToBase64String(bytesEncrypted);

            TempData["TEncrypted"] = encryptionText;
            return RedirectToAction("Index");
        }

        public byte[] AES_Encryption(byte[] Msg, byte[] Key)
        {
            byte[] encryptedBytes = null;

            //salt is generated randomly as an additional number to 
            //hash password or message in order o dictionary attack
            //against pre computed rainbow table
            //dictionary attack is a systematic way to test 
            //all of possibilities words in dictionary weather or not is true?
            //to find decryption key
            //rainbow table is precomputed key for cracking password
            // Set your salt here, change it to meet your flavor:
            // The salt bytes must be at least 8 bytes.  == 16 bits
            byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    var key = new Rfc2898DeriveBytes(Key, saltBytes, 1000);
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);

                    AES.Mode = CipherMode.CBC;

                    using (var cs = new CryptoStream
                          (ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(Msg, 0, Msg.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }

            return encryptedBytes;
        }

        [HttpPost]
        public ActionResult Decryption(string Text2, string Key2)
        {
            // Convert String to Byte
            byte[] MsgBytes = Convert.FromBase64String(Text2);
            byte[] KeyBytes = Encoding.UTF8.GetBytes(Key2);
            KeyBytes = SHA256.Create().ComputeHash(KeyBytes);

            byte[] bytesDecrypted = AES_Decryption(MsgBytes, KeyBytes);

            string decryptionText = Encoding.UTF8.GetString(bytesDecrypted);

            TempData["TDecrypted"] = decryptionText;
            return RedirectToAction("Index");
        }

        public byte[] AES_Decryption(byte[] Msg, byte[] Key)
        {
            byte[] decryptedBytes = null;

            // Set your salt here, change it to meet your flavor:
            // The salt bytes must be at least 8 bytes.
            byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    var key = new Rfc2898DeriveBytes(Key, saltBytes, 1000);
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);

                    AES.Mode = CipherMode.CBC;

                    using (var cs = new CryptoStream
                          (ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(Msg, 0, Msg.Length);
                        cs.Close();
                    }
                    decryptedBytes = ms.ToArray();
                }
            }

            return decryptedBytes;
        }
    }
}

右键单击Index(Action)-> 选择“添加视图”。

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>Encryption And Decryption</h2>
 
<div style="color:red;" id="EncryptedText"
>Encrypted Message: @ViewData["Encrypted"]</div>
 
<div style="color:red;" id="DecryptedText"
>Decrypted Message: @ViewData["Decrypted"]</div>
 
<pre>
@using(Html.BeginForm("Encryption", "AES", FormMethod.Post))
{
     &lt;label id="lbk1">Key:&lt;/label>
     &lt;input name="Key" id="Key" type="text" />
    <br />
<br />
     &lt;label id="lbk2">Message:&lt;/label>
     &lt;input name="Text" id="Text" type="text" />
    <br />
<br />
    &lt;input id="btnEncryption" type="submit" value="Encryption" />
    <br />  
    <br />          
}

如何测试应用程序

用于加密

  1. 输入密钥,例如:Key=122
  2. 输入消息:Message=Mahsa
  3. 按“加密”按钮
  4. 您将看到密文 --> Encrypted Message: 7gkI7SpPzsOiJ8O2OO2jOQ==

用于解密

  1. 输入相同的密钥=“122
  2. 输入加密消息 --> 7gkI7SpPzsOiJ8O2OO2jOQ==
  3. 按“解密”按钮
  4. 您将看到:Decrypted Message: Mahsa

安全断言标记语言 (SAML)

SAML是基于XML的开放标准,它格式化数据,这些数据用于在身份提供者和服务提供者之间传输用户信息的加密数据。它包含一个包含此加密数据的特定标签。

<saml:Assertion ..> 
“includes important message from identity provider to service provider
“Who is this user (Attribute Identity)
 “Is he/she allowed to consume service?
</saml:Assertion>

当服务提供者通过安全通道直接调用身份提供者时,会请求SAML协议。SAML的流行用途是Web浏览器单点登录(SSO)。在此问题中,使用SAML会发生以下情况

  1. 请求目标资源

    用户在Chrome或Mozila等Web浏览器中,在地址栏中输入www.sample.com,例如:http://www.stackoverflow.com/,并发送请求以使用stackoverflow作为服务提供者的特定服务。该用户可以直接使用stack身份验证输入其用户名和密码,或者选择登录页面上的身份验证选项之一。

  2. 重定向到SSO服务

    假设用户在身份验证过程中选择Google作为身份验证选项,那么stackoverflow将把他/她从http://www.stackoverflow.com/重定向到https://#

  3. 请求SSO服务

    在此示例中,stackoverflow是为用户提供所需服务的服务提供者,而Google.com是为用户提供单点登录的身份提供者。Google通过请求属于用户的某些信息(如用户名和密码)来识别用户,并检查这些凭据是否有效。身份提供者使用LDAP、Radius和Active Directory等目录服务进行身份验证。

  4. 以XHTML表单响应

    在此阶段,用户应该在Google.com(作为身份提供者)内的接受按钮上按一下,以允许其部分信息(如用户名和电子邮件)传递给服务提供者。当他/她这样做时,身份提供者会以XHTML表单(如下代码)响应服务提供者。

    <form method="post" action="https://sp.example.com/SAML2/SSO/POST" ...>
        <input type="hidden" name="SAMLResponse" value="response" />
        <input type="submit" value="Submit" />
    </form>
  5. 请求断言消费者服务

    如果上述XHTML中,身份提供者允许用户从服务提供者那里消费服务,那么用户将被重定向到服务提供者,此时他/她是一个有效的用户,可以消费所需的任何服务。(尽管在此阶段,服务提供者会进行授权处理,以检查他/她消费每项服务的访问权限)。

  6. 重定向到目标资源

    在此阶段,服务提供者进行授权处理,以检查他/她消费每项服务的访问权限,然后用户将被重定向到目标资源。

  7. 请求目标资源

    用户向服务提供者请求特定资源,正如我上面提到的,如果服务提供者确认了权限,那么用户就可以使用它。例如http://astronomy.stackexchange.com/

  8. 响应请求的资源

    如果用户有权访问该服务,那么服务提供者将用户重定向到资源。

词典

在本节中,我解释了一些需要进一步描述的特定词汇。这一部分可以解决误解,并阐明我在写作风格中使用这些词汇的意图。

XML

可扩展标记语言 (XML) 是一种标记语言,它包含特定的规则来编码和格式化文档,使其对人类和机器都可读。XML对于在Web应用程序和服务上组织不同类型的数据结构和人类语言非常有用。

XML有规则来定义如何安排我们的内容。它包括标签,如“<div></div>”,属性,如“<div class=”class1”></div>”中的class属性,最后,我们的数据位于标签内,例如“<div class=”class1”>Hello</div>”中的“Hello”,其声明以<?xml version="1.0" encoding="UTF-8"?>开头。

安全令牌

安全令牌是一种生成密钥用于身份验证过程的设备。它是一个附加工具,用于提供高安全性,以检测用户是否真的是声称的那个人。它是一种设备,如密钥生成器、USB连接器、蓝牙无线设备。它存储用于密码学问题(加密和解密功能)的密钥,该密钥可以是生物识别信息,如指纹或数字签名。这个密钥与特定的密码学函数一起可以生成一个新的数字,用户在输入用户名和密码后输入这个数字。这个密钥证明了用户的声称,他/她是否真的是声称的那个人。在图中,用户应该输入用户名和密码,然后按下设备上的密钥,输入密码“54392971”,然后点击“登录”。

服务提供者

服务提供者是指提供一系列服务的公司的公司。这些服务分为电信、应用程序、存储空间和互联网。

身份提供者

身份提供者是第三方,位于身份验证过程的两个部分(消费者作为用户,服务提供者作为供应商)之外,用于检测用户是否是授权用户,并将用户的某些重要信息提供给服务提供者,最终授权用户有权消费服务。

例如,stackoverflow.com是一个供应商(服务提供者),您可以在相关部分提出问题。如果用户想要登录该网站,它有一些选项可以做到,例如使用Google、Facebook、Yahoo、LiveJournal、WordPress、Blogger、Verisign和AOL登录,或者通过stackoverflow登录。如果用户选择stackoverflow,那么他/她应该为该网站创建用户名和密码,并再次在此输入所有重复信息。每当用户选择其他选项(即身份提供者)时,他/她将被从stackoverflow重定向到这些网站,并向它们输入特定的用户名和密码,然后这些网站将决定该用户是否有效?如果用户有效,那么用户的电子邮件地址等信息将被传递给stackoverflow网站。这个故事中重要的安全问题是,身份提供者(IP)不会发现这个人将要做什么操作,用户的隐私将受到保护。

重定向到Google进行身份验证(使用Google帐户登录Stackoverflow.com)。

LDAP

轻量级目录访问协议(LDAP)是一种互联网协议。LDAP通过为每个数据建立索引并仅过滤所需的特定项目来查找信息。

Active Directory

Active Directory是基于Windows域的目录服务,提供身份验证和授权服务。用户登录到Windows域中的计算机,Active Directory通过LDAP检查提交的密码,如果用户名和密码具有访问权限,则Active Directory允许其使用所需的任何服务。

Windows域

Windows域是一种网络,其中所有用户、计算机及其外围设备都在中央计算机上注册。

联合身份提供者

联合身份是一项技术,用于在用户身份(用户名和密码)与其他身份管理系统之间建立链接,以验证用户并通知源节点用户是有效的。这意味着您只有一个用户名和密码,就可以在多个网站上有效。单点登录是联合身份的子集。

U-Prove

U-Prove是一种密码学技术,它会揭示最少关于想要访问多个网站的用户的信息,尤其是在用户与身份提供者交互时。U-Prove使得追踪用户想要做什么变得困难。U-Prove令牌用两个特性加密信息。首先,信息的加密“包装”没有相关性会处理,从而避免了用户跟踪。其次,用户在验证者策略过程中披露最少的信息,例如“年龄”,而无需明确透露“出生日期”。

OpenID

OpenID是一种协议,它允许用户通过其他称为“信赖方”的网站(如Google、Microsoft、Facebook、AOL等第三方)继续其身份验证过程。

无状态和有状态

无状态是一种通信协议,它在客户端和服务器之间建立独立的请求和响应。它不需要服务器保留有关请求者和响应者之间通信的信息,而有状态则需要服务器保留有关其状态的信息。互联网协议(IP)是互联网的基础,超文本传输协议(HTTP)是Web上数据通信的基础,这些都是无状态的例子。传输控制协议(TCP)是有状态的例子,它在客户端和服务器之间提供可靠的、经过错误检查的通信。

结论

我在我的应用程序中使用了最流行的密码学技术之一,即AES。AES是一种对称加密函数,在发送方和接收方使用相同的密钥,AES生成强大的密钥,黑客无法破解。因此,AES是保持数据机密性和完整性的好方法。

历史

  • 2015年8月31日:第一个版本

反馈

欢迎就本文提出任何反馈;很高兴看到您的意见和对该代码的投票。如果您有任何疑问,请随时在此提问。

通过高级加密标准 (AES) 和安全断言标记语言 (SAML) 在 Web 上实现安全 - CodeProject - 代码之家
© . All rights reserved.