如何在.net核心中加密和解密字符串

Posted

技术标签:

【中文标题】如何在.net核心中加密和解密字符串【英文标题】:How to Encrypt and decrypt string in .net core 【发布时间】:2019-07-05 10:31:35 【问题描述】:

我将 .net webapi 移植到 .net core webapi。 在我使用的旧代码中

Cryptographer.CreateHash("SHA1CryptoServiceProvider", strPass);

为此,我使用了库 Microsoft.Practices.EnterpriseLibrary.Security.Cryptography

但在移植到 .net 核心后,我遇到了问题:

System.MissingMethodException: Method not found: 'System.AppDomainSetup System.AppDomain.get_SetupInformation()'.
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource.SafeGetCurrentConfigurationFile()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceFactory.Create()
   at Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.SetCurrentContainerIfNotSet()
   at Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Cryptographer.GetHashProvider(String hashInstance)
   at Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Cryptographer.CreateHash(String hashInstance, String plaintext)
   at Social27Bot.DAL.Data.Mappers.Security.EncryptPass(String strPass) 

解决办法是什么?

【问题讨论】:

因为您使用 SHA41 对字符串进行哈希处理,我觉得这个问题是 Using SHA-1 in .NET Core 的部分重复 Using SHA-1 in .NET Core的可能重复 您的应用中有 appname.config 文件吗?可能与a config file problem 有关 不要使用Microsoft.Practices.EnterpriseLibrary。它是十多年前创建的遗留库,用于处理现在由 .NET 本身处理的场景。它绝对适用于 Core。 此外,SHA1 已经过时,多年来一直被认为是密码散列的危害。它太容易坏了。在任何情况下都不应该使用它,尤其是针对新运行时的代码。同样,密码的安全加密散列已经在 .NET 中通过 Rfc2898DeriveBytes 类提供。 【参考方案1】:

长话短说,EntLib 是一个十多年前创建的遗留库。不要使用它。它从未打算在 .NET Core 中使用,并且显然从未升级以使用它。请改用KeyDerivation.Pbkdf2。

在这种特定情况下,您完全不能使用 EntLib,因为它试图使用不存在的属性 AppDomain.SetupInformation。 AppDomain 类 was removed in the first versions of .NET Core 并添加回 i .NET Core 2.0。即使是现在,它也不提供所有成员,包括SetupInformation

正如文档页面所解释的,此属性将在 .NET Core 3.0 中重新添加,该属性将于 9 月发布。

真正的解决方案是一开始就不使用这样的代码,使用ASP.NET Core的Identity来存储密码。

像这样使用 SHA1 散列密码很容易在几分钟内破解。早在人们用来创建彩虹表的时候,就会为所有密码组合预先计算 SHA1 哈希值,然后只需查找哈希值即可找到密码。如今,仅暴力破解它可能比搜索大哈希表更快

ASP.NET 始终提供更安全的密码散列和存储,包括加盐和多次 散列迭代。在 ASP.NET Web 窗体和旧版本的 MVC 中,使用了加盐和至少 1000 次哈希迭代。

ASP.NET Core Identity 还提供安全的散列和存储。使用它是最简单和最安全的选择。它是开源的,所以即使不能使用它,也很容易检查它是如何散列密码的。

HashPasswordV3 方法使用 ASP.NET Core 的 KeyDerivation 类对用户提供的密码进行哈希处理。代码非常简单。本质上,它是对 KeyDerivation.Pbkdf2 的调用,带有一个 16 字节的盐,返回一个 32 字节的哈希缓冲区。

byte[] salt = new byte[16];
rng.GetBytes(salt);
byte[] subkey = KeyDerivation.Pbkdf2(password, salt, KeyDerivationPrf.HMACSHA256, 
                                     iterCount, 32);

其余代码将散列算法 ID、散列字节、迭代计数和盐值打包在一个单字节数组中,以便存储在一个表中。这些属性可以存储在表的不同列中,但将所有内容放在单个 byte[] 数组中更方便。

VerifyHashedPasswordV3 稍后会读取存储的缓冲区,提取属性并对提供的密码进行哈希处理,然后再检查存储和计算的哈希值

【讨论】:

【参考方案2】:

试试这个,

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DevExtremeAspNetCoreApp07052019.App_Start;


namespace DevExtremeAspNetCoreApp07052019.App_Start

    public class HelperClass
    

        public static char Mid(string param, int startIndex, int length)
        
            Char result = Convert.ToChar(param.Substring(startIndex, length));
            return result;
        
        public static string Decrypt(string icText)
        
            int icLen;
            string icNewText = "";
            char icChar;
            //icChar = '' ;
            icLen = icText.Length;
            for (int i = 0; i <= icLen-1; i++)
            
                icChar = Mid(icText, i, 1);
                switch (Strings.AscW(icChar))
                
                    case object _ when 192 <= Strings.AscW(icChar) && Strings.AscW(icChar) <= 217:
                        
                            icChar = Strings.ChrW(Strings.AscW(icChar) - 127);
                            break;
                        

                    case object _ when 218 <= Strings.AscW(icChar) && Strings.AscW(icChar) <= 243:
                        
                            icChar = Strings.ChrW(Strings.AscW(icChar) - 121);
                            break;
                        

                    case object _ when 244 <= Strings.AscW(icChar) && Strings.AscW(icChar) <= 253:
                        
                            icChar = Strings.ChrW(Strings.AscW(icChar) - 196);
                            break;
                        

                    case 32:
                        
                            icChar = Strings.ChrW(32);
                            break;
                        
                
                icNewText = icNewText + icChar;
            
           // icNewText = Microsoft.VisualBasic.StrReverse(icNewText);
            return (icNewText);
        
        public static string Encrypt(string icText)
        
            int icLen;
            string icNewText = "";
            char icChar;
            icLen = icText.Length;
            for (int i = 1; i <= icLen; i++)
            
                icChar = Mid(icText, i, 1); 
                switch (Strings.AscW(icChar))
                
                    case object _ when 65 <= Strings.AscW(icChar) && Strings.AscW(icChar) <= 90:
                        
                            icChar = Strings.ChrW(Strings.AscW(icChar) + 127);
                            break;
                        

                    case object _ when 97 <= Strings.AscW(icChar) && Strings.AscW(icChar) <= 122:
                        
                            icChar = Strings.ChrW(Strings.AscW(icChar) + 121);
                            break;
                        

                    case object _ when 48 <= Strings.AscW(icChar) && Strings.AscW(icChar) <= 57:
                        
                            icChar = Strings.ChrW(Strings.AscW(icChar) + 196);
                            break;
                        

                    case 32:
                        
                            icChar = Strings.ChrW(32);
                            break;
                        
                
                icNewText = icNewText + icChar;
            
            return (icNewText);
        

        public static string ReplaceFirstOccurrence(string Source, string Find, string Replace)
        
            string result = "";
            int Place = Source.IndexOf(Find);
            if (Place != -1)
            
                result = Source.Remove(Place, Find.Length).Insert(Place, Replace);
            
            else
            
                result = Source;
            
            return result;
        

        public static string SQLString(string sStrings, Boolean Trim = true)
        
            //Get
            //

            if (Trim)
            
                if (sStrings != null && sStrings.Trim() != "")
                    return ReplaceFirstOccurrence(sStrings.Trim(), "'", "''");
                else
                    return "";
            
            else if (sStrings.Trim() != "")
                return ReplaceFirstOccurrence(sStrings, "'", "''");
            else
                return "";
            //
        

    

【讨论】:

以上是关于如何在.net核心中加密和解密字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中加密和解密字符串?

.NET RSACryptoServiceProvider 使用 4096 私钥加密,如何在 Android 上解密

.net 中用户登录时密码加密 如何解密

如何使用Base64进行加密和解密

php源代码被加密了,请问如何解密?

如何对数据库进行加密和解密