Как обратить вспять процесс этого метода C # Decode для создания метода Encode? - PullRequest
1 голос
/ 28 июня 2010

Я хотел бы знать, как отменить процесс описанного ниже 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 для файла.Приведенный выше метод является примером понимания того, как работает декодирование для получения правильной строки.

ENCODED

/ KUGOuoESMWYuDb + BTMK1LaGe7k =

DECODED

FCA5063AEA0448C598B836FE05330AD4B6867BB9

или

0xFCA5063AEA0448C598B836FE05330AD4B6867BB9

* исправлено из-за исправления для исправления ** * * * * * * * * *Дин 'кодека' Хардин обнаружил ошибку.

Внедренное решение

Вот реализация, которая у меня есть сейчас, это из сообщения Поргеса, перебранного до двухметоды.

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 ]

3 голосов
/ 28 июня 2010

Я не верю, что это физически возможно.Проблема в том, что string.Format("{0:X}", b) вернет 1 или 2 символа в зависимости от того, равен ли входной байт <16 или нет.И у вас нет возможности узнать, как только строка была объединена. </p>

Если вы можете изменить метод 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());
}

(хотя проверка ошибок и т. Д. Отсутствует)

0 голосов
/ 28 июня 2010

Поэтому я немного расширил свой ответ:

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

Я предположил последнее, потому что вы сказали (1-й комментарий к другому ответу)что вы хотели бы иметь возможность копировать кодировку Microsoft.(И что заметил Дин - ваша функция не обеспечивала обратимый вывод.):)

В любом случае вышеприведенное переопределяет вашу версию для правильного вывода, поэтому обе функции являются противоположностями друг другу.

0 голосов
/ 28 июня 2010

Итак, вы переходите от Base-64 к строке ASCII / UTF-8 - и затем выводите каждый символ в виде двузначного шестнадцатеричного значения.

Я не знаю ни одного способаавтоматически получить это обратно.Возможно, вам придется извлекать по два символа за раз, приводить их как «char» и использовать string.format (), чтобы превратить их обратно в символы, может быть?

Я никогда не видел необходимостиВозьмите шестнадцатеричный вывод, подобный этому, и превратите его обратно в настоящую строку раньше.Надеюсь, это поможет.

...