我需要通过互联网发送一个大约30个字符的字符串,这个字符串最终可能会成为另一家公司数据库中的ID。
虽然这个字符串本身不会被识别,但我希望它在任何情况下都不可辨认。
在.NET中,最简单的方法是什么,可以使这样的字符串混淆,以便在必要时轻松地恢复?
我需要通过互联网发送一个大约30个字符的字符串,这个字符串最终可能会成为另一家公司数据库中的ID。
虽然这个字符串本身不会被识别,但我希望它在任何情况下都不可辨认。
在.NET中,最简单的方法是什么,可以使这样的字符串混淆,以便在必要时轻松地恢复?
请勿将此答案用于任何需要保密的信息。
它会使字符串对人类来说难以阅读。
它可以往返转换,但如果您的字符串不是“普通”的,并且使用了较大的偏移值,则可能无法转换回原始状态。
这段代码无法防止有组织的破解尝试。一个聪明而有技巧的人可以用纸和笔解码它。
如何尝试一些古典风格的东西(带有现代的变化)?
public static string Caesar(this string source, Int16 shift)
{
var maxChar = Convert.ToInt32(char.MaxValue);
var minChar = Convert.ToInt32(char.MinValue);
var buffer = source.ToCharArray();
for (var i = 0; i < buffer.Length; i++)
{
var shifted = Convert.ToInt32(buffer[i]) + shift;
if (shifted > maxChar)
{
shifted -= maxChar;
}
else if (shifted < minChar)
{
shifted += maxChar;
}
buffer[i] = Convert.ToChar(shifted);
}
return new string(buffer);
}
显然你会这样使用
var plain = "Wibble";
var caesered = plain.Caesar(42);
var newPlain = caesered.Caesar(-42);
shift
和Unicode的某些组合可能会产生不映射到实际Unicode代码点的char
值。如果数据在两个.NET组件之间以二进制形式传输,则没有问题,但是当通过HTTP返回给未知浏览器时,我无法确定会发生什么。如果您可以限制字符串中的char值范围和shift的大小,那么您可能会没事,但我倾向于找到“铸铁”替代方案。 - Jodrell怎么样:
Convert.ToBase64String(Encoding.UTF8.GetBytes(myString));
及其逆命题:
Encoding.UTF8.GetString(Convert.FromBase64String(myObfuscatedString));
只要您不介意字符串长度的增加。我受到@Jodrell的回答启发,这是我的替代版本。唯一的真正区别是我使用模运算符而不是if-then-else结构。
如果你和我一样以前从未听说过凯撒密码,这里有一个链接:
https://en.wikipedia.org/wiki/Caesar_cipher
public static partial class MString
{
...
/// <summary>
/// Method to perform a very simple (and classical) encryption for a string. This is NOT at
/// all secure, it is only intended to make the string value non-obvious at a first glance.
///
/// The shiftOrUnshift argument is an arbitrary "key value", and must be a non-zero integer
/// between -65535 and 65535 (inclusive). To decrypt the encrypted string you use the negative
/// value. For example, if you encrypt with -42, then you decrypt with +42, or vice-versa.
///
/// This is inspired by, and largely based on, this:
/// https://dev59.com/8Wcs5IYBdhLWcg3wOBbl#13026595
/// </summary>
/// <param name="inputString">string to be encrypted or decrypted, must not be null</param>
/// <param name="shiftOrUnshift">see above</param>
/// <returns>encrypted or decrypted string</returns>
public static string CaesarCipher(string inputString, int shiftOrUnshift)
{
// Check C# is still C#
Debug.Assert(char.MinValue == 0 && char.MaxValue == UInt16.MaxValue);
const int C64K = UInt16.MaxValue + 1;
// Check the arguments
if (inputString == null)
throw new ArgumentException("Must not be null.", "inputString");
if (shiftOrUnshift == 0)
throw new ArgumentException("Must not be zero.", "shiftOrUnshift");
if (shiftOrUnshift <= -C64K || shiftOrUnshift >= C64K)
throw new ArgumentException("Out of range.", "shiftOrUnshift");
// Perform the Caesar cipher shifting, using modulo operator to provide wrap-around
char[] charArray = new char[inputString.Length];
for (int i = 0; i < inputString.Length; i++)
{
charArray[i] =
Convert.ToChar((Convert.ToInt32(inputString[i]) + shiftOrUnshift + C64K) % C64K);
}
// Return the result as a new string
return new string(charArray);
}
...
}
还有一些测试代码:
// Test CaesarCipher() method
const string CHelloWorld = "Hello world!";
const int CCaesarCipherKey = 42;
string caesarCiphered = MString.CaesarCipher(CHelloWorld, CCaesarCipherKey);
if (MString.CaesarCipher(caesarCiphered, -CCaesarCipherKey) != CHelloWorld)
throw new Exception("Oh no!");