using System.Text; namespace XGame.Framework.Utils { /// /// 安全性工具类 /// public static partial class SecurityUtils { /// /// rc4 密钥字节数组长度 /// private const short RC4_KEY_LENGTH = 256; /// /// 用于密钥索引计算 /// 位操作( index & 255 )比余数快一点( index % 256 ) /// private const byte RC4_KEY_LIMIT = 0xFF;//255 /// /// 状态向量S /// private static readonly byte[] RC4_KEY_INDEXS = new byte[RC4_KEY_LENGTH]; /// /// RC4算法的特点是算法简单,运行速度快,而且密钥长度是可变的,可变范围为1-256字节(8-2048比特), /// RC4加密算法中的几个关键变量: /// 1、密钥流:RC4算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是500字节,那么密钥流也是500字节。当然,加密生成的密文也是500字节,因为密文第i字节=明文第i字节^密钥流第i字节; /// 2、状态向量S:长度为256,S[0],S[1].....S[255]。每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换; /// 3、临时向量T:长度也为256,每个单元也是一个字节。如果密钥的长度是256字节,就直接把密钥的值赋给T,否则,轮转地将密钥的每个字节赋给T; /// 4、密钥K:长度为1-256字节,注意密钥的长度keylen与明文长度、密钥流的长度没有必然关系,通常密钥的长度趣味16字节(128比特)。 /// RC4步骤:1、初始化S和T 2、初始排列S 3、产生密钥流 /// 本质上是打乱密钥顺序的异或加密 /// /// 密钥 /// 输入数组 /// 数据偏移值 /// 加密的数据长度 /// 输出,长度和input一致 public static void RC4(byte[] pwd, byte[] input, int offset, int length, byte[] output) { Assert.IsFalse(pwd == null || pwd.Length == 0, "RC4密钥不能为空."); Assert.IsFalse(input == null || input.Length == 0, "RC4输入数据内容不能为空."); Assert.IsFalse(output == null || output.Length == 0, "RC4输出数据不能为空."); Assert.IsTrue(input.Length == output.Length, $"RC4输入输出数据长度必须一致.Input:{input.Length} Output:{output.Length}"); Assert.IsFalse(offset < 0 || length <= 0 || offset + length > input.Length, $"RC4数据偏移值错误.offset:{offset} length:{length} inputL:{input.Length}"); int a, i, j, k; var pwdLength = pwd.Length; //打乱密码,密码,密码箱长度 for (i = 0; i < RC4_KEY_LENGTH; i++) { // 先重置索引 RC4_KEY_INDEXS[i] = (byte)i; } for (j = i = 0; i < RC4_KEY_LENGTH; i++) { j = (j + RC4_KEY_INDEXS[i] + pwd[i % pwdLength]) & RC4_KEY_LIMIT; // 位操作( &255 )比余数快一点( %256 ) Swap(RC4_KEY_INDEXS, i, j); } for (j = i = 0; i < length; i++) { a = (i + 1) & RC4_KEY_LIMIT; j = (j + RC4_KEY_INDEXS[a]) & RC4_KEY_LIMIT; Swap(RC4_KEY_INDEXS, a, j); k = RC4_KEY_INDEXS[(RC4_KEY_INDEXS[a] + RC4_KEY_INDEXS[j]) & RC4_KEY_LIMIT]; output[i + offset] = (byte)(input[i + offset] ^ k); } } private static void Swap(byte[] s, int i, int j) { var c = s[i]; s[i] = s[j]; s[j] = c; } /// /// 加密字节数组 /// 加密直接替换原数组内容 /// /// 密钥 /// 加密源&输出 public static void RC4(byte[] pwd, byte[] bytes) { RC4(pwd, bytes, 0, bytes.Length, bytes); } /// /// 十六进制字符串加密 /// 返回十六进制字符串 /// /// 密钥,不强制使用十六进制 /// 必须是十六进制的字符串 /// public static string RC4(string pwd, string hexString) { byte[] key = Encoding.UTF8.GetBytes(pwd); byte[] bytes = hexString.ToHexBytes(); RC4(key, bytes, 0, bytes.Length, bytes); return bytes.ToHexString(); } } }