1

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

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

由于 Porges 和 Dean 'codeka' Hardin 发现的十六进制错误修复,更新以反映正确的 SHA1 值。

已实施的解决方案

这是我现在拥有的实现,它是从 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")));
}  
4

3 回答 3

3

我不相信这在物理上是可能的。问题是string.Format("{0:X}", b)根据输入字节是否小于 16 将返回 1 或 2 个字符。一旦字符串连接在一起,您就无法知道。

如果您可以修改该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());
}

(不过,缺少错误检查等)

于 2010-06-27T23:53:08.140 回答
0

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

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

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

于 2010-06-27T23:54:27.697 回答
0

所以我扩大了我的答案:

/** 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"

我假设后者,因为您说(对其他答案的第一条评论)您希望能够复制 Microsoft 的编码。(以及 Dean 指出的 - 你的函数没有提供可逆输出。):)

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

于 2010-06-28T00:56:00.650 回答