Просмотр исходного кода

新增零宽字符串编解码器

懒得勤快 2 лет назад
Родитель
Сommit
2e8c1b372a

+ 1 - 1
Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj

@@ -3,7 +3,7 @@
         <TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5;net6;net7</TargetFrameworks>
         <LangVersion>latest</LangVersion>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-        <Version>2.5.7.7</Version>
+        <Version>2.5.8</Version>
         <Authors>懒得勤快</Authors>
         <Description>Masuit.Tools基础公共库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。</Description>
         <Copyright>懒得勤快,长空X</Copyright>

+ 138 - 0
Masuit.Tools.Abstractions/Security/ZeroWidthCodec.cs

@@ -0,0 +1,138 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Masuit.Tools.Security;
+
+/// <summary>
+/// 零宽字符串编解码器
+/// </summary>
+public static class ZeroWidthCodec
+{
+	/// <summary>
+	/// 注入零宽字符串
+	/// </summary>
+	/// <param name="s"></param>
+	/// <param name="hidden"></param>
+	/// <returns></returns>
+	public static string InjectZeroWidthString(this string s, string hidden)
+	{
+		return Encrypt(s, hidden);
+	}
+
+	/// <summary>
+	/// 编码为零宽字符串
+	/// </summary>
+	/// <param name="s"></param>
+	/// <returns></returns>
+	public static string EncodeToZeroWidthText(this string s)
+	{
+		return Encode(s);
+	}
+
+	/// <summary>
+	/// 解码零宽字符串
+	/// </summary>
+	/// <param name="s"></param>
+	/// <returns></returns>
+	public static string DecodeZeroWidthString(this string s)
+	{
+		return Decrypt(s);
+	}
+
+	/// <summary>
+	/// 注入零宽字符串
+	/// </summary>
+	/// <param name="pub">显示字符串</param>
+	/// <param name="hidden">隐式字符串</param>
+	/// <returns></returns>
+	public static string Encrypt(string pub, string hidden)
+	{
+		// 将字符串拆分成单个字符
+		var pubMsg = pub.ToCharArray();
+		var hiddenMsg = Str2Bin(Encoding.UTF8.GetBytes(hidden));// 将需要隐藏的字符串转换成二进制格式
+		hiddenMsg = Bin2Hidden(hiddenMsg);// 将二进制转换成隐藏字符格式
+		hiddenMsg = $"\uFEFF{hiddenMsg}\uFEFF";// 用边界字符包装隐藏的字符
+		if (pubMsg.Length == 1)
+		{
+			return pub + hiddenMsg;
+		}
+
+		// 将编码的隐藏消息注入到公共字符串的大约中间位置
+		int half = pub.Length / 2;
+		var chars = new List<char>();
+		for (var i = 0; i < pubMsg.Length; i++)
+		{
+			if (i == half)
+			{
+				chars.AddRange(hiddenMsg);
+			}
+
+			chars.Add(pubMsg[i]);
+		}
+
+		return string.Concat(chars);
+	}
+
+	/// <summary>
+	/// 编码为零宽字符串
+	/// </summary>
+	/// <param name="str"></param>
+	/// <returns></returns>
+	public static string Encode(string str)
+	{
+		var encodeText = new StringBuilder(string.Join(" ", Encoding.UTF8.GetBytes(str).Select(byt => Convert.ToString(byt, 2).PadLeft(8, '0'))))
+			.Replace('\u0030', '\u200B')
+			.Replace('\u0031', '\u200C')
+			.Replace('\u0020', '\u200D')
+			.ToString();
+		return encodeText;
+	}
+
+	/// <summary>
+	/// 解码零宽字符串
+	/// </summary>
+	/// <param name="pub"></param>
+	/// <returns></returns>
+	public static string Decrypt(string pub)
+	{
+		var unwrapped = Unwrap(pub);
+		var message = Bin2Str(unwrapped == "false" ? Hidden2Bin(pub) : Hidden2Bin(unwrapped));
+		return message.Length < 2 ? "No private message was found in that text." : message;
+	}
+
+	private static string Str2Bin(byte[] text)
+	{
+		return string.Join(" ", text.Select(byt => Convert.ToString(byt, 2).PadLeft(8, '0')));
+	}
+
+	private static string Unwrap(string text)
+	{
+		var tmp = text.Split("\uFEFF".ToCharArray());
+		return tmp.Length == 1 ? "false" : tmp[1];
+	}
+
+	private static string Bin2Str(string bin)
+	{
+		bin = Regex.Replace(bin, "[^0-1]", " ");
+		return Encoding.UTF8.GetString(Enumerable.Range(0, bin.Split().Length).Select(vw => Convert.ToByte(Regex.Replace(bin.Split()[vw], @"\s", ""), 2)).ToArray());
+	}
+
+	private static string Bin2Hidden(string text)
+	{
+		text = text.Replace(" ", "\u2060"); // Unicode Character 'WORD JOINER' (U+2060) 0xE2 0x81 0xA0
+		text = text.Replace("0", "\u200B"); // Unicode Character 'ZERO WIDTH SPACE' (U+200B) 0xE2 0x80 0x8B
+		text = text.Replace("1", "\u200C"); // Unicode Character 'ZERO WIDTH NON-JOINER' (U+200C) 0xE2 0x80 0x8C
+		return text;
+	}
+
+	private static string Hidden2Bin(string text)
+	{
+		text = text.Replace("\u2060", " "); // Unicode Character 'WORD JOINER' (U+2060) 0xE2 0x81 0xA0
+		text = text.Replace("\u200B", "0"); // Unicode Character 'ZERO WIDTH SPACE' (U+200B) 0xE2 0x80 0x8B
+		text = text.Replace("\u200C", "1"); // Unicode Character 'ZERO WIDTH NON-JOINER' (U+200C) 0xE2 0x80 0x8C
+		return text;
+	}
+}

+ 1 - 1
Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj

@@ -17,7 +17,7 @@
         <Product>Masuit.Tools.AspNetCore</Product>
         <PackageId>Masuit.Tools.AspNetCore</PackageId>
         <LangVersion>latest</LangVersion>
-        <Version>1.1.7.7</Version>
+        <Version>1.1.8</Version>
         <RepositoryType></RepositoryType>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
         <FileVersion>$(Version)</FileVersion>

+ 1 - 1
Masuit.Tools.Core/Masuit.Tools.Core.csproj

@@ -20,7 +20,7 @@ github:https://github.com/ldqk/Masuit.Tools
         <UserSecretsId>830c282f-f7c1-42be-8651-4cd06ac8e73f</UserSecretsId>
         <RepositoryType></RepositoryType>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-        <Version>2.5.7.7</Version>
+        <Version>2.5.8</Version>
         <FileVersion>$(Version)</FileVersion>
         <Company>masuit.org</Company>
         <AssemblyVersion>$(Version)</AssemblyVersion>