英文:
How to implement the algorithm for HashCash in Go (type conversion issues)?
问题
我一直在尝试在Go中实现HashCash算法!对于那些不了解的人来说 -
> HashCash是一种阻止垃圾邮件的方法。基本上,一个头部由一些环境变量构成,客户端和服务器都知道(例如电子邮件、时间戳等)。一个随机的nonce被附加到头部的末尾。客户端通过更改nonce来尝试强制产生一个部分哈希碰撞(例如,前x位为0)。
> HashCash之所以有效,是因为找到部分哈希碰撞不那么昂贵。当服务器接收到这个头部时,它会验证其中的信息(因此它只能用于一个会话)并计算出结果哈希。如果前x位为0,那么客户端的机器上已经花费了相当多的时间来计算碰撞(这在垃圾邮件机器人上是不会发生的)。
对我来说,我只是想编写一个程序,找出客户端找到x位部分哈希碰撞所需的时间。
我编写了以下代码,如果int64具有x位的哈希碰撞,则返回true/false。
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个0位
zeroes, e := strconv.Btoi64(unsetBitString, 2) // 64个1位
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()
// 不知道如何将testCollision的前x位转换为int64类型,以便我可以在partialAllZeroes中使用它
英文:
I've been trying to implement the HashCash algorithm in Go! For those of you who don't know -
> HashCash is a method to stop spam. Basically, a header is constructed of some environment variables known both to the client and server (email, timestamp etc.). A random nonce is appended to the end of the header. The client tries to bruteforce a partial hash collision (e.g. where the first x bits are 0) by changing the nonce.
>
> HashCash works because it's not as expensive to find partial hash collisions. When the server receives this header, they verify the information in it (so it can be used only for one session) and compute the resulting hash. If the first x bits are 0, then a good amount of time has been expended on the client's machine, computing the collision (which wouldn't happen on a spambot)
For me, I'm just wanting to write a program which finds the time it takes for a client to find a partial hash collision of x bits.
I wrote this code which will return true/false if the int64 has a hash collision of x bits.
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("")
}
My current problem is I'm having alot of type conversion issues. For example, I am only able to operate on the int64 type, because that's what strconv.Btoi64 returns. Another issue that I'm also looking at is that the hash function returns as a byte array, and I have no idea how to convert that into an int64.
Below is my current hash code -
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
答案1
得分: 4
我建议使用以下代码(函数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)
}
英文:
I would suggest the following code (the function partialAllZeroes
should run much faster):
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)
}
答案2
得分: 1
我建议使用math/big.Int类型。它可以处理大的位集。它有SetString方法,也可以处理二进制(例如"0b101010"
)。使用fmt.Printf或Sprintf可以使用%b
动词从中获取二进制文本字符串。
英文:
I would suggest to use the math/big.Int type. It can handle large bit sets. It has the SetString method which also handles binary (like "0b101010"
). With fmt.Printf or Sprintf one can use the %b
verb to get a binary text string back from it.
答案3
得分: 0
我还建议升级到最新的每周版本(自昨天的RC1以来)。
“go fix”命令将帮助您进行过渡。
然后使用strconv包:
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))
}
英文:
I also suggest to upgrade to the latest weekly (since yesterday RC1).
The "go fix" command will help you in the transition.
Then using 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))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论