您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

开发者该如何利用 C# 加解密?

时间:2019-11-11 09:04:30  来源:  作者:
开发者该如何利用 C# 加解密?

作者 | 喵叔

责编 | 刘静

出品 | CSDN(ID:CSDNnews)

加密解密在开发中经常用到,比如登录密码加密解密、消息传输加密解密等。但是很多人只会使用不理解其中的原理,这篇文章就带领大家快速学习加密解密的原理和使用。

1.零、什么是加密解密

通俗的说加密解密就是将不想让别人很容易看到的东西根据一定的规则进行处理,形成无规则的内容。拿到加密后内容的人通过一定规则将加密后的内容还原成原文。这里所说的原文在计算机中被称为明文,加密后的内容被称为密文。加密后的内容并不是完全不可破解的,只是提高了破解的难度,让大多数人退缩。那么怎么判断一个加解密安全呢?一般来说加密消息在发送方和接收方进行传递时必须满足三个条件:

  1. 发送方可以确定所发送的消息只有预期接收方可以解密,但不保证其他非接收方获得密文,只要保证非接收方获得密文后无法解密即可;

  2. 接收方可以确定消息是谁发送的;

  3. 接收方可以确定消息在传输过程中没有被篡改,也就是说可以验证消息的完整性。

一般来说常用的加密方式有三种:

  • 不可逆加密;

  • 对称可逆加密;

  • 非堆成可逆加密。

下面我来讲一讲这三种常用的加密方式。

2.不可逆加密

常用的不可逆加密是 MD5 加密,MD5是Message-Digest Algorithm 5英文简称,MD5 的特点如下:

  1. 任意长度的输入,经过 MD5 处理后都会输出128位的信息,这个信息称作数字指纹;

  2. 输入不同的信息产生的数字指纹不一样,数字指纹是全球唯一的;

  3. 无法根据数字指纹推导出加密前的信息。MD5 我们经常用在文档防篡改、密码加密、数字签名、网盘秒传。针对这四个方面我下面简单讲解一下:

  4. 文档防篡改

    在文档发送前记录文档的 MD5 值,接收方收到文档后计算文档的 MD5 值,如果两个 MD5 值不一样就说明文档在发送过程中被篡改过;

  5. 密码加密

    如果将密码明文存储在数据库中,泄露后可以别人可以直接登录,在用 MD5 将密码加密后即使泄露了也无法通过密文直接登录。但是这里需要注意,目前网上有很多破解 MD5 密文的网站,这些网站说白了就是利用撞库实现的,这些网站收集了常用的密码组合方式,比如生日、连续相同的数字或密码等,因此我们在验证密码强度时应当将常见的简单密码列,针对所有密码最好将密码中加入随机的信息内容然后再进行 MD5 加密,这就是所谓的加盐;

  6. 数字签名

    某人写了一个重要文件,这个文件经过认证机构利用 MD5 生成摘要信息进行认证,如果以后这个人不承认这个文件是他写的,只需认证机构再次对文件生成摘要信息和以前的照耀信息进行对比即可知道该文件是所写的;

  7. 网盘秒传

    网盘记录文件第一次上传的 MD5 值,以后当有人上传具有相同 MD5 值的文件时只需要将存在于网盘中的这个文件的链接发送出去即可。

MD5 的实现很简单代码如下:

public class MD5
{
/// <summary>
///
/// </summary>
/// <param name="source">待加密字串</param>
/// <param name="length">加密结果长度</param>
/// <returns>加密后的字串</returns>
public string Encrypt(string source, int length = 32)
{
if (string.IsOrEmpty(source))
{
return string.Empty;
}
HashAlgorithm provider = CryptoConfig.CreateFromName("MD5") as HashAlgorithm;
byte bytes = Encoding.UTF8.GetBytes(source);
byte hashValue = provider.ComputeHash(bytes);
StringBuilder sb = new StringBuilder;
switch (length)
{
case 16:
for (int i = 4; i < 12; i++)
{
sb.Append(hashValue[i].ToString("x2"));
}
break;
case 32:
for (int i = 0; i < 16; i++)
{
sb.Append(hashValue[i].ToString("x2"));
}
break;
default:
for (int i = 0; i < hashValue.Length; i++)
{
sb.Append(hashValue[i].ToString("x2"));
}
break;
}
return sb.ToString;
}

/// <summary>
/// 获取文件的MD5
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public string AbstractFile(string fileName)
{
FileStream file = new FileStream(fileName, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider;
byte retVal = md5.ComputeHash(file);
file.Close;
StringBuilder sb = new StringBuilder;
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString;
}
}

3.对称可逆加密

对称可逆加密就是用密钥将需要加密的内容进行加密,然后将加密后的内容发送给接收方,接收方街道内容后利用相同的密钥进行解密后就拿到了明文。对称可逆加密方式有一个严重的问题就是要保证密钥的安全,一旦密钥泄密第三方就可以利用这个密钥对解密收到的密文,甚至可以利用密钥伪造信息发送给接收方,接收方也就无法分辨出到底是谁发送的密文。

最常用的对称可逆加密算法是 DES ,下面我们通过代码看一下 DES 的实现:

public class DES
{
/// <summary>
/// 密钥
/// </summary>
private byte key = ASCIIEncoding.ASCII.GetBytes("123456");
/// <summary>
/// 偏移量
/// </summary>
private byte iv = ASCIIEncoding.ASCII.GetBytes("123456".Insert(0, "w").Substring(0, 8));

/// <summary>
/// 加密
/// </summary>
/// <param name="text">需要加密的值</param>
/// <returns>加密后的结果</returns>
public string Encrypt(string text)
{
DESCryptoServiceProvider dsp = new DESCryptoServiceProvider;
using (MemoryStream memStream = new MemoryStream)
{
CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateEncryptor(key, iv), CryptoStreamMode.Write);
StreamWriter sWriter = new StreamWriter(crypStream);
sWriter.Write(text);
sWriter.Flush;
crypStream.FlushFinalBlock;
memStream.Flush;
return Convert.ToBase64String(memStream.GetBuffer, 0, (int)memStream.Length);
}
}

/// <summary>
/// 解密
/// </summary>
/// <param name="encryptText"></param>
/// <returns>解密后的结果</returns>
public string Decrypt(string encryptText)
{
DESCryptoServiceProvider dsp = new DESCryptoServiceProvider;
byte buffer = Convert.FromBase64String(encryptText);

using (MemoryStream memStream = new MemoryStream)
{
CryptoStream crypStream = new CryptoStream(memStream, dsp.CreateDecryptor(key, iv), CryptoStreamMode.Write);
crypStream.Write(buffer, 0, buffer.Length);
crypStream.FlushFinalBlock;
return ASCIIEncoding.UTF8.GetString(memStream.ToArray);
}
}
}

4.非对称可逆加密

非对称加密比较麻烦,发送方和接收方都保存有两个密钥,其中一个密钥是公钥,公钥是对外公开的,任何人都可以拿到,另一个是私钥,每个人的私钥不一样。规则是由A公钥加密的信息只能用A的私钥解密,由A的私钥加密的消息只能由A的公钥解密。

非对称可逆加密的模式由两种:

  1. 加密模式

    使用接收方的公钥加密,然后使用接收方的私钥解密,这样可以保证只有特定的接收方能收到信息,但是无法确认发送方是谁。

  2. 认证模式

    使用发送方的私钥加密,然后使用发送方的公钥解密,这样可以保证特定发送方发送消息,但是无法确定消息是发给了谁。

从上述两种模式的描述中我们可以看到他们存在问题,因此就出现了数字签名,在上述认证模式中加入了散列算法(例如MD5),对明文进行处理后再把信息进行加密后发送出去,接收方收到信息解密后比较信息的散列值和原始消息的散列值就可以确定信息是否被篡改。

常用的非对称可逆加密算法常用的是RSA,代码实现如下:

public class Rsa
{
/// <summary>
/// 获取加密/解密对
/// </summary>
/// <returns>Encrypt Decrypt</returns>
public static KeyValuePair<string, string> GetKeyPair
{
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider;
string publicKey = RSA.ToXmlString(false);
string privateKey = RSA.ToXmlString(true);
return new KeyValuePair<string, string>(publicKey, privateKey);
}

/// <summary>
/// 加密
/// </summary>
/// <param name="content"></param>
/// <param name="encryptKey">加密key</param>
/// <returns></returns>
public static string Encrypt(string content, string encryptKey)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider;
rsa.FromXmlString(encryptKey);
UnicodeEncoding ByteConverter = new UnicodeEncoding;
byte DataToEncrypt = ByteConverter.GetBytes(content);
byte resultBytes = rsa.Encrypt(DataToEncrypt, false);
return Convert.ToBase64String(resultBytes);
}

/// <summary>
/// 解密
/// </summary>
/// <param name="content"></param>
/// <param name="decryptKey">解密key</param>
/// <returns></returns>
public static string Decrypt(string content, string decryptKey)
{
byte dataToDecrypt = Convert.FromBase64String(content);
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider;
RSA.FromXmlString(decryptKey);
byte resultBytes = RSA.Decrypt(dataToDecrypt, false);
UnicodeEncoding ByteConverter = new UnicodeEncoding;
return ByteConverter.GetString(resultBytes);
}


/// <summary>
/// 产生一组新的密钥
/// </summary>
/// <param name="content"></param>
/// <param name="encryptKey">加密key</param>
/// <param name="decryptKey">解密key</param>
/// <returns>加密后结果</returns>
private static string Encrypt(string content, out string publicKey, out string privateKey)
{
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider;
publicKey = rsaProvider.ToXmlString(false);
privateKey = rsaProvider.ToXmlString(true);

UnicodeEncoding ByteConverter = new UnicodeEncoding;
byte DataToEncrypt = ByteConverter.GetBytes(content);
byte resultBytes = rsaProvider.Encrypt(DataToEncrypt, false);
return Convert.ToBase64String(resultBytes);
}
}

5.总结

上述三种加密方式在开发中会经常用到,根据我在开发中的经验我建议使用非对称加密,这样更安全。

作者简介:朱钢,笔名喵叔,CSDN博客专家,.NET高级开发工程师,7年一线开发经验,参与过电子政务系统和AI客服系统的开发,以及互联网招聘网站的架构设计,目前就职于北京恒创融慧科技发展有限公司,从事企业级安全监控系统的开发。

声明:本文系作者独立观点,不代表CSDN立场。

【END】



Tags:C# 加密   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
加密解密在开发中经常用到,比如登录密码加密解密、消息传输加密解密等。但是很多人只会使用不理解其中的原理,这篇文章就带领大家快速学习加密解密的原理和使用...【详细内容】
2019-11-11  Tags: C# 加密  点击:(92)  评论:(0)  加入收藏
▌简易百科推荐
一、简介很多时候我们都需要用到一些验证的方法,有时候需要用正则表达式校验数据时,往往需要到网上找很久,结果找到的还不是很符合自己想要的。所以我把自己整理的校验帮助类分...【详细内容】
2021-12-27  中年农码工    Tags:C#   点击:(2)  评论:(0)  加入收藏
引言在学习C语言或者其他编程语言的时候,我们编写的一个程序代码,基本都是在屏幕上打印出 hello world ,开始步入编程世(深)界(坑)的。C 语言版本的 hello world 代码:#include <std...【详细内容】
2021-12-21  一起学嵌入式    Tags:C 语言   点击:(11)  评论:(0)  加入收藏
读取SQLite数据库,就是读取一个路径\\192.168.100.**\position\db.sqlite下的文件<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/...【详细内容】
2021-12-16  今朝我的奋斗    Tags:c#   点击:(21)  评论:(0)  加入收藏
什么是shellshell是c语言编写的程序,它在用户和操作系统之间架起了一座桥梁,用户可以通过这个桥梁访问操作系统内核服务。 它既是一种命令语言,同时也是一种程序设计语言,你可以...【详细内容】
2021-12-16  梦回故里归来    Tags:shell脚本   点击:(18)  评论:(0)  加入收藏
一、编程语言1.根据熟悉的语言,谈谈两种语言的区别?主要浅谈下C/C++和PHP语言的区别:1)PHP弱类型语言,一种脚本语言,对数据的类型不要求过多,较多的应用于Web应用开发,现在好多互...【详细内容】
2021-12-15  linux上的码农    Tags:c/c++   点击:(17)  评论:(0)  加入收藏
1.字符串数组+初始化char s1[]="array"; //字符数组char s2[6]="array"; //数组长度=字符串长度+1,因为字符串末尾会自动添&lsquo;\0&lsquo;printf("%s,%c\n",s1,s2[2]);...【详细内容】
2021-12-08  灯-灯灯    Tags:C语言   点击:(47)  评论:(0)  加入收藏
函数调用约定(Calling Convention),是一个重要的基础概念,用来规定调用者和被调用者是如何传递参数的,既调用者如何将参数按照什么样的规范传递给被调用者。在参数传递中,有两个很...【详细内容】
2021-11-30  小智雅汇    Tags:函数   点击:(19)  评论:(0)  加入收藏
一、问题提出问题:把m个苹果放入n个盘子中,允许有的盘子为空,共有多少种方法?注:5,1,1和1 5 1属同一种方法m,n均小于10二、算法分析设f(m,n) 为m个苹果,n个盘子的放法数目,则先对...【详细内容】
2021-11-17  C语言编程    Tags:C语言   点击:(49)  评论:(0)  加入收藏
一、为什么需要使用内存池在C/C++中我们通常使用malloc,free或new,delete来动态分配内存。一方面,因为这些函数涉及到了系统调用,所以频繁的调用必然会导致程序性能的损耗;另一...【详细内容】
2021-11-17  深度Linux    Tags:C++   点击:(38)  评论:(0)  加入收藏
OpenCV(Open Source Computer Vision Library)是一个(开源免费)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android、ios等操作系统上,它轻量级而且高效---由一系列...【详细内容】
2021-11-11  zls315    Tags:C#   点击:(50)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条