如何在.NET中实现加密结果与原字符串等长的安全加密与解密?
.NET 实现等长加密解密机制
要实现加密结果与原始数据长度完全一致的加密解密机制,核心是采用一对一的字符/字节映射逻辑,避免使用需要填充的分组加密算法(如AES的CBC/ECB模式)。以下是两种可行的实现方案:
方案一:自定义字符映射加密
基于异或运算和自定义字符集,将每个明文字符映射为目标字符集中的唯一字符,确保长度严格一致。适合对可见字符进行加密的场景。
代码实现
using System; using System.Text; public class FixedCharCrypto { // 自定义映射字符集(与示例一致) private readonly string _charSet = "abcdeABCDE12345"; private readonly int _charSetLen; // 自定义密钥偏移量,用于增强加密强度 private readonly int _keyOffset = 7; public FixedCharCrypto() { _charSetLen = _charSet.Length; } // 加密:明文字符→字符集映射字符 public string Encrypt(string plainText) { var cipherBuilder = new StringBuilder(); foreach (char c in plainText) { // 以字符ASCII值为基础计算映射索引,加入密钥偏移 int mapIndex = (c % _charSetLen + _keyOffset) % _charSetLen; cipherBuilder.Append(_charSet[mapIndex]); } return cipherBuilder.ToString(); } // 解密:映射字符→原明文字符 public string Decrypt(string cipherText) { var plainBuilder = new StringBuilder(); foreach (char c in cipherText) { int charIndex = _charSet.IndexOf(c); if (charIndex == -1) throw new ArgumentException("密文中包含无效字符"); // 反向偏移计算原字符ASCII值 int originAscii = (charIndex - _keyOffset + _charSetLen) % _charSetLen; plainBuilder.Append((char)originAscii); } return plainBuilder.ToString(); } } // 使用示例 public class Demo { public static void Main() { var crypto = new FixedCharCrypto(); string plain = "Hello Word!"; string cipher = crypto.Encrypt(plain); Console.WriteLine($"加密结果:{cipher}"); // 长度与原字符串一致 string decrypted = crypto.Decrypt(cipher); Console.WriteLine($"解密结果:{decrypted}"); // 输出:Hello Word! } }
方案二:流密码算法(RC4)
流密码会生成与明文长度一致的密钥流,通过逐字节异或完成加密,天然保证等长。安全性比自定义映射更高,适合对任意字节数据加密的场景。
代码实现
using System; using System.Text; public class RC4FixedLengthCrypto { private readonly byte[] _key; private readonly string _charSet = "abcdeABCDE12345"; private readonly int _charSetLen; public RC4FixedLengthCrypto(string secretKey) { _key = Encoding.UTF8.GetBytes(secretKey); _charSetLen = _charSet.Length; } // RC4核心逻辑:生成密钥流并完成异或运算(加密解密通用) private byte[] RC4Process(byte[] input) { byte[] sBox = new byte[256]; byte[] keyBox = new byte[256]; byte temp; // 初始化S盒与密钥盒 for (int i = 0; i < 256; i++) { sBox[i] = (byte)i; keyBox[i] = _key[i % _key.Length]; } // 置换S盒 int j = 0; for (int i = 0; i < 256; i++) { j = (j + sBox[i] + keyBox[i]) % 256; temp = sBox[i]; sBox[i] = sBox[j]; sBox[j] = temp; } // 生成密钥流并异或加密 int i1 = 0, j1 = 0; byte[] output = new byte[input.Length]; for (int x = 0; x < input.Length; x++) { i1 = (i1 + 1) % 256; j1 = (j1 + sBox[i1]) % 256; temp = sBox[i1]; sBox[i1] = sBox[j1]; sBox[j1] = temp; int t = (sBox[i1] + sBox[j1]) % 256; output[x] = (byte)(input[x] ^ sBox[t]); } return output; } // 字符串加密:字节流→字符集映射 public string EncryptString(string plainText) { byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); byte[] encryptedBytes = RC4Process(plainBytes); var cipherBuilder = new StringBuilder(); foreach (byte b in encryptedBytes) { cipherBuilder.Append(_charSet[b % _charSetLen]); } return cipherBuilder.ToString(); } // 字符串解密:字符集映射→字节流 public string DecryptString(string cipherText) { byte[] cipherBytes = new byte[cipherText.Length]; for (int i = 0; i < cipherText.Length; i++) { int charIndex = _charSet.IndexOf(cipherText[i]); if (charIndex == -1) throw new ArgumentException("密文中包含无效字符"); cipherBytes[i] = (byte)charIndex; } byte[] decryptedBytes = RC4Process(cipherBytes); return Encoding.UTF8.GetString(decryptedBytes); } } // 使用示例 public class Demo { public static void Main() { var crypto = new RC4FixedLengthCrypto("MySecureKey123"); string plain = "Hello Word!"; string cipher = crypto.EncryptString(plain); Console.WriteLine($"加密结果:{cipher}"); // 长度与原字符串一致 string decrypted = crypto.DecryptString(cipher); Console.WriteLine($"解密结果:{decrypted}"); // 输出:Hello Word! } }
注意事项
- 自定义映射加密的安全性较低,仅适合对安全性要求不高的场景;流密码(RC4)安全性更强,但需妥善管理密钥。
- 若需支持全字符集加密,需确保映射字符集的覆盖范围足够(如包含256个可见字符),避免出现无法映射的情况。
- 示例中的密钥偏移量或密钥可根据实际需求自定义,提升加密强度。
内容的提问来源于stack exchange,提问作者Praveen Kumar
相关产品推荐
相关产品推荐

