Files
Go_I2p/lib/i2np/build_response_record.go
2025-02-11 13:15:47 +01:00

134 lines
3.4 KiB
Go

package i2np
import (
"errors"
"github.com/sirupsen/logrus"
common "github.com/go-i2p/go-i2p/lib/common/data"
)
/*
I2P I2NP BuildResponseRecord
https://geti2p.net/spec/i2np#buildresponserecord
Accurate for version 0.9.65
Encrypted:
bytes 0-527 :: AES-encrypted record (note: same size as BuildRequestRecord)
Unencrypted:
+----+----+----+----+----+----+----+----+
| |
+ +
| |
+ SHA-256 Hash of following bytes +
| |
+ +
| |
+----+----+----+----+----+----+----+----+
| random data... |
~ ~
| |
+ +----+
| | ret|
+----+----+----+----+----+----+----+----+
bytes 0-31 :: SHA-256 Hash of bytes 32-527
bytes 32-526 :: random data
byte 527 :: reply
total length: 528
*/
type (
BuildResponseRecordELGamalAES [528]byte
BuildResponseRecordELGamal [528]byte
)
/*
BuildResponseRecord struct contains a response to BuildRequestRecord
concerning the creation of one hop in the tunnel
*/
type BuildResponseRecord struct {
Hash common.Hash
RandomData [495]byte
Reply byte
}
var ERR_BUILD_RESPONSE_RECORD_NOT_ENOUGH_DATA = errors.New("not enough i2np build request record data")
func ReadBuildResponseRecord(data []byte) (BuildResponseRecord, error) {
log.Debug("Reading BuildResponseRecord")
build_response_record := BuildResponseRecord{}
hash, err := readBuildResponseRecordHash(data)
if err != nil {
log.WithError(err).Error("Failed to read Hash")
return build_response_record, err
}
build_response_record.Hash = hash
random_data, err := readBuildResponseRecordRandomData(data)
if err != nil {
log.WithError(err).Error("Failed to read Random Data")
return build_response_record, err
}
build_response_record.RandomData = random_data
reply, err := readBuildResponseRecordReply(data)
if err != nil {
log.WithError(err).Error("Failed to read Reply")
return build_response_record, err
}
build_response_record.Reply = reply
log.Debug("BuildResponseRecord read successfully")
return build_response_record, nil
}
func readBuildResponseRecordHash(data []byte) (common.Hash, error) {
if len(data) < 32 {
return common.Hash{}, ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA
}
hash := common.Hash(data[0:32])
log.WithFields(logrus.Fields{
"at": "i2np.readBuildResponseRecordHash",
"hash": hash,
}).Debug("parsed_build_response_record_hash")
return hash, nil
}
func readBuildResponseRecordRandomData(data []byte) ([495]byte, error) {
if len(data) < 527 {
return [495]byte{}, ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA
}
random_data := [495]byte{}
copy(random_data[:], data[32:527])
log.WithFields(logrus.Fields{
"at": "i2np.readBuildResponseRandomData",
"random_data": random_data,
}).Debug("parsed_build_response_record_random_data")
return random_data, nil
}
func readBuildResponseRecordReply(data []byte) (byte, error) {
if len(data) < 528 {
return byte(0), ERR_BUILD_REQUEST_RECORD_NOT_ENOUGH_DATA
}
reply := data[527]
log.WithFields(logrus.Fields{
"at": "i2np.readBuildResponseReply",
"reply": reply,
}).Debug("parsed_build_response_record_reply")
return reply, nil
}