mirror of
https://github.com/fumiama/WireGold.git
synced 2026-06-09 18:40:36 +08:00
fix: multi-segment hash checking
This commit is contained in:
@@ -17,18 +17,21 @@ import (
|
||||
// PreCRC64 calculate crc64 checksum without idxdatsz.
|
||||
func (p *Packet) PreCRC64() (crc uint64) {
|
||||
w := bin.SelectWriter()
|
||||
// 固定 TTL 为 0 计算
|
||||
// 固定 TTL 为 0, flag 为空 计算
|
||||
if bin.IsLittleEndian {
|
||||
ttl := p.TTL
|
||||
f := p.Proto
|
||||
p.TTL = 0
|
||||
p.Proto &= protobit
|
||||
w.Write((*[PacketHeadNoCRCLen]byte)(
|
||||
(unsafe.Pointer)(p),
|
||||
)[:])
|
||||
p.TTL = ttl
|
||||
p.Proto = f
|
||||
} else {
|
||||
w.WriteUInt32(p.idxdatsz)
|
||||
w.WriteUInt32(uint32(p.randn))
|
||||
w.WriteUInt16(uint16(p.Proto)) // TTL is set to 0
|
||||
w.WriteUInt16(uint16(p.Proto & protobit)) // TTL, flags is set to 0
|
||||
w.WriteUInt16(p.SrcPort)
|
||||
w.WriteUInt16(p.DstPort)
|
||||
w.WriteUInt16(p.Offset)
|
||||
@@ -58,9 +61,9 @@ func (p *Packet) WriteHeaderTo(buf *bytes.Buffer) {
|
||||
pbuf.NewBytes(buf.Len()).V(func(b []byte) {
|
||||
copy(b, buf.Bytes())
|
||||
ClearTTL(b)
|
||||
p.md5h8rem = int64(algo.MD5Hash8(b))
|
||||
p.md5h8 = algo.MD5Hash8(b)
|
||||
})
|
||||
_ = binary.Write(buf, binary.LittleEndian, p.md5h8rem)
|
||||
_ = binary.Write(buf, binary.LittleEndian, p.md5h8)
|
||||
return
|
||||
}
|
||||
w := bin.SelectWriter()
|
||||
@@ -76,10 +79,10 @@ func (p *Packet) WriteHeaderTo(buf *bytes.Buffer) {
|
||||
pbuf.NewBytes(buf.Len()).V(func(b []byte) {
|
||||
copy(b, buf.Bytes())
|
||||
ClearTTL(b)
|
||||
p.md5h8rem = int64(algo.MD5Hash8(b))
|
||||
p.md5h8 = algo.MD5Hash8(b)
|
||||
})
|
||||
})
|
||||
w.WriteUInt64(uint64(p.md5h8rem))
|
||||
w.WriteUInt64(p.md5h8)
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
_, _ = buf.ReadFrom(b)
|
||||
})
|
||||
|
||||
@@ -69,11 +69,11 @@ func (pb *HeaderBuilder) Dst(ip net.IP, p uint16) *HeaderBuilder {
|
||||
func (pb *HeaderBuilder) With(data []byte) *DataBuilder {
|
||||
return (*DataBuilder)(pb.p(func(ub *PacketBuf) {
|
||||
// header crc64 except idxdatasz
|
||||
ub.DAT.md5h8rem = int64(ub.DAT.PreCRC64())
|
||||
ub.DAT.md5h8 = ub.DAT.PreCRC64()
|
||||
// plain data
|
||||
ub.Buffer.Write(data)
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln(file.Header(), strconv.FormatUint(uint64(ub.DAT.md5h8rem), 16), "build with data", file.ToLimitHexString(data, 64))
|
||||
logrus.Debugln(file.Header(), strconv.FormatUint(ub.DAT.md5h8, 16), "build with data", file.ToLimitHexString(data, 64))
|
||||
}
|
||||
}))
|
||||
}
|
||||
@@ -89,16 +89,16 @@ func (pb *DataBuilder) Zstd() *DataBuilder {
|
||||
ub.Reset()
|
||||
data.V(func(b []byte) { ub.Write(b) })
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln(file.Header(), strconv.FormatUint(uint64(ub.DAT.md5h8rem), 16), "data after zstd", file.ToLimitHexString(ub.Bytes(), 64))
|
||||
logrus.Debugln(file.Header(), strconv.FormatUint(ub.DAT.md5h8, 16), "data after zstd", file.ToLimitHexString(ub.Bytes(), 64))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (pb *DataBuilder) Hash() *DataBuilder {
|
||||
return pb.p(func(ub *PacketBuf) {
|
||||
ub.DAT.hash = algo.Blake2bHash8(
|
||||
uint64(ub.DAT.md5h8rem), ub.Bytes(),
|
||||
)
|
||||
ub.DAT.hashrem = int64(algo.Blake2bHash8(
|
||||
ub.DAT.md5h8, ub.Bytes(),
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func (pb *DataBuilder) Seal(aead cipher.AEAD, teatyp uint8, additional uint16) *
|
||||
p(func(ub *PacketBuf) {
|
||||
// encrypted data: chacha20(hash + plain)
|
||||
w := bin.SelectWriter()
|
||||
w.WriteUInt64(ub.DAT.hash)
|
||||
w.WriteUInt64(uint64(ub.DAT.hashrem))
|
||||
w.Write(ub.Bytes())
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
data := algo.EncodeAEAD(aead, additional, b.Bytes())
|
||||
@@ -133,7 +133,7 @@ func (pb *DataBuilder) Plain(teatyp uint8, additional uint16) *PacketBuilder {
|
||||
return (*PacketBuilder)(pb.tea(teatyp).additional(additional).
|
||||
p(func(ub *PacketBuf) {
|
||||
w := bin.SelectWriter()
|
||||
w.WriteUInt64(ub.DAT.hash)
|
||||
w.WriteUInt64(uint64(ub.DAT.hashrem))
|
||||
w.Write(ub.Bytes())
|
||||
w.P(func(b *pbuf.Buffer) {
|
||||
ub.Reset()
|
||||
|
||||
@@ -3,6 +3,7 @@ package head
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"github.com/fumiama/orbyte"
|
||||
@@ -13,8 +14,8 @@ const (
|
||||
// PacketHeadPreCRCIdx skip idxdatsz, which will be set at Seal().
|
||||
PacketHeadPreCRCIdx = unsafe.Offsetof(Packet{}.randn)
|
||||
// PacketHeadNoCRCLen without final crc
|
||||
PacketHeadNoCRCLen = unsafe.Offsetof(Packet{}.md5h8rem)
|
||||
PacketHeadLen = unsafe.Offsetof(Packet{}.hash)
|
||||
PacketHeadNoCRCLen = unsafe.Offsetof(Packet{}.md5h8)
|
||||
PacketHeadLen = unsafe.Offsetof(Packet{}.hashrem)
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -57,19 +58,18 @@ type Packet struct {
|
||||
src [4]byte
|
||||
// dst 目的 ip (ipv4)
|
||||
dst [4]byte
|
||||
// md5h8rem 发送时记录包头字段除自身外的 checksum 值,
|
||||
// 接收时记录剩余字节数.
|
||||
// md5h8 发送时记录包头字段除自身外的 checksum 值.
|
||||
//
|
||||
// 可以认为在一定时间内唯一 (现已更改算法为 md5 但名字未变)。
|
||||
md5h8rem int64
|
||||
md5h8 uint64
|
||||
|
||||
// 以下字段为包体, 与 data 一起加密
|
||||
|
||||
// hash 使用 BLAKE2B 生成加密前 packet data+crc64 的摘要,
|
||||
// 取其前 8 字节, 小端序读写.
|
||||
// hashrem 使用 BLAKE2B 生成加密前 packet data+crc64 的摘要,
|
||||
// 取其前 8 字节, 小端序读写. 接收时记录剩余字节数.
|
||||
//
|
||||
// https://github.com/fumiama/blake2b-simd
|
||||
hash uint64
|
||||
hashrem int64
|
||||
|
||||
// Buffer 用于 builder with 暂存原始包体数据
|
||||
// 以及接收时保存 body, 通过 PacketBytes 截取偏移.
|
||||
@@ -92,7 +92,7 @@ func (p *Packet) Size() int {
|
||||
|
||||
// CRC64 extract md5h8rem field
|
||||
func (p *Packet) CRC64() uint64 {
|
||||
return uint64(p.md5h8rem)
|
||||
return p.md5h8
|
||||
}
|
||||
|
||||
func (p *Packet) Src() net.IP {
|
||||
@@ -102,3 +102,7 @@ func (p *Packet) Src() net.IP {
|
||||
func (p *Packet) Dst() net.IP {
|
||||
return append(net.IP{}, p.dst[:]...)
|
||||
}
|
||||
|
||||
func (p *Packet) HasFinished() bool {
|
||||
return atomic.LoadInt64(&p.hashrem) <= 0
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ func ParsePacketHeader(data []byte) (pbytes PacketBytes, err error) {
|
||||
pb.DAT.Offset = binary.LittleEndian.Uint16(data[14:16])
|
||||
copy(pb.DAT.src[:], data[16:20])
|
||||
copy(pb.DAT.dst[:], data[20:24])
|
||||
pb.DAT.md5h8rem = int64(binary.LittleEndian.Uint64(data[24:32]))
|
||||
pb.DAT.md5h8 = binary.LittleEndian.Uint64(data[24:32])
|
||||
}
|
||||
sz = pb.DAT.Size()
|
||||
if !pb.DAT.Proto.IsValid() {
|
||||
@@ -60,10 +60,10 @@ func ParsePacketHeader(data []byte) (pbytes PacketBytes, err error) {
|
||||
ClearTTL(b)
|
||||
crc = algo.MD5Hash8(b)
|
||||
})
|
||||
if crc != uint64(pb.DAT.md5h8rem) {
|
||||
if crc != pb.DAT.md5h8 {
|
||||
err = ErrBadCRCChecksum
|
||||
if config.ShowDebugLog {
|
||||
logrus.Warnf("[unbox] exp crc %016x but got %016x", pb.DAT.md5h8rem, crc)
|
||||
logrus.Warnf("[unbox] exp crc %016x but got %016x", pb.DAT.md5h8, crc)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -72,12 +72,12 @@ func ParsePacketHeader(data []byte) (pbytes PacketBytes, err error) {
|
||||
}
|
||||
if sz+int(PacketHeadLen) == len(data) {
|
||||
pb.Buffer.Write(data[PacketHeadLen:])
|
||||
pb.DAT.md5h8rem = -1
|
||||
pb.DAT.hashrem = -1
|
||||
return
|
||||
}
|
||||
pb.Buffer.Grow(sz)
|
||||
pb.Buffer.Write(make([]byte, sz))
|
||||
pb.DAT.md5h8rem = int64(sz)
|
||||
pb.DAT.hashrem = int64(sz)
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
@@ -92,7 +92,7 @@ func ParsePacketHeader(data []byte) (pbytes PacketBytes, err error) {
|
||||
//
|
||||
// return: complete.
|
||||
func (p *Packet) WriteDataSegment(data, buf []byte) bool {
|
||||
if atomic.LoadInt64(&p.md5h8rem) <= 0 {
|
||||
if p.HasFinished() {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -103,21 +103,24 @@ func (p *Packet) WriteDataSegment(data, buf []byte) bool {
|
||||
}
|
||||
|
||||
if offset == 0 {
|
||||
p.randn = int32(binary.LittleEndian.Uint32(data[4:8]))
|
||||
p.Proto = flags
|
||||
p.TTL = data[9]
|
||||
p.Offset = 0
|
||||
p.md5h8 = binary.LittleEndian.Uint64(data[24:32])
|
||||
if config.ShowDebugLog {
|
||||
logrus.Debugln("[unbox] parse data set zero offset flags", flags)
|
||||
}
|
||||
}
|
||||
|
||||
rembytes := atomic.LoadInt64(&p.md5h8rem)
|
||||
rembytes := atomic.LoadInt64(&p.hashrem)
|
||||
if rembytes > 0 {
|
||||
n := int64(copy(buf[offset:], data[PacketHeadLen:]))
|
||||
newrem := rembytes - n
|
||||
for !atomic.CompareAndSwapInt64(&p.md5h8rem, rembytes, newrem) {
|
||||
rembytes = atomic.LoadInt64(&p.md5h8rem)
|
||||
for !atomic.CompareAndSwapInt64(&p.hashrem, rembytes, newrem) {
|
||||
rembytes = atomic.LoadInt64(&p.hashrem)
|
||||
newrem = rembytes - n
|
||||
}
|
||||
}
|
||||
return atomic.LoadInt64(&p.md5h8rem) <= 0
|
||||
return p.HasFinished()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user