mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 03:26:37 +08:00
92 lines
1.9 KiB
Go
92 lines
1.9 KiB
Go
package service
|
|
|
|
import (
|
|
"crypto/sha1" // #nosec G505 -- BitTorrent v1 info-hash is SHA-1 by protocol.
|
|
"encoding/hex"
|
|
)
|
|
|
|
func torrentInfoHash(data []byte) string {
|
|
start, end, ok := torrentInfoBounds(data)
|
|
if !ok {
|
|
return ""
|
|
}
|
|
sum := sha1.Sum(data[start:end]) // #nosec G401 -- BitTorrent v1 info-hash is SHA-1 by protocol, not a security hash.
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
func torrentInfoBounds(data []byte) (int, int, bool) {
|
|
if len(data) == 0 || data[0] != 'd' {
|
|
return 0, 0, false
|
|
}
|
|
pos := 1
|
|
for pos < len(data) && data[pos] != 'e' {
|
|
keyStart, keyEnd, next, ok := parseBencodeString(data, pos)
|
|
if !ok {
|
|
return 0, 0, false
|
|
}
|
|
valueStart := next
|
|
valueEnd, ok := bencodeValueEnd(data, valueStart)
|
|
if !ok {
|
|
return 0, 0, false
|
|
}
|
|
if string(data[keyStart:keyEnd]) == "info" {
|
|
return valueStart, valueEnd, true
|
|
}
|
|
pos = valueEnd
|
|
}
|
|
return 0, 0, false
|
|
}
|
|
|
|
func parseBencodeString(data []byte, pos int) (int, int, int, bool) {
|
|
if pos >= len(data) || data[pos] < '0' || data[pos] > '9' {
|
|
return 0, 0, 0, false
|
|
}
|
|
length := 0
|
|
for pos < len(data) && data[pos] >= '0' && data[pos] <= '9' {
|
|
length = length*10 + int(data[pos]-'0')
|
|
pos++
|
|
}
|
|
if pos >= len(data) || data[pos] != ':' {
|
|
return 0, 0, 0, false
|
|
}
|
|
start := pos + 1
|
|
end := start + length
|
|
if end > len(data) {
|
|
return 0, 0, 0, false
|
|
}
|
|
return start, end, end, true
|
|
}
|
|
|
|
func bencodeValueEnd(data []byte, pos int) (int, bool) {
|
|
if pos >= len(data) {
|
|
return 0, false
|
|
}
|
|
switch data[pos] {
|
|
case 'i':
|
|
end := pos + 1
|
|
for end < len(data) && data[end] != 'e' {
|
|
end++
|
|
}
|
|
if end >= len(data) {
|
|
return 0, false
|
|
}
|
|
return end + 1, true
|
|
case 'l', 'd':
|
|
end := pos + 1
|
|
for end < len(data) && data[end] != 'e' {
|
|
next, ok := bencodeValueEnd(data, end)
|
|
if !ok {
|
|
return 0, false
|
|
}
|
|
end = next
|
|
}
|
|
if end >= len(data) {
|
|
return 0, false
|
|
}
|
|
return end + 1, true
|
|
default:
|
|
_, _, next, ok := parseBencodeString(data, pos)
|
|
return next, ok
|
|
}
|
|
}
|