Initial commit

This commit is contained in:
wuka
2026-09-24 11:33:28 +02:00
commit bc38ade3f9
20 changed files with 1607 additions and 0 deletions

73
record.go Normal file
View File

@@ -0,0 +1,73 @@
package lafsession
import (
"crypto/cipher"
"encoding/binary"
"golang.org/x/crypto/chacha20poly1305"
)
const (
recordHeaderLen = 1 + 8
recordTypeData byte = 0x10
recordTypeClose byte = 0x11
)
func newAEAD(key []byte) (cipher.AEAD, error) {
return chacha20poly1305.New(key)
}
func sealRecord(aead cipher.AEAD, seq uint64, recType byte, plaintext, dst []byte, nonce *[nonceLen]byte, aad *[recordHeaderLen]byte) []byte {
aad[0] = recType
binary.BigEndian.PutUint64(aad[1:], seq)
for i := 0; i < 4; i++ {
nonce[i] = 0
}
binary.BigEndian.PutUint64(nonce[4:], seq)
need := recordHeaderLen + len(plaintext) + aead.Overhead()
if cap(dst) < need {
dst = make([]byte, need)
} else {
dst = dst[:need]
}
dst[0] = recType
binary.BigEndian.PutUint64(dst[1:9], seq)
_ = aead.Seal(dst[recordHeaderLen:recordHeaderLen], nonce[:], plaintext, aad[:])
return dst
}
// openRecord decrypts a full frame. Returns record type and plaintext (reusing dst when possible).
func openRecord(aead cipher.AEAD, frame, dst []byte, nonce *[nonceLen]byte, aad *[recordHeaderLen]byte) (recType byte, plaintext []byte, err error) {
if len(frame) < recordHeaderLen+aead.Overhead() {
return 0, nil, ErrShortMessage
}
recType = frame[0]
seq := binary.BigEndian.Uint64(frame[1:9])
aad[0] = recType
binary.BigEndian.PutUint64(aad[1:], seq)
for i := 0; i < 4; i++ {
nonce[i] = 0
}
binary.BigEndian.PutUint64(nonce[4:], seq)
ct := frame[recordHeaderLen:]
ptLen := len(ct) - aead.Overhead()
if ptLen < 0 {
return 0, nil, ErrShortMessage
}
if cap(dst) < ptLen {
dst = make([]byte, ptLen)
} else {
dst = dst[:ptLen]
}
out, err := aead.Open(dst[:0], nonce[:], ct, aad[:])
if err != nil {
return 0, nil, ErrBadTag
}
return recType, out, nil
}