@verbatim
+------------ HEADER -------------+ +-------- ENCRYPTED --------+
/ \ / \
-+-------------------------------------+------------+----...-----------+------+
-| MAGIC | NICE | SENDER | EPUB | SIGN | SIZE | MAC | CIPHERTEXT | MAC | JUNK |
-+------------------------------/------\------------+----...-----------+------+
- / \
- +-------------------------------------+
- | MAGIC | NICE | RCPT | SENDER | EPUB |
- +-------------------------------------+
++--------------------------------------------+------------+----...-----------+------+
+| MAGIC | NICE | SENDER | RCPT | EPUB | SIGN | SIZE | MAC | CIPHERTEXT | MAC | JUNK |
++-------------------------------------/------\------------+----...-----------+------+
+ / \
+ +-------------------------------------+
+ | MAGIC | NICE | SENDER | RCPT | EPUB |
+ +-------------------------------------+
@end verbatim
@multitable @columnfractions 0.2 0.3 0.5
@item Sender @tab
32-byte, fixed length opaque data @tab
Sender node's id
+@item Recipient @tab
+ 32-byte, fixed length opaque data @tab
+ Recipient node's id
@item Exchange public key @tab
32-byte, fixed length opaque data @tab
Ephemeral curve25519 public key
ed25519 signature for that packet's header
@end multitable
-Signature is calculated over the following structure:
-
-@itemize
-@item Magic number
-@item Niceness
-@item Recipient (32-byte recipient node's id)
-@item Sender
-@item Exchange public key
-@end itemize
+Signature is calculated over all previous fields.
All following encryption is done using
@url{https://www.schneier.com/academic/twofish/, Twofish} algorithm with
var (
MagicNNCPPv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'P', 0, 0, 1}
- MagicNNCPEv1 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 1}
+ MagicNNCPEv2 [8]byte = [8]byte{'N', 'N', 'C', 'P', 'E', 0, 0, 2}
BadMagic error = errors.New("Unknown magic number")
BadPktType error = errors.New("Unknown packet type")
type PktTbs struct {
Magic [8]byte
Nice uint8
- Recipient *NodeId
Sender *NodeId
+ Recipient *NodeId
ExchPub *[32]byte
}
type PktEnc struct {
- Magic [8]byte
- Nice uint8
- Sender *NodeId
- ExchPub *[32]byte
- Sign *[ed25519.SignatureSize]byte
+ Magic [8]byte
+ Nice uint8
+ Sender *NodeId
+ Recipient *NodeId
+ ExchPub *[32]byte
+ Sign *[ed25519.SignatureSize]byte
}
func init() {
panic(err)
}
pktEnc := PktEnc{
- Magic: MagicNNCPEv1,
- Nice: 123,
- Sender: dummyId,
- ExchPub: new([32]byte),
- Sign: new([ed25519.SignatureSize]byte),
+ Magic: MagicNNCPEv2,
+ Nice: 123,
+ Sender: dummyId,
+ Recipient: dummyId,
+ ExchPub: new([32]byte),
+ Sign: new([ed25519.SignatureSize]byte),
}
n, err = xdr.Marshal(&buf, pktEnc)
if err != nil {
return err
}
tbs := PktTbs{
- Magic: MagicNNCPEv1,
+ Magic: MagicNNCPEv2,
Nice: nice,
- Recipient: their.Id,
Sender: our.Id,
+ Recipient: their.Id,
ExchPub: pubEph,
}
var tbsBuf bytes.Buffer
signature := new([ed25519.SignatureSize]byte)
copy(signature[:], ed25519.Sign(our.SignPrv, tbsBuf.Bytes()))
pktEnc := PktEnc{
- Magic: MagicNNCPEv1,
- Nice: nice,
- Sender: our.Id,
- ExchPub: pubEph,
- Sign: signature,
+ Magic: MagicNNCPEv2,
+ Nice: nice,
+ Sender: our.Id,
+ Recipient: their.Id,
+ ExchPub: pubEph,
+ Sign: signature,
}
if _, err = xdr.Marshal(out, &pktEnc); err != nil {
return err
}
sharedKey := new([32]byte)
curve25519.ScalarMult(sharedKey, prvEph, their.ExchPub)
- kdf := hkdf.New(blake256, sharedKey[:], nil, MagicNNCPEv1[:])
+ kdf := hkdf.New(blake256, sharedKey[:], nil, MagicNNCPEv2[:])
keyEnc := make([]byte, 32)
if _, err = io.ReadFull(kdf, keyEnc); err != nil {
func TbsVerify(our *NodeOur, their *Node, pktEnc *PktEnc) (bool, error) {
tbs := PktTbs{
- Magic: MagicNNCPEv1,
+ Magic: MagicNNCPEv2,
Nice: pktEnc.Nice,
- Recipient: our.Id,
Sender: their.Id,
+ Recipient: our.Id,
ExchPub: pktEnc.ExchPub,
}
var tbsBuf bytes.Buffer
if err != nil {
return nil, 0, err
}
- if pktEnc.Magic != MagicNNCPEv1 {
+ if pktEnc.Magic != MagicNNCPEv2 {
return nil, 0, BadMagic
}
their, known := nodes[*pktEnc.Sender]
if !known {
return nil, 0, errors.New("Unknown sender")
}
+ if *pktEnc.Recipient != *our.Id {
+ return nil, 0, errors.New("Invalid recipient")
+ }
verified, err := TbsVerify(our, their, &pktEnc)
if err != nil {
return nil, 0, err
}
sharedKey := new([32]byte)
curve25519.ScalarMult(sharedKey, our.ExchPrv, pktEnc.ExchPub)
- kdf := hkdf.New(blake256, sharedKey[:], nil, MagicNNCPEv1[:])
+ kdf := hkdf.New(blake256, sharedKey[:], nil, MagicNNCPEv2[:])
keyEnc := make([]byte, 32)
if _, err = io.ReadFull(kdf, keyEnc); err != nil {