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のおかげで正しいSHA1値を反映するように更新され、Dean'codeka'Hardinによって発見されたhexバグが修正されました。

実装されたソリューション

これが私が今持っている実装です、それは2つの方法に蒸留されたポルゲスからのものです。

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各バイトに常に2文字を追加するようにメソッドを変更できる場合、つまりを使用string.Format("{0:X2}", b)することにより、一度に2文字の入力文字列を取得するだけで可能になります。

にその変更を加えた場合は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桁の16進値として出力します。

自動的にそれを取り戻す方法がわかりません。一度に2文字を引き出し、それらを「char」としてキャストし、string.format()を使用してそれらを文字に戻す必要があるかもしれません。

このような16進出力を取得して、実際の文字列に戻す必要があることは、これまで見たことがありません。お役に立てば幸いです。

于 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のエンコーディングを複製できるようにしたいとあなたが言ったからです(他の回答に対する最初のコメント)。(そしてディーンが指摘したこと-あなたの関数は可逆的な出力を提供していませんでした。):)

いずれにせよ、上記は正しい出力のためにバージョンを再実装するので、両方の関数は互いに逆になります。

于 2010-06-28T00:56:00.650 に答える