zoukankan      html  css  js  c++  java
  • 密码学系列——常见的加密方式(c#代码实操)

    前言

    说起加密方式,其实密码学的角度ASCII编码其实本身就是一种加密解密。

    由于其公开,现在用于数字与字符的转换。

    查看ASCII表可以去官网查查。

    转换代码如下:

    static void Main(string[] args)
    {
    	char c = (char)97;
    	Console.WriteLine(c);//a
    	Console.ReadKey();
    }
    

    大概就是这样了。

    再讲另外一个故事,我们在数据传输过程中为什么要求编码格式一致。

    这个问题其实也是一个密码学问题。比如说传输方的编码是UTF8,接收方是GBK,那么两者是接收不到正确的消息的。最起码的一点就是UTF-8是汉字是三个字节,GBK汉字是两个字节。

    好吧,下面就介绍几种常用的加解密大法吧。

    正文

    凯撒加解密

    凯撒大法是通过移位来加解密,比如说a移动1位就是b了。

    代码如下:

    public class KaiserDemo
    {
    	//解密
    	public static string decrytKaiser(string encrytedData, int key)
    	{
    		char[] chars = encrytedData.ToCharArray();
    		StringBuilder sb = new StringBuilder();
    		foreach (char c in chars)
    		{
    			//转换为int
    			int asciiCode = c;
    			asciiCode -= key;
    			char result = (char)asciiCode;
    			sb.Append(result);
    		}
    		return sb.ToString();
    	}
    	//加密
    	public static string encrytKaiser(string orinal,int key)
    	{
    		char[] chars = orinal.ToCharArray();
    		StringBuilder sb = new StringBuilder();
    		foreach (char c in chars)
    		{
    			//转换为int
    			int asciiCode = c;
    			asciiCode += key;
    			char result = (char)asciiCode;
    			sb.Append(result);
    		}
    		return sb.ToString();
    	}
    }
    

    测试:

    static void Main(string[] args)
    {
    	string s = "Hello Word";
    	int key = 5;
    	var encrytedStr = KaiserDemo.encrytKaiser(s, key);
    	Console.WriteLine(encrytedStr);
    	var decrytedStr = KaiserDemo.decrytKaiser(encrytedStr, key);
    	Console.WriteLine(decrytedStr);
    	Console.ReadKey();
    }
    

    效果:

    base64位转换

    base64位是一个非常关键地方,先写一下原理:

    base64 是 3个字节为一组,一个字节 8位,一共 就是24位 ,然后,把3个字节转成4组,每组6位,
    3 * 8 = 4 * 6 = 24 ,每组6位,缺少的2位,会在高位进行补0 ,这样做的好处在于 ,base取的是后面6位,去掉高2位 ,

    那么base64的取值就可以控制在0-63位了,所以就叫base64,111 111 = 32 + 16 + 8 + 4 + 2 + 1 =63

    在64范围之内,当然也有人认为0-63,一共64位。

    base64 构成原则
    ① 小写 a - z = 26个字母
    ② 大写 A - Z = 26个字母
    ③ 数字 0 - 9 = 10 个数字
    ④ + / = 2个符号

    前面提及到为什么base64是一个非常关键的地方呢?

    因为base64可以将一些特殊字符全部转换成常规字符,原来的4个字节变成3个字节,那么数值是变小的。

    具体可看一下:

    https://baike.baidu.com/item/base64/8545775?fr=aladdin

    des 加解密

    直接上代码:

    /// <summary>
    /// DES 加解密
    /// </summary>
    /// <param name="origal">加解密字符串</param>
    /// <param name="key">key</param>
    /// <param name="iv">iv</param>
    /// <param name="sign">标识加密或者解密位,默认加密</param>
    /// <returns>加解密后的结果</returns>
    public static string DES(string origal, string key, string iv, int sign = 0)
    {
    	byte[] origalByteArray = sign == 0 ? Encoding.Default.GetBytes(origal) : Convert.FromBase64String(origal);
    	DESCryptoServiceProvider des = new DESCryptoServiceProvider();
    	des.Key = Encoding.ASCII.GetBytes(key);
    	des.IV = Encoding.ASCII.GetBytes(iv);
    	if (sign != 0)
    	{
    		des.Padding = PaddingMode.None;
    	}
    	string result = string.Empty;
    	using (MemoryStream ms = new MemoryStream())
    	{
    		using (CryptoStream cs = new CryptoStream(ms, sign == 0 ? des.CreateEncryptor() : des.CreateDecryptor(), CryptoStreamMode.Write))
    		{
    			cs.Write(origalByteArray, 0, origalByteArray.Length);
    			cs.FlushFinalBlock();
    			result = sign == 0 ? Convert.ToBase64String(ms.ToArray()) : System.Text.Encoding.Default.GetString(ms.ToArray());
    			
    		}
    	}
    	if (result == string.Empty)
    	{
    		throw new ArgumentException();
    	}
    	return result;
    }
    

    测试:

    static void Main(string[] args)
    {
    	string origal = "王胖子";
    	string key = "12345678";
    	string iv = "12345678";
    	string encrytedStr = DESDemo.DES(origal, key, iv);
    	Console.WriteLine("加密后的字符串:" + encrytedStr);
    	string dncrytedStr = DESDemo.DES(encrytedStr, key, iv, 1);
    	Console.WriteLine("加密后的字符串:" + dncrytedStr);
    	Console.Read();
    }
    

    测试结果:

    这里有人看到心里就想啊,怎么跟我代码里面的helper类不一样?

    一个是现在不完善,第二个是现在是无填充模式,下一章将会介绍填充模式。

    aes

    /// <summary>
    /// AES 加解密
    /// </summary>
    /// <param name="origal">加解密字符串</param>
    /// <param name="key">key</param>
    /// <param name="iv">iv</param>
    /// <param name="sign">标识加密或者解密位,默认加密</param>
    /// <returns>加解密后的结果</returns>
    public static string AES(string origal, string key, string iv, int sign = 0)
    {
    	byte[] origalByteArray = sign == 0 ? Encoding.Default.GetBytes(origal) : Convert.FromBase64String(origal);
    	RijndaelManaged aes = new RijndaelManaged();
    	aes.Key = Encoding.ASCII.GetBytes(key);
    	aes.IV = Encoding.ASCII.GetBytes(iv);
    	if (sign != 0)
    	{
    		aes.Padding = PaddingMode.None;
    	}
    	string result = string.Empty;
    	using (MemoryStream ms = new MemoryStream())
    	{
    		using (CryptoStream cs = new CryptoStream(ms, sign == 0 ? aes.CreateEncryptor() : aes.CreateDecryptor(), CryptoStreamMode.Write))
    		{
    			cs.Write(origalByteArray, 0, origalByteArray.Length);
    			cs.FlushFinalBlock();
    			result = sign == 0 ? Convert.ToBase64String(ms.ToArray()) : System.Text.Encoding.Default.GetString(ms.ToArray());
    
    		}
    	}
    	if (result == string.Empty)
    	{
    		throw new ArgumentException();
    	}
    	return result;
    }
    
    string origal = "王胖子";
    string key = "IE7XG5ORF7EA4JC5";
    string iv = "IE7XG5ORF7EA4JC5";
    string encrytedStr = AESDemo.AES(origal, key, iv);
    Console.WriteLine("加密后的字符串:" + encrytedStr);
    string dncrytedStr = AESDemo.AES(encrytedStr, key, iv, 1);
    Console.WriteLine("加密后的字符串:" + dncrytedStr);
    Console.Read();
    

    测试结果:

    和des一样哈,不完善,下一节将会完善。

    下一节介绍填充和不填充,如果不明白在开发中还是很容易出事的,比如说服务端采用填充模式,客户端非填充模式,那么会报错的,顺便完善的一下code。

  • 相关阅读:
    jade反编译,把html编译成jade
    runtime环境下的jade
    jade过滤器
    jade-render-renderFile
    【[USACO17DEC]Standing Out from the Herd】
    bzoj 1396: 识别子串
    bzoj 4327:JSOI2012 玄武密码
    hihocoder 后缀自动机四·重复旋律6
    hihocoder 后缀自动机四·重复旋律7
    【[CTSC2012]熟悉的文章】
  • 原文地址:https://www.cnblogs.com/aoximin/p/13398415.html
Copyright © 2011-2022 走看看