如何实现Go中HashCash的算法(类型转换问题)?
我一直在尝试在Go中实现HashCash算法!对于那些不知道的人- HashCash是一种阻止垃圾邮件的方法。基本上,报头是由客户端和服务器都知道的一些环境变量(电子邮件、时间戳等)构成的。将随机nonce追加到标头的末尾。客户端试图通过更改nonce来强制执行部分哈希冲突(例如,前x位为0) HashCash之所以有效,是因为查找部分散列冲突没有那么昂贵。当服务器接收到这个头时,它们会验证其中的信息(因此它只能用于一个会话)并计算结果哈希。如果前x位为0,则在客户端机器上花费了大量时间来计算冲突(这在spambot上不会发生) 对我来说,我只是想写一个程序,找出客户端查找x位的部分哈希冲突所需的时间 我编写了这段代码,如果int64有x位的哈希冲突,它将返回true/false 我目前的问题是我有很多类型转换问题。例如,我只能对int64类型进行操作,因为strconv.Btoi64会返回该类型。另一个我也在关注的问题是散列函数以字节数组的形式返回,我不知道如何将其转换为int64 下面是我当前的哈希代码-如何实现Go中HashCash的算法(类型转换问题)?,hash,casting,bit-manipulation,go,Hash,Casting,Bit Manipulation,Go,我一直在尝试在Go中实现HashCash算法!对于那些不知道的人- HashCash是一种阻止垃圾邮件的方法。基本上,报头是由客户端和服务器都知道的一些环境变量(电子邮件、时间戳等)构成的。将随机nonce追加到标头的末尾。客户端试图通过更改nonce来强制执行部分哈希冲突(例如,前x位为0) HashCash之所以有效,是因为查找部分散列冲突没有那么昂贵。当服务器接收到这个头时,它们会验证其中的信息(因此它只能用于一个会话)并计算结果哈希。如果前x位为0,则在客户端机器上花费了大量时间来计算冲
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
我建议使用这种类型。它可以处理大型位集。它的方法也可以处理二进制文件(如
“0b101010”
)。使用fmt.Printf或Sprintf,可以使用%b
动词从中获取二进制文本字符串。我建议使用该类型。它可以处理大型位集。它的方法也可以处理二进制文件(如“0b101010”
)。使用fmt.Printf或Sprintf,可以使用%b
动词从中获取二进制文本字符串。我还建议升级到最新的每周(从昨天的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))
}
我还建议升级到最新的每周(从昨天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))
}
我建议使用以下代码(函数
partialallzeros
应该运行得更快):
我建议使用以下代码(函数
partialallzeros
应该运行得更快):
我不熟悉Go,所以这可能是正常的,但为什么涉及字符串?我不熟悉Go,所以这可能是正常的,但为什么涉及字符串?如果
zeroCount
为10,b
必须以10个零位开始。8位构成1字节,因此b
必须以一个零字节开始,后跟2个零位(8+2=10)。|如果zeroCount
为20,b
必须以2个零字节开始,后跟4个零位(2*8+4=20)。掩码:=0xFF>>uint(8-zeroCount)这将产生与开关情况相同的结果如果zeroCount
为10,b
必须以10个零位开始。8位构成1字节,因此b
必须以一个零字节开始,后跟2个零位(8+2=10)。|如果zeroCount
为20,b
必须以2个零字节开始,后跟4个零位(2*8+4=20)。掩码:=0xFF>>uint(8-zeroCount)这将产生与开关情况相同的结果知道实现了另一个新的go函数很好,尽管知道实现了另一个新的go函数也很好
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)
}