github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/libs/niaucchi4/tunnel.go (about) 1 package niaucchi4 2 3 import ( 4 "bytes" 5 "crypto/cipher" 6 "crypto/hmac" 7 "crypto/rand" 8 "crypto/sha256" 9 "encoding/binary" 10 "errors" 11 "fmt" 12 mrand "math/rand" 13 "time" 14 15 "github.com/ethereum/go-ethereum/rlp" 16 "github.com/geph-official/geph2/libs/c25519" 17 "golang.org/x/crypto/chacha20poly1305" 18 "golang.org/x/crypto/curve25519" 19 ) 20 21 var masterSec = make([]byte, 32) 22 23 func genSK(seed []byte) [32]byte { 24 return c25519.GenSKWithSeed(append(seed, masterSec...)) 25 } 26 27 func init() { 28 rand.Read(masterSec) 29 } 30 31 func hm(m, k []byte) []byte { 32 h := hmac.New(sha256.New, k) 33 h.Write(m) 34 return h.Sum(nil) 35 } 36 37 type tunstate struct { 38 enc cipher.AEAD 39 dec cipher.AEAD 40 ss []byte 41 isserv bool 42 replayProtection bool 43 rw replayWindow 44 } 45 46 func (ts *tunstate) deriveKeys(ss []byte) { 47 //log.Printf("deriving keys from shared state %x", ss[:5]) 48 ts.ss = ss 49 upcrypt := aead(hm(ss, []byte("up"))) 50 dncrypt := aead(hm(ss, []byte("dn"))) 51 if ts.isserv { 52 ts.enc = dncrypt 53 ts.dec = upcrypt 54 } else { 55 ts.enc = upcrypt 56 ts.dec = dncrypt 57 } 58 } 59 60 func (ts *tunstate) Decrypt(pkt []byte) (bts []byte, err error) { 61 ns := ts.dec.NonceSize() 62 if len(pkt) < ns { 63 err = errors.New("WAT") 64 return 65 } 66 bts, err = ts.dec.Open(nil, pkt[:ns], pkt[ns:], nil) 67 if err != nil { 68 return 69 } 70 if ts.replayProtection { 71 var e2epkt e2ePacket 72 err = rlp.DecodeBytes(bts, &e2epkt) 73 if err != nil { 74 return 75 } 76 if !ts.rw.check(e2epkt.Sn) { 77 err = errors.New("blocking replay") 78 return 79 } 80 } 81 return 82 } 83 84 func (ts *tunstate) Encrypt(pkt []byte) (ctext []byte) { 85 nonceb := make([]byte, ts.enc.NonceSize()) 86 rand.Read(nonceb) 87 ctext = ts.enc.Seal(nonceb, nonceb, pkt, nil) 88 return 89 } 90 91 type prototun struct { 92 mySK [32]byte 93 cookie []byte 94 } 95 96 func (pt *prototun) realize(response []byte, isserv bool, replayProtection bool) (ts *tunstate, err error) { 97 // decode their hello 98 var theirHello helloPkt 99 err = binary.Read(bytes.NewReader(response), binary.BigEndian, &theirHello) 100 if err != nil { 101 return 102 } 103 // create possible nowcookies 104 for i := -30; i < 30; i++ { 105 // derive nowcookie 106 nowcookie := hm(pt.cookie, []byte(fmt.Sprintf("%v", time.Now().Unix()/30+int64(i)))) 107 //log.Printf("trying nowcookie %x", nowcookie[:5]) 108 boo := aead(hm(nowcookie, theirHello.Nonce[:])) 109 theirPK, e := boo. 110 Open(nil, make([]byte, boo.NonceSize()), theirHello.EncPK[:], nil) 111 if e != nil { 112 continue 113 } 114 var sharedsec [32]byte 115 var theirPKf [32]byte 116 copy(theirPKf[:], theirPK) 117 if isserv { 118 pt.mySK = genSK(theirPKf[:]) 119 } 120 curve25519.ScalarMult(&sharedsec, &pt.mySK, &theirPKf) 121 // make ts 122 ts = &tunstate{ 123 isserv: isserv, 124 replayProtection: replayProtection, 125 } 126 ts.deriveKeys(sharedsec[:]) 127 return 128 } 129 err = errors.New("none of the cookies work") 130 return 131 } 132 133 func newproto(cookie []byte) (pt *prototun) { 134 //log.Printf("newproto with cookie = %x and nowcookie = %x", cookie[:5], nowcookie[:5]) 135 // generate keys 136 sk := c25519.GenSK() 137 pt = &prototun{ 138 mySK: sk, 139 cookie: cookie, 140 } 141 return 142 } 143 144 func (pt *prototun) genHello() []byte { 145 var pk [32]byte 146 curve25519.ScalarBaseMult(&pk, &pt.mySK) 147 // derive nowcookie 148 nowcookie := hm(pt.cookie, []byte(fmt.Sprintf("%v", time.Now().Unix()/30))) 149 // create hello 150 nonce := make([]byte, 32) 151 rand.Read(nonce) 152 crypter := aead(hm(nowcookie, nonce)) 153 encpk := crypter. 154 Seal(nil, make([]byte, crypter.NonceSize()), pk[:], nil) 155 if len(encpk) != 32+crypter.Overhead() { 156 panic("encpk not right bytes long") 157 } 158 // form the pkt 159 var tosend helloPkt 160 copy(tosend.Nonce[:], nonce) 161 copy(tosend.EncPK[:], encpk) 162 buf := new(bytes.Buffer) 163 binary.Write(buf, binary.BigEndian, tosend) 164 padd := make([]byte, mrand.Int()%1000) 165 mrand.Read(padd) 166 buf.Write(padd) 167 return buf.Bytes() 168 } 169 170 func aead(key []byte) cipher.AEAD { 171 a, e := chacha20poly1305.NewX(key) 172 if e != nil { 173 panic(e) 174 } 175 return a 176 } 177 178 type helloPkt struct { 179 Nonce [32]byte 180 EncPK [48]byte 181 }