加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

使用VB.NET的ASP.NET中的AES

发布时间:2020-12-17 00:02:58 所属栏目:大数据 来源:网络整理
导读:有关使用AES加密URL链接以使用VB.NET 2005将用户名传递到ASP.NET中的其他网站的好链接或文章是什么? 仅供参考:接收网站将有权访问私钥以进行解密. 第一 不要这样做!编写自己的加密系统很容易导致出错.最好使用现有系统,如果没有,请让知道密码学的人去做.
有关使用AES加密URL链接以使用VB.NET 2005将用户名传递到ASP.NET中的其他网站的好链接或文章是什么?
仅供参考:接收网站将有权访问私钥以进行解密.
第一

不要这样做!编写自己的加密系统很容易导致出错.最好使用现有系统,如果没有,请让知道密码学的人去做.如果您必须自己动手,请阅读Practical Cryptography.

请记住:“我们已经拥有足够快速,不安全的系统.” (布鲁斯施奈尔) – 做正确的事情并担心以后的表现.

也就是说,如果你坚持使用AES来推销自己的,那么这里有一些指示.

初始化矢量

AES是分组密码.给定一个密钥和一个明文块,它将其转换为特定的密文.这样做的问题是,每次相同的数据块都会生成相同密钥的相同密文.所以假设你发送这样的数据:

用户=加密(用户名)及角色=加密(的UserRole)

它们是两个独立的块,UserRoles加密每次都有相同的密文,无论名称如何.我需要的只是管理员的密文,我可以使用我的密码用户名将其删除.哎呀.

所以,有cipher operation modes.主要思想是你将获取一个块的密文,并将其异或成为下一个块的密文.这样我们就会进行加密(UserRoles,用户名),并且用户名密文会受到UserRoles的影响.

问题是第一个块仍然容易受到攻击 – 仅仅通过查看某人的密文,我可能知道他们的角色.输入initialization vector. IV“启动”密码并确保其具有随机数据以加密流的其余部分.所以现在UserRoles密文具有随机IV异或的密文.问题解决了.

因此,请确保为每条消息生成随机IV. IV不敏感,可以用密文发送明文.使用足够大的IV – 对于许多情况,块的大小应该没问题.

廉正

AES不提供完整性功能.任何人都可以修改您的密文,解密仍然有效.它一般不太可能是有效数据,但可能很难知道有效数据是什么.例如,如果您正在传输加密的GUID,则很容易修改某些位并生成完全不同的位.这可能会导致应用程序错误等.

修复是在明文上运行哈希算法(使用SHA256或SHA512),并将其包含在您传输的数据中.因此,如果我的消息是(UserName,Roles),您将发送(UserName,Roles,Hash(UserName,Roles)).现在,如果有人通过翻转来篡改密文,则哈希将不再计算,您可以拒绝该消息.

密钥派生

如果需要从密码生成密钥,请使用内置类:System.Security.Cryptography.PasswordDeriveBytes.这提供了salting和迭代,这可以提高派生密钥的强度,并降低密钥泄露时发现密码的机会.

定时/重播

编辑:很抱歉没有提到这个:P.您还需要确保您有一个反重播系统.如果您只是加密邮件并传递它,那么获取邮件的任何人都可以重新发送邮件.为避免这种情况,您应该为邮件添加时间戳.如果时间戳与特定阈值不同,请拒绝该消息.您可能还希望包含一次性ID(可能是IV)并拒绝来自使用相同ID的其他IP的时间有效消息.

在包含时序信息时,确保进行哈希验证非常重要.否则,如果您没有检测到这种强力尝试,有人可能会篡改一些密文并可能生成有效的时间戳.

示例代码

由于显然正确地使用IV对某些人来说是有争议的,这里有一些代码可以生成随机IV并将它们添加到您的输出中.它还将执行身份验证步骤,确保未修改加密数据.

using System;
using System.Security.Cryptography;
using System.Text;

class AesDemo {

    const int HASH_SIZE = 32; //SHA256

    /// <summary>Performs encryption with random IV (prepended to output),and includes hash of plaintext for verification.</summary>
    public static byte[] Encrypt(string password,byte[] passwordSalt,byte[] plainText) {
        // Construct message with hash
        var msg = new byte[HASH_SIZE + plainText.Length];
        var hash = computeHash(plainText,plainText.Length);
        Buffer.BlockCopy(hash,msg,HASH_SIZE);
        Buffer.BlockCopy(plainText,HASH_SIZE,plainText.Length);

        // Encrypt
        using (var aes = createAes(password,passwordSalt)) {
            aes.GenerateIV();
            using (var enc = aes.CreateEncryptor()) {

                var encBytes = enc.TransformFinalBlock(msg,msg.Length);
                // Prepend IV to result
                var res = new byte[aes.IV.Length + encBytes.Length];
                Buffer.BlockCopy(aes.IV,res,aes.IV.Length);
                Buffer.BlockCopy(encBytes,aes.IV.Length,encBytes.Length);
                return res;
            }
        }
    }

    public static byte[] Decrypt(string password,byte[] cipherText) {
        using (var aes = createAes(password,passwordSalt)) {
            var iv = new byte[aes.IV.Length];
            Buffer.BlockCopy(cipherText,iv,iv.Length);
            aes.IV = iv; // Probably could copy right to the byte array,but that's not guaranteed

            using (var dec = aes.CreateDecryptor()) {
                var decBytes = dec.TransformFinalBlock(cipherText,iv.Length,cipherText.Length - iv.Length);

                // Verify hash
                var hash = computeHash(decBytes,decBytes.Length - HASH_SIZE);
                var existingHash = new byte[HASH_SIZE];
                Buffer.BlockCopy(decBytes,existingHash,HASH_SIZE);
                if (!compareBytes(existingHash,hash)){
                    throw new CryptographicException("Message hash incorrect.");
                }

                // Hash is valid,we're done
                var res = new byte[decBytes.Length - HASH_SIZE];
                Buffer.BlockCopy(decBytes,res.Length);
                return res;
            }
        }
    }

    static bool compareBytes(byte[] a1,byte[] a2) {
        if (a1.Length != a2.Length) return false;
        for (int i = 0; i < a1.Length; i++) {
            if (a1[i] != a2[i]) return false;
        }
        return true;
    }

    static Aes createAes(string password,byte[] salt) {
        // Salt may not be needed if password is safe
        if (password.Length < 8) throw new ArgumentException("Password must be at least 8 characters.","password");
        if (salt.Length < 8) throw new ArgumentException("Salt must be at least 8 bytes.","salt");
        var pdb = new PasswordDeriveBytes(password,salt,"SHA512",129);
        var key = pdb.GetBytes(16);

        var aes = Aes.Create();
        aes.Mode = CipherMode.CBC;
        aes.Key = pdb.GetBytes(aes.KeySize / 8);
        return aes;
    }

    static byte[] computeHash(byte[] data,int offset,int count) {
        using (var sha = SHA256.Create()) {
            return sha.ComputeHash(data,offset,count);
        }
    }

    public static void Main() {
        var password = "1234567890!";
        var salt = new byte[] { 1,2,3,4,5,6,7,8,9,0 };
        var ct1 = Encrypt(password,Encoding.UTF8.GetBytes("Alice; Bob; Eve;: PerformAct1"));
        Console.WriteLine(Convert.ToBase64String(ct1));
        var ct2 = Encrypt(password,Encoding.UTF8.GetBytes("Alice; Bob; Eve;: PerformAct2"));
        Console.WriteLine(Convert.ToBase64String(ct2));

        var pt1 = Decrypt(password,ct1);
        Console.WriteLine(Encoding.UTF8.GetString(pt1));
        var pt2 = Decrypt(password,ct2);
        Console.WriteLine(Encoding.UTF8.GetString(pt2));

        // Now check tampering
        try {
            ct1[30]++;
            Decrypt(password,ct1);
            Console.WriteLine("Error: tamper detection failed.");
        } catch (Exception ex) {
            Console.WriteLine("Success: tampering detected.");
            Console.WriteLine(ex.ToString());
        }
    }
}

输出:

JZVaD327sDmCmdzY0PsysnRgHbbC3eHb7YXALb0qxFVlr7Lkj8WaOZWc1ayWCvfhTUz/y0QMz+uv0PwmuG8VBVEQThaNTD02JlhIs1DjJtg=
QQvDujNJ31qTu/foDFUiVMeWTU0jKL/UJJfFAvmFtz361o3KSUlk/zH+4701mlFEU4Ce6VuAAuaiP1EENBJ74Wc8mE/QTofkUMHoa65/5e4=
Alice; Bob; Eve;: PerformAct1 Alice;
Bob; Eve;: PerformAct2 Success:
tampering detected.
System.Security.Cryptography.CryptographicException:
Message hash incorrect. at
AesDemo.Decrypt(String password,
Byte[] passwordSalt,Byte[]
cipherText) in
C:Program.cs:line
46 at AesDemo.Main() in
C:Program.cs:line
100

删除随机IV和哈希后,这是输出的类型:

tZfHJSFTXYX8V38AqEfYVXU5Dl/meUVAond70yIKGHY=
tZfHJSFTXYX8V38AqEfYVcf9a3U8vIEk1LuqGEyRZXM=

注意第一个块是如何对应的“Alice; Bob; Eve;”是一样的.确实是“角落案”.

没有散??列的示例

这是传递64位整数的简单示例.只是加密,你就会受到攻击.事实上,即使使用CBC填充,攻击也很容易完成.

public static void Main() {
    var buff = new byte[8];
    new Random().NextBytes(buff);
    var v = BitConverter.ToUInt64(buff,0);
    Console.WriteLine("Value: " + v.ToString());
    Console.WriteLine("Value (bytes): " + BitConverter.ToString(BitConverter.GetBytes(v)));
    var aes = Aes.Create();
    aes.GenerateIV();
    aes.GenerateKey();
    var encBytes = aes.CreateEncryptor().TransformFinalBlock(BitConverter.GetBytes(v),8);
    Console.WriteLine("Encrypted: " + BitConverter.ToString(encBytes));
    var dec = aes.CreateDecryptor();
    Console.WriteLine("Decrypted: " + BitConverter.ToUInt64(dec.TransformFinalBlock(encBytes,encBytes.Length),0));
    for (int i = 0; i < 8; i++) {
        for (int x = 0; x < 250; x++) {
            encBytes[i]++;
            try {
                Console.WriteLine("Attacked: " + BitConverter.ToUInt64(dec.TransformFinalBlock(encBytes,0));
                return;
            } catch { }
        }
    }
}

输出:

Value: 6598637501946607785 Value

(bytes): A9-38-19-D1-D8-11-93-5B

Encrypted:

31-59-B0-25-FD-C5-13-D7-81-D8-F5-8A-33-2A-57-DD

Decrypted: 6598637501946607785

Attacked: 14174658352338201502

因此,如果这是您要发送的ID类型,则可以很容易地将其更改为其他值.您需要在邮件之外进行身份验证.有时,消息结构不太可能落实到位,并且可以作为一种保护措施,但为什么要依赖可能发生变化的事情呢?无论应用程序如何,您都需要能够依赖加密才能正常工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读