This repository was archived by the owner on Feb 8, 2023. It is now read-only.
This repository was archived by the owner on Feb 8, 2023. It is now read-only.
Shared Secret constructions for Private Networks #177
Open
Description
Caveats:
- this is a very basic encryption to segregate libp2p nodes into separate networks, using a network wide shared secret
- this is not meant to be highly secure, as the underlying connection will run its own online encryption handshake, with authenticated encryption, ephemeral keys, forward secrecy, and so on.
- this wrapper is merely to prevent nodes from connecting to each other when they are in different private networks.
- Thus the threat model is:
- we do not need authentication (bit flipping is ok, as it will be detected in the underlying cipher)
- we do not need to protect against replay (replay will be detected/discarded in underlying cipher)
- we use a network-wide shared secret and re-key when revoking access to a single node
- we must protect against secret extraction (do not exchange the secret)
- we must protect against ciphertext collection to derive the key/shared secret (ie derive per-session keys, use random IVs/nonces)
- WARNING: i have not studied these carefully. this is notes. these may be broken. need review.
Construction 1:
- 0-RTT
- basic shard secret encryption
- individual session keys
- not safe to replay (fine because internal stream will encrypt with an online key echange, and a session key)
- not authenticated, can flip bits (fine because internal stream will encrypt with AEAD)
- no MAC overhead
|| = concat
SS = <shared secret>
conn = <plaintext connection>
N = randomNonce(32) # 256 bits
LK = LocalPublicKey() # use only if remote has it available already. (wouldn't allow connecting to unknown nodes to identify them via secio)
SK = sha2-256(SS || LK || N) # session key
SC = AESCTR(SK) or CHACHA(SK) # stream cipher
conn.Write(N)
for {
data := getOutgoingData()
SC.XORKeyStream(data, data)
conn.Write(data)
}
Though really:
for { # AES has a 64GB key limit
N = randomNonce(32) # 256 bits
SK = sha2-256(SS || LK || N) # session key
conn.Write(N)
SC = AESCTR(SK) or CHACHA(SK)
SW = cipher.StreamWriter{S: SC, W: conn} # XORs using given cipher
written := 0
for written < 63GB { # AES must be re-keyed after 64GB.
data = getOutgoingData()
n, _ = SW.Write(data)
written += n
}
}
Construction 2:
- 1-RTT
- basic shared secret encryption
- individual session keys
- safe to replay
- not authenticated, can flip bits (fine because internal stream will encrypt with AEAD)
- no MAC overhead
SS = <shared secret>
conn = <plaintext connection>
N1, N2 := make([]byte, 32) # 256 bits
N1 = randomNonce(32)
conn.Write(N1)
conn.Read(N2)
N = sortAndConcat(N1, N2) # to disregard order.
LK = localPublicKey()
RK = remotePublicKey() # only available if we know it beforehand. this is pre-secio
PKs = sortAndConcat(LK, RK) # to disregard order.
SK = sha2-256(SS || PKs || N) # session key
SC = AESCTR(SK) or CHACHA(SK) # stream cipher
for {
data := getOutgoingData()
SC.XORKeyStream(data, data)
conn.Write(data)
}
Construction 3:
- 1-RTT
- AEAD (AES-GCM or ChaCha/Poly1305)
- individual session keys
- safe to replay
- authenticated
- another MAC overhead (oof!)