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

时间:2010-06-27 23:48:00

标签: c# encoding .net-4.0 decoding

我想知道如何反转下面的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哈希。上述方法是了解解码如何工作以获得正确字符串的示例。

ENCODED

/ KUGOuoESMWYuDb + BTMK1LaGe7k =

DECODED

FCA5063AEA0448C598B836FE05330AD4B6867BB9

0xFCA5063AEA0448C598B836FE05330AD4B6867BB9

更新以反映正确的SHA1值,这要归功于Porges和Dean'codeka'Dadin发现的六角虫修复。

已实施解决方案

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

3 个答案:

答案 0 :(得分:3)

我不相信它在身体上是可能的。问题是string.Format("{0:X}", b)将返回1或2个字符,具体取决于输入字节是否为&lt; 1。 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());
}

(但是缺少错误检查等等)

答案 1 :(得分:0)

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

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

我从未见过像这样需要采用十六进制输出,并且之前将它变回真正的字符串。希望有所帮助。

答案 2 :(得分: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"

我假设后者,因为你说(其他答案的第一条评论)你希望能够复制微软的编码。 (而Dean指出 - 你的功能并没有提供可逆输出。):)

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