mirror of
https://github.com/go-i2p/go-i2p.git
synced 2025-06-16 22:10:48 -04:00
208 lines
5.7 KiB
Go
208 lines
5.7 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"encoding/binary"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/go-i2p/go-i2p/lib/crypto"
|
|
)
|
|
|
|
/*
|
|
I2P Encrypted Tunnel Message
|
|
https://geti2p.net/spec/tunnel-message
|
|
Accurate for version 0.9.11
|
|
+----+----+----+----+----+----+----+----+
|
|
| Tunnel ID | IV |
|
|
+----+----+----+----+ +
|
|
| |
|
|
+ +----+----+----+----+
|
|
| | |
|
|
+----+----+----+----+ +
|
|
| |
|
|
+ Encrypted Data +
|
|
~ ~
|
|
| |
|
|
+ +-------------------+
|
|
| |
|
|
+----+----+----+----+
|
|
|
|
Tunnel ID :: TunnelId
|
|
4 bytes
|
|
the ID of the next hop
|
|
|
|
IV ::
|
|
16 bytes
|
|
the initialization vector
|
|
|
|
Encrypted Data ::
|
|
1008 bytes
|
|
the encrypted tunnel message
|
|
|
|
total size: 1028 Bytes
|
|
|
|
|
|
|
|
I2P Decrypted Tunnel Message
|
|
https://geti2p.net/spec/tunnel-message
|
|
Accurate for version 0.9.11
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
| Tunnel ID | IV |
|
|
+----+----+----+----+ +
|
|
| |
|
|
+ +----+----+----+----+
|
|
| | Checksum |
|
|
+----+----+----+----+----+----+----+----+
|
|
| nonzero padding... |
|
|
~ ~
|
|
| |
|
|
+ +----+
|
|
| |zero|
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
| Delivery Instructions 1 |
|
|
~ ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ I2NP Message Fragment 1 +
|
|
| |
|
|
~ ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
| Delivery Instructions 2... |
|
|
~ ~
|
|
| |
|
|
+----+----+----+----+----+----+----+----+
|
|
| |
|
|
+ I2NP Message Fragment 2... +
|
|
| |
|
|
~ ~
|
|
| |
|
|
+ +-------------------+
|
|
| |
|
|
+----+----+----+----+
|
|
|
|
Tunnel ID :: TunnelId
|
|
4 bytes
|
|
the ID of the next hop
|
|
|
|
IV ::
|
|
16 bytes
|
|
the initialization vector
|
|
|
|
Checksum ::
|
|
4 bytes
|
|
the first 4 bytes of the SHA256 hash of (the contents of the message
|
|
(after the zero byte) + IV)
|
|
|
|
Nonzero padding ::
|
|
0 or more bytes
|
|
random nonzero data for padding
|
|
|
|
Zero ::
|
|
1 byte
|
|
the value 0x00
|
|
|
|
Delivery Instructions :: TunnelMessageDeliveryInstructions
|
|
length varies but is typically 7, 39, 43, or 47 bytes
|
|
Indicates the fragment and the routing for the fragment
|
|
|
|
Message Fragment ::
|
|
1 to 996 bytes, actual maximum depends on delivery instruction size
|
|
A partial or full I2NP Message
|
|
|
|
total size: 1028 Bytes
|
|
*/
|
|
|
|
type TunnelID uint32
|
|
|
|
type EncryptedTunnelMessage crypto.TunnelData
|
|
|
|
type DeliveryInstructionsWithFragment struct {
|
|
DeliveryInstructions DeliveryInstructions
|
|
MessageFragment []byte
|
|
}
|
|
|
|
func (tm EncryptedTunnelMessage) ID() (tid TunnelID) {
|
|
tid = TunnelID(binary.BigEndian.Uint32(tm[:4]))
|
|
return
|
|
}
|
|
|
|
func (tm EncryptedTunnelMessage) IV() crypto.TunnelIV {
|
|
return tm[4:20]
|
|
}
|
|
|
|
func (tm EncryptedTunnelMessage) Data() crypto.TunnelIV {
|
|
return tm[24:]
|
|
}
|
|
|
|
type DecryptedTunnelMessage [1028]byte
|
|
|
|
func (decrypted_tunnel_message DecryptedTunnelMessage) ID() TunnelID {
|
|
return TunnelID(binary.BigEndian.Uint32(
|
|
decrypted_tunnel_message[:4],
|
|
))
|
|
}
|
|
|
|
func (decrypted_tunnel_message DecryptedTunnelMessage) IV() crypto.TunnelIV {
|
|
return decrypted_tunnel_message[4 : 4+16]
|
|
}
|
|
|
|
func (decrypted_tunnel_message DecryptedTunnelMessage) Checksum() crypto.TunnelIV {
|
|
return decrypted_tunnel_message[4+16 : 4+4+16]
|
|
}
|
|
|
|
//
|
|
// Returns the contents of a decrypted tunnel message that contain the data for the
|
|
// DeliveryInstructions.
|
|
//
|
|
func (decrypted_tunnel_message DecryptedTunnelMessage) deliveryInstructionData() []byte {
|
|
data_area := decrypted_tunnel_message[4+4+16:]
|
|
for i := 0; i < len(data_area); i++ {
|
|
if data_area[i] == 0x00 {
|
|
return data_area[i+1:]
|
|
}
|
|
}
|
|
return []byte{}
|
|
}
|
|
|
|
//
|
|
// Returns a slice of DeliveryInstructionWithFragment structures, which all of the Delivery Instructions
|
|
// in the tunnel message and their corresponding MessageFragment structures.
|
|
//
|
|
//
|
|
func (decrypted_tunnel_message DecryptedTunnelMessage) DeliveryInstructionsWithFragments() []DeliveryInstructionsWithFragment {
|
|
set := make([]DeliveryInstructionsWithFragment, 0)
|
|
data := decrypted_tunnel_message.deliveryInstructionData()
|
|
for {
|
|
instructions, remainder, err := readDeliveryInstructions(data)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"at": "(DecryptedTunnelMessage) DeliveryInstructionsWithFragments",
|
|
"err": err.Error(),
|
|
}).Error("error reading delivery instructions")
|
|
break
|
|
}
|
|
|
|
fragment_size, err := instructions.FragmentSize()
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"at": "(DecryptedTunnelMessage) DeliveryInstructionsWithFragments",
|
|
"err": err.Error(),
|
|
}).Error("error getting delivery instructions fragment size")
|
|
break
|
|
}
|
|
|
|
fragment_data := remainder[:fragment_size]
|
|
pair := DeliveryInstructionsWithFragment{
|
|
DeliveryInstructions: instructions,
|
|
MessageFragment: fragment_data,
|
|
}
|
|
|
|
data = remainder[fragment_size:]
|
|
set = append(set, pair)
|
|
}
|
|
return set
|
|
}
|