如何反转此 C# Decode 方法的过程来创建 Encode 方法?

发布于 2024-09-07 23:43:55 字数 1479 浏览 6 评论 0原文

我想知道如何反转下面的 DecodeBinaryBase64 的过程,以便我可以有一个匹配的 Encode 方法。简而言之,如果给出此方法的输出,它将返回与输入相同的字符串。

private static string DecodeBinaryBase64(string stringToDecode)
{
    StringBuilder builder = new StringBuilder();
    foreach (var b in Convert.FromBase64String(stringToDecode))
        builder.Append(string.Format("{0:X2}", b));
    return builder.ToString();
}

这是编码字符串及其解码对应部分的示例。结果是文件的 SHA1 哈希值。上述方法是了解如何解码以获得正确字符串的示例。

编码

/KUGOuoESMWYuDb+BTMK1LaGe7k=

解码

FCA5063AEA0448C598B836FE05330AD4B6867BB9

0xFCA5063AEA0448C598B836FE05330AD4B6867BB9

已更新以反映正确的 SHA1 值感谢 Porges 以及 Dean 'codeka' Hardin 发现的十六进制错误的修复。

已实现的解决方案

这是我现在的实现,它是从 Porges 帖子中提炼成两种方法的。

private static string EncodeFileDigestBase64(string digest)
{
    byte[] result = new byte[digest.Length / 2];

    for (int i = 0; i < digest.Length; i += 2)
        result[i / 2] = byte.Parse(digest.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);

    if (result.Length != 20)
        throw new ArgumentException("Not a valid SHA1 filedigest.");

    return Convert.ToBase64String(result);
}

private static string DecodeFileDigestBase64(string encodedDigest)
{
    byte[] base64bytes = Convert.FromBase64String(encodedDigest);
    return string.Join(string.Empty, base64bytes.Select(x => x.ToString("X2")));
}  

I would like to know how to reverse the process of the below DecodeBinaryBase64 so that I can have a matching Encode method. In short C# code that if given the output of this method it would return the same string that it took as input.

private static string DecodeBinaryBase64(string stringToDecode)
{
    StringBuilder builder = new StringBuilder();
    foreach (var b in Convert.FromBase64String(stringToDecode))
        builder.Append(string.Format("{0:X2}", b));
    return builder.ToString();
}

Here is an example of an encoded string and its decoded counterpart. The result is a SHA1 hash for a file. The above method is an example of understanding how the decoding works to get to the right string.

ENCODED

/KUGOuoESMWYuDb+BTMK1LaGe7k=

DECODED

FCA5063AEA0448C598B836FE05330AD4B6867BB9

or

0xFCA5063AEA0448C598B836FE05330AD4B6867BB9

Updated to reflect correct SHA1 value thanks to Porges and a fix for hex bug found by Dean 'codeka' Hardin.

Implemented Solution

Here is the the implementation I have now, it is from Porges post distilled down to two methods.

private static string EncodeFileDigestBase64(string digest)
{
    byte[] result = new byte[digest.Length / 2];

    for (int i = 0; i < digest.Length; i += 2)
        result[i / 2] = byte.Parse(digest.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);

    if (result.Length != 20)
        throw new ArgumentException("Not a valid SHA1 filedigest.");

    return Convert.ToBase64String(result);
}

private static string DecodeFileDigestBase64(string encodedDigest)
{
    byte[] base64bytes = Convert.FromBase64String(encodedDigest);
    return string.Join(string.Empty, base64bytes.Select(x => x.ToString("X2")));
}  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泛滥成性 2024-09-14 23:43:55

我不相信这在物理上是可能的。问题是 string.Format("{0:X}", b) 将返回 1 或 2 个字符,具体取决于输入字节是否 16 或没有。一旦绳子连接在一起,你就无法知道。

如果您可以修改 DecodeBinaryBase64 方法,使其始终为每个字节附加两个字符,即使用 string.Format("{0:X2}", b) 那么只需一次输入两个字符即可实现这一点。

如果您对 DecodeBinaryBase64 进行了更改,则可以使用以下命令再次转换回来:(

private static string DecodeBinaryBase64(string stringToDecode)
{
    StringBuilder builder = new StringBuilder();
    foreach (var b in Convert.FromBase64String(stringToDecode))
        builder.Append(string.Format("{0:X2}", b));
    return "0x" + builder.ToString();
}

private static string EncodeBinaryBase64(string stringToEncode)
{
    var binary = new List<byte>();
    for(int i = 2; i < stringToEncode.Length; i += 2)
    {
        string s = new string(new [] {stringToEncode[i], stringToEncode[i+1]});
        binary.Add(byte.Parse(s, NumberStyles.HexNumber));
    }
    return Convert.ToBase64String(binary.ToArray());
}

但缺少错误检查等)

I don't believe it's physically possible. The problem is that string.Format("{0:X}", b) will return either 1 or 2 characters depending on whether the input byte is < 16 or not. And you've got no way to know once the string has been joined together.

If you can modify the DecodeBinaryBase64 method so that it always appends two character for each byte, i.e. by using string.Format("{0:X2}", b) then it will be possible by just taking the input string two characters at a time.

If you made that change to your DecodeBinaryBase64, then you can use the following to convert back again:

private static string DecodeBinaryBase64(string stringToDecode)
{
    StringBuilder builder = new StringBuilder();
    foreach (var b in Convert.FromBase64String(stringToDecode))
        builder.Append(string.Format("{0:X2}", b));
    return "0x" + builder.ToString();
}

private static string EncodeBinaryBase64(string stringToEncode)
{
    var binary = new List<byte>();
    for(int i = 2; i < stringToEncode.Length; i += 2)
    {
        string s = new string(new [] {stringToEncode[i], stringToEncode[i+1]});
        binary.Add(byte.Parse(s, NumberStyles.HexNumber));
    }
    return Convert.ToBase64String(binary.ToArray());
}

(Error checking and so on is missing, though)

够钟 2024-09-14 23:43:55

好吧,您将从 Base-64 转换为 ASCII/UTF-8 字符串,然后将每个字符输出为 2 位十六进制值。

我不知道有什么方法可以自动恢复它。您可能需要一次取出两个字符,将它们转换为“char”,然后使用 string.format() 将它们转回字符,也许?

我以前从未见过需要像这样获取十六进制输出并将其转回真正的字符串。希望有帮助。

Well, you're going from Base-64 to an ASCII/UTF-8 string - and then outputting each character as a 2-digit hex value.

I don't know of any way to automatically get that back. You may have to pull out two characters at a time, cast those as a "char", and use string.format() to turn those back into characters, maybe?

I've never seen the need to take hex output like that, and turn it back into a real string before. Hope that helps.

旧街凉风 2024-09-14 23:43:55

所以我稍微扩展了我的答案:

/** Here are the methods in question: **/
string Encode(string input)
{
    return SHA1ToBase64String(StringToBytes(input));
}

string Decode(string input)
{
    return BytesToString(Base64StringToSHA1(input));
}
/****/

string BytesToString(byte[] bytes)
{
    return string.Join("",bytes.Select(x => x.ToString("X2")));
}

byte[] StringToBytes(string input)
{
    var result = new byte[input.Length/2];

    for (var i = 0; i < input.Length; i+=2)
        result[i/2] = byte.Parse(input.Substring(i,2), System.Globalization.NumberStyles.HexNumber);

    return result;
}

string SHA1ToBase64String(byte[] hash)
{
    if (hash.Length != 20)
        throw new Exception("Not an SHA-1 hash.");

    return Convert.ToBase64String(hash);
}

byte[] Base64StringToSHA1(string input)
{
    return Convert.FromBase64String(input);
}

void Main() {

    var encoded = "/KUGOuoESMWYuDb+BTMK1LaGe7k=";

    var decoded = Decode(encoded);
    var reencoded = Encode(decoded);

    Console.WriteLine(encoded == reencoded); //True
    Console.WriteLine(decoded);
    // FCA5063AEA0448C598B836FE05330AD4B6867BB9
}

我想其他评论中的困惑在于你是否想要提供左逆或右逆。

那就是你想要一个函数“f”吗:

f(Decode(x)) == x // "left inverse"

或者:

Decode(f(x)) == x // "right inverse"

我假设是后者,因为你说(其他答案的第一个评论)你希望能够复制微软的编码。 (迪恩指出的 - 你的函数没有提供可逆的输出。):)

无论哪种方式,上面都会重新实现你的版本以获得正确的输出,因此这两个函数是彼此相反的。

So I expanded my answer a bit:

/** Here are the methods in question: **/
string Encode(string input)
{
    return SHA1ToBase64String(StringToBytes(input));
}

string Decode(string input)
{
    return BytesToString(Base64StringToSHA1(input));
}
/****/

string BytesToString(byte[] bytes)
{
    return string.Join("",bytes.Select(x => x.ToString("X2")));
}

byte[] StringToBytes(string input)
{
    var result = new byte[input.Length/2];

    for (var i = 0; i < input.Length; i+=2)
        result[i/2] = byte.Parse(input.Substring(i,2), System.Globalization.NumberStyles.HexNumber);

    return result;
}

string SHA1ToBase64String(byte[] hash)
{
    if (hash.Length != 20)
        throw new Exception("Not an SHA-1 hash.");

    return Convert.ToBase64String(hash);
}

byte[] Base64StringToSHA1(string input)
{
    return Convert.FromBase64String(input);
}

void Main() {

    var encoded = "/KUGOuoESMWYuDb+BTMK1LaGe7k=";

    var decoded = Decode(encoded);
    var reencoded = Encode(decoded);

    Console.WriteLine(encoded == reencoded); //True
    Console.WriteLine(decoded);
    // FCA5063AEA0448C598B836FE05330AD4B6867BB9
}

I guess the confusion in other comments was over whether you want to provide a left-inverse or a right-inverse.

That is do you want a function "f" that does:

f(Decode(x)) == x // "left inverse"

or:

Decode(f(x)) == x // "right inverse"

I assumed the latter, because you said (1st comment on other answer) that you wanted to be able to replicate Microsoft's encoding. (And what Dean noted - your function wasn't providing reversible output.) :)

Either way the above reimplements your version for correct output, so both functions are inverses of each other.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文