Как реализовать алгоритм для HashCash в Go (проблемы с преобразованием типов)? - PullRequest
0 голосов
/ 14 марта 2012

Я пытался реализовать алгоритм HashCash в Go!Для тех из вас, кто не знает -

HashCash - это способ остановить спам.По сути, заголовок состоит из некоторых переменных среды, известных как клиенту, так и серверу (электронная почта, отметка времени и т. Д.).Случайный одноразовый номер добавляется в конец заголовка.Клиент пытается перехватить частичное столкновение хеша (например, где первые x биты равны 0), изменяя одноразовый номер.

HashCash работает, потому что не так дорого найти частичные коллизии хешей.Когда сервер получает этот заголовок, он проверяет информацию в нем (так что он может использоваться только для одного сеанса) и вычисляет результирующий хэш.Если первые x биты равны 0, то на компьютере клиента было потрачено значительное количество времени, чтобы вычислить коллизию (которая не произошла бы на спамботе)

Для меня я просто хочу написать программу, которая находит время, которое требуется клиенту, чтобы найти частичное столкновение хеша x бит.

Я написал этот код, который будет возвращать true / false, если int64 имеет хеш-коллизию x бит.

func partialAllZeroes (zeroCount uint8, val int64) (bool, os.Error) {
    setBitString := "1111111111111111111111111111111111111111111111111111111111111111"
    unsetBitString := "0000000000000000000000000000000000000000000000000000000000000000"
    setBitString = setBitString[0:zeroCount-1]
    unsetBitString = unsetBitString[0:zeroCount-1]

    zeroTest, e := strconv.Btoi64(setBitString, 2) // 64 0bits
    zeroes, e   := strconv.Btoi64(unsetBitString, 2) // 64 1bits

    if e != nil {
        return false, e
    }
    result := val & zeroTest
    switch {
        case result == zeroes:
            return true, nil
        case result != zeroes:
            return false, nil
    }

    return false, os.NewError("")
}

Мой текущийПроблема в том, что у меня много проблем с преобразованием типов.Например, я могу работать только с типом int64 , потому что это то, что возвращает strconv.Btoi64 .Другая проблема, на которую я также обращаю внимание, заключается в том, что хеш-функция возвращается в виде байтового массива, и я понятия не имею, как преобразовать ее в int64 .

Ниже мой текущий хэш-код -

hasher := sha1.New()
baseCollisionString := "BASE COLLISION STRING"
nonce := "12345"
hasher.Write([]byte(strings.Join(baseCollisionString, nonce)))
testCollision := hasher.Sum()
// Somehow I must convert the first x bits of testCollision into an int64 type, so I can use partialAllZeroes with it

Ответы [ 3 ]

4 голосов
/ 14 марта 2012

Я бы предложил следующий код (функция partialAllZeroes должна работать намного быстрее):

package main

import "crypto/sha1"

func partialAllZeroes(zeroCount uint8, b []byte) bool {
    i := 0
    for zeroCount >= 8 {
        if b[i] != 0 {
            return false
        }
        i++
        zeroCount -= 8
    }

    var mask byte
    switch zeroCount {
    case 0: mask = 0x00
    case 1: mask = 0x01
    case 2: mask = 0x03
    case 3: mask = 0x07
    case 4: mask = 0x0f
    case 5: mask = 0x1f
    case 6: mask = 0x3f
    case 7: mask = 0x7f
    }

    return (b[i] & mask) == 0
}

func main() {
    hasher := sha1.New()
    baseCollisionString := "BASE COLLISION STRING"
    nonce := "12345"
    hasher.Write([]byte(baseCollisionString + nonce))
    testCollision := hasher.Sum()
    partialAllZeroes(100, testCollision)
}
1 голос
/ 14 марта 2012

Я бы предложил использовать тип math / big.Int .Он может обрабатывать большие наборы битов.Он имеет метод SetString , который также обрабатывает двоичные файлы (например, "0b101010").С помощью fmt.Printf или Sprintf можно использовать глагол %b, чтобы получить от него двоичную текстовую строку.

0 голосов
/ 14 марта 2012

Я также предлагаю обновиться до последней еженедельной версии (со вчерашнего дня RC1). Команда "go fix" поможет вам в переходе.

Затем с помощью strconv pkg:

package main

import (
        "fmt"
        "strconv"
        "reflect"
)

func main() {
        a := []byte{ '1', '1', '1', '0', '1', '0', '1', '1' }

        b, err := strconv.ParseInt(string(a[:3]), 2, 64)
        if err != nil {
                fmt.Println(err)
                return
        }

        fmt.Println(b, reflect.TypeOf(b))
}
...