Go, средне-состояние SHA-256 хэш - PullRequest
3 голосов
/ 12 февраля 2012

Имеет 128 байтов данных, например:

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca064f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d89b574a864db8345b1b00b5ac00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000

И, желая выполнить хэш SHA-256, нужно разделить его на два 64 байта данных и хешировать их по отдельности, прежде чем хэшировать результаты вместе. Если часто нужно менять некоторые биты во второй половине данных, можно было бы упростить вычисления и хэшировать первую половину данных только один раз. Как можно это сделать в Google Go? Я пытался позвонить

func SingleSHA(b []byte)([]byte){
    var h hash.Hash = sha256.New()
    h.Write(b)
    return h.Sum()
}

Но вместо правильного ответа

e772fc6964e7b06d8f855a6166353e48b2562de4ad037abc889294cea8ed1070

Я получил

12E84A43CBC7689AE9916A30E1AA0F3CA12146CBF886B60103AEC21A5CFAA268

Обсуждая этот вопрос на форуме Биткойн , кто-то упомянул, что могут быть некоторые проблемы с получением этого хеша среднего уровня.

Как рассчитать хеш-код SHA-256 среднего уровня в Google Go?

Ответы [ 4 ]

5 голосов
/ 17 февраля 2012

Операции с биткойнами, связанные с байтами, немного сложны, так как они имеют тенденцию переключать порядковый номер прихоти. Сначала мы берем начальный байтовый массив [], представляющий

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca064f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d89b574a864db8345b1b00b5ac00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000

Затем мы выделяем первую половину массива, получая:

00000001c570c4764aadb3f09895619f549000b8b51a789e7f58ea750000709700000000103ca06 4f8c76c390683f8203043e91466a7fcc40e6ebc428fbcc2d8

После этого нам нужно поменять местами несколько байтов. Мы меняем порядок байтов в каждом срезе по 4 байта, получая таким образом:

0100000076C470C5F0B3AD4A9F619598B80090549E781AB575EA587F977000000000000064A03C10396CC7F820F8830614E94330C4FCA76642BC6E0ED8C2BC8F

И это массив, который мы будем использовать для вычисления среднего состояния. Теперь нам нужно изменить файл hash.go, добавив к type Hash interface:

Midstate() []byte

И измените файл sha256.go, добавив эту функцию:

func (d *digest) Midstate() []byte {
    var answer []byte
    for i:=0;i<len(d.h);i++{
        answer=append(answer[:], Uint322Hex(d.h[i])...)
    }
    return answer
}

Где Uint322Hex преобразует переменную uint32 в переменную []byte. Имея все это, мы можем позвонить:

var h BitSHA.Hash = BitSHA.New()
h.Write(Str2Hex("0100000076C470C5F0B3AD4A9F619598B80090549E781AB575EA587F977000000000000064A03C10396CC7F820F8830614E94330C4FCA76642BC6E0ED8C2BC8F"))
log.Printf("%X", h.Midstate())

Где Str2Hex превращает string в []byte. Результат:

69FC72E76DB0E764615A858F483E3566E42D56B2BC7A03ADCE9492887010EDA8

Запоминание правильного ответа:

e772fc6964e7b06d8f855a6166353e48b2562de4ad037abc889294cea8ed1070

Мы можем сравнить их:

69FC72E7 6DB0E764 615A858F 483E3566 E42D56B2 BC7A03AD CE949288 7010EDA8
e772fc69 64e7b06d 8f855a61 66353e48 b2562de4 ad037abc 889294ce a8ed1070

Итак, мы можем видеть, что нам просто нужно поменять местами байты в каждом срезе по 4 байта, и у нас будет правильное «среднее состояние», используемое пулами и майнерами биткойнов (до тех пор, пока оно больше не понадобится из-за того, что Устаревшее).

3 голосов
/ 12 февраля 2012

Код Go, который у вас есть, является правильным способом для вычисления sha256 потока байтов.

Скорее всего, ответ заключается в том, что вы хотите не sha256. В частности:

нужно было бы разделить его на два 64-битных данных и хешировать их по отдельности, прежде чем хешировать результаты вместе. Если бы часто нужно было менять некоторые биты во второй половине данных, можно было бы упростить вычисления и хэшировать первую половину данных только один раз.

- недопустимый способ вычисления sha256 (прочитайте http://doc.golang.org/src/pkg/crypto/sha256/sha256.go, например, смотрите, что sha256 работает с блоками данных, которые должны быть дополнены и т. Д.).

Алгоритм, который вы описали, рассчитывает что-то, но не sha256.

Поскольку вы знаете ожидаемое значение, вы, вероятно, имеете некоторую эталонную реализацию вашего алгоритма на другом языке, поэтому просто сделайте построчный порт для Go.

Наконец, в любом случае это сомнительная оптимизация. 128 бит это 16 байтов. Стоимость хэширования обычно пропорциональна размеру данных. При 16 байтах затраты настолько малы, что дополнительная попытка быть умной путем разделения данных на 8-байтовые части, вероятно, будет стоить больше, чем вы сохранили.

2 голосов
/ 12 февраля 2012

В sha256.go , в начале функции Sum() реализация создает копию состояния SHA256.Базовый тип данных SHA256 (struct digest) является частным для пакета sha256.

Я бы предложил создать вашу собственную личную копию файла sha256.go (это небольшой файл).Затем добавьте функцию Copy() для сохранения текущего состояния дайджеста:

func (d *digest) Copy() hash.Hash {
    d_copy := *d
    return &d_copy
}

Затем просто вызовите функцию Copy(), чтобы сохранить хеш SHA256 в среднем состоянии.

0 голосов
/ 12 февраля 2012

Я провел два теста Go на 128 байтах данных, используя процессор Intel i5 2,70 ГГц. Сначала 1000 раз я записал все 128 байтов в хеш SHA256 и прочитал сумму, которая заняла в общей сложности около 9 285 000 наносекунд. Во-вторых, я записал первые 64 байта в хеш SHA256 один раз, а затем 1000 раз я записал вторые 64 байта в копию хэша SHA256 и прочитал сумму, что в общей сложности составило около 6 492 371 наносекунд. Второй бенчмарк, который предполагал, что первые 64 байта являются инвариантными, выполнялся на 30% меньше времени, чем первый бенчмарк.

Используя первый метод, вы можете вычислить около 9 305 331 179 SHA256 128-байтовых сумм в день, прежде чем покупать более быстрый ЦП. Используя второй метод, вы можете рассчитать 13 307 927 103 SHA256 128-байтовых сумм в день, предполагая, что первые 64 байта инвариантны 1000 раз подряд, прежде чем покупать более быстрый ЦП. Сколько SHA256 128-байтовых сумм в день вам нужно рассчитать? Для скольких 128-байтовых сумм SHA256 в день первые 64 байта являются инвариантами?

Какие тесты вы проводили и каковы были результаты?

...