1 // https://wiki.vuze.com/w/Message_Stream_Encryption
20 "github.com/bradfitz/iter"
26 cryptoMethodPlaintext = 1
31 // Prime P according to the spec, and G, the generator.
33 // The rand.Int max arg for use in newPadLen()
35 // For use in initer's hashes
39 // Verification constant "VC" which is all zeroes in the bittorrent
44 // Tracks counts of received crypto_provides
45 cryptoProvidesCount = expvar.NewMap("mseCryptoProvides")
49 p.SetString("0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563", 0)
51 newPadLenMax.SetInt64(maxPadLen + 1)
54 func hash(parts ...[]byte) []byte {
56 for _, p := range parts {
68 func newEncrypt(initer bool, s []byte, skey []byte) (c *rc4.Cipher) {
69 c, err := rc4.NewCipher(hash([]byte(func() string {
79 var burnSrc, burnDst [1024]byte
80 c.XORKeyStream(burnDst[:], burnSrc[:])
84 type cipherReader struct {
89 func (cr *cipherReader) Read(b []byte) (n int, err error) {
90 be := make([]byte, len(b))
91 n, err = cr.r.Read(be)
92 cr.c.XORKeyStream(b[:n], be[:n])
96 func newCipherReader(c *rc4.Cipher, r io.Reader) io.Reader {
97 return &cipherReader{c, r}
100 type cipherWriter struct {
105 func (cr *cipherWriter) Write(b []byte) (n int, err error) {
106 be := make([]byte, len(b))
107 cr.c.XORKeyStream(be, b)
108 n, err = cr.w.Write(be)
110 // The cipher will have advanced beyond the callers stream position.
111 // We can't use the cipher anymore.
117 func readY(r io.Reader) (y big.Int, err error) {
119 _, err = io.ReadFull(r, b[:])
127 func newX() big.Int {
129 X.SetBytes(func() []byte {
131 _, err := rand.Read(b[:])
140 func paddedLeft(b []byte, _len int) []byte {
144 ret := make([]byte, _len)
145 if n := copy(ret[_len-len(b):], b); n != len(b) {
151 // Calculate, and send Y, our public key.
152 func (h *handshake) postY(x *big.Int) error {
155 return h.postWrite(paddedLeft(y.Bytes(), 96))
158 func (h *handshake) establishS() (err error) {
162 _, err = io.ReadFull(h.conn, b[:])
170 copy(h.s[96-len(sBytes):96], sBytes)
174 func newPadLen() int64 {
175 i, err := rand.Int(rand.Reader, &newPadLenMax)
180 if ret < 0 || ret > maxPadLen {
186 // Manages state for both initiating and receiving handshakes.
187 type handshake struct {
190 initer bool // Whether we're initiating or receiving.
191 skeys [][]byte // Skeys we'll accept if receiving.
192 skey []byte // Skey we're initiating with.
193 ia []byte // Initial payload. Only used by the initiator.
206 func (h *handshake) finishWriting() {
209 h.writeCond.Broadcast()
220 func (h *handshake) writer() {
224 h.writerCond.Broadcast()
230 if len(h.writes) != 0 {
240 h.writes = h.writes[1:]
242 _, err := h.conn.Write(b)
252 func (h *handshake) postWrite(b []byte) error {
254 defer h.writeMu.Unlock()
255 if h.writeErr != nil {
258 h.writes = append(h.writes, b)
263 func xor(dst, src []byte) (ret []byte) {
268 ret = make([]byte, 0, max)
269 for i := range iter.N(max) {
270 ret = append(ret, dst[i]^src[i])
275 func marshal(w io.Writer, data ...interface{}) (err error) {
276 for _, data := range data {
277 err = binary.Write(w, binary.BigEndian, data)
285 func unmarshal(r io.Reader, data ...interface{}) (err error) {
286 for _, data := range data {
287 err = binary.Read(r, binary.BigEndian, data)
295 // Looking for b at the end of a.
296 func suffixMatchLen(a, b []byte) int {
300 // i is how much of b to try to match
301 for i := len(b); i > 0; i-- {
302 // j is how many chars we've compared
305 if b[i-1-j] != a[len(a)-1-j] {
315 // Reads from r until b has been seen. Keeps the minimum amount of data in
317 func readUntil(r io.Reader, b []byte) error {
318 b1 := make([]byte, len(b))
321 _, err := io.ReadFull(r, b1[i:])
325 i = suffixMatchLen(b1, b)
329 if copy(b1, b1[len(b1)-i:]) != i {
336 type readWriter struct {
341 func (h *handshake) newEncrypt(initer bool) *rc4.Cipher {
342 return newEncrypt(initer, h.s[:], h.skey)
345 func (h *handshake) initerSteps() (ret io.ReadWriter, err error) {
346 h.postWrite(hash(req1, h.s[:]))
347 h.postWrite(xor(hash(req2, h.skey), hash(req3, h.s[:])))
348 buf := &bytes.Buffer{}
349 padLen := uint16(newPadLen())
350 err = marshal(buf, vc[:], uint32(cryptoMethodRC4), padLen, zeroPad[:padLen], uint16(len(h.ia)), h.ia)
354 e := h.newEncrypt(true)
355 be := make([]byte, buf.Len())
356 e.XORKeyStream(be, buf.Bytes())
358 bC := h.newEncrypt(false)
360 bC.XORKeyStream(eVC[:], vc[:])
361 // Read until the all zero VC. At this point we've only read the 96 byte
362 // public key, Y. There is potentially 512 byte padding, between us and
363 // the 8 byte verification constant.
364 err = readUntil(io.LimitReader(h.conn, 520), eVC[:])
367 err = errors.New("failed to synchronize on VC")
369 err = fmt.Errorf("error reading until VC: %s", err)
373 r := &cipherReader{bC, h.conn}
375 err = unmarshal(r, &method, &padLen)
379 if method != cryptoMethodRC4 {
380 err = fmt.Errorf("receiver chose unsupported method: %x", method)
383 _, err = io.CopyN(ioutil.Discard, r, int64(padLen))
387 ret = readWriter{r, &cipherWriter{e, h.conn}}
391 var ErrNoSecretKeyMatch = errors.New("no skey matched")
393 func (h *handshake) receiverSteps() (ret io.ReadWriter, err error) {
394 // There is up to 512 bytes of padding, then the 20 byte hash.
395 err = readUntil(io.LimitReader(h.conn, 532), hash(req1, h.s[:]))
398 err = errors.New("failed to synchronize on S hash")
403 _, err = io.ReadFull(h.conn, b[:])
407 err = ErrNoSecretKeyMatch
408 for _, skey := range h.skeys {
409 if bytes.Equal(xor(hash(req2, skey), hash(req3, h.s[:])), b[:]) {
418 r := newCipherReader(newEncrypt(true, h.s[:], h.skey), h.conn)
425 err = unmarshal(r, vc[:], &method, &padLen)
429 cryptoProvidesCount.Add(strconv.FormatUint(uint64(method), 16), 1)
430 if method&cryptoMethodRC4 == 0 {
431 err = errors.New("no supported crypto methods were provided")
434 _, err = io.CopyN(ioutil.Discard, r, int64(padLen))
441 h.ia = make([]byte, lenIA)
444 buf := &bytes.Buffer{}
445 w := cipherWriter{h.newEncrypt(false), buf}
446 padLen = uint16(newPadLen())
447 err = marshal(&w, &vc, uint32(cryptoMethodRC4), padLen, zeroPad[:padLen])
451 err = h.postWrite(buf.Bytes())
455 ret = readWriter{io.MultiReader(bytes.NewReader(h.ia), r), &cipherWriter{w.c, h.conn}}
459 func (h *handshake) Do() (ret io.ReadWriter, err error) {
460 h.writeCond.L = &h.writeMu
461 h.writerCond.L = &h.writerMu
471 err = fmt.Errorf("error while establishing secret: %s", err)
474 pad := make([]byte, newPadLen())
475 io.ReadFull(rand.Reader, pad)
476 err = h.postWrite(pad)
481 ret, err = h.initerSteps()
483 ret, err = h.receiverSteps()
488 func InitiateHandshake(rw io.ReadWriter, skey []byte, initialPayload []byte) (ret io.ReadWriter, err error) {
497 func ReceiveHandshake(rw io.ReadWriter, skeys [][]byte) (ret io.ReadWriter, err error) {