Esempio n. 1
0
func (kx *KeyExchange) exchange1() error {
	reply, err := kx.meetingPlace.Exchange(kx.Log, kx.meeting1[:], kx.message1[:], kx.ShutdownChan)
	if err != nil {
		return err
	}

	var peerDHPublic, encryptedPeerDHPublic [32]byte
	if len(reply) < len(encryptedPeerDHPublic) {
		return errors.New("panda: meeting point reply too small")
	}

	copy(encryptedPeerDHPublic[:], reply)
	rijndael.NewCipher(&kx.key).Decrypt(&peerDHPublic, &encryptedPeerDHPublic)

	curve25519.ScalarMult(&kx.sharedKey, &kx.dhPrivate, &peerDHPublic)

	paddedLen := kx.meetingPlace.Padding()
	padded := make([]byte, paddedLen-24 /* nonce */ -secretbox.Overhead)
	binary.LittleEndian.PutUint32(padded, uint32(len(kx.kxBytes)))
	copy(padded[4:], kx.kxBytes)
	if _, err := io.ReadFull(kx.rand, padded[4+len(kx.kxBytes):]); err != nil {
		return err
	}

	var nonce [24]byte
	if _, err := io.ReadFull(kx.rand, nonce[:]); err != nil {
		return err
	}

	kx.message2 = make([]byte, paddedLen)
	copy(kx.message2, nonce[:])
	secretbox.Seal(kx.message2[24:24], padded, &nonce, &kx.sharedKey)

	return nil
}
Esempio n. 2
0
File: panda.go Progetto: nico/pond
func (kx *KeyExchange) derivePassword() error {
	serialised, err := proto.Marshal(kx.sharedSecret.toProto())
	if err != nil {
		return err
	}

	if kx.Testing {
		h := sha256.New()
		h.Write([]byte{0})
		h.Write(serialised)
		h.Sum(kx.key[:0])

		h.Reset()
		h.Write([]byte{1})
		h.Write(serialised)
		h.Sum(kx.meeting1[:0])

		h.Reset()
		h.Write([]byte{2})
		h.Write(serialised)
		h.Sum(kx.meeting2[:0])
	} else {
		data, err := scrypt.Key(serialised, nil, 1<<17, 16, 4, 32*3)
		if err != nil {
			return err
		}

		copy(kx.key[:], data)
		copy(kx.meeting1[:], data[32:])
		copy(kx.meeting2[:], data[64:])
	}

	var encryptedDHPublic [32]byte
	rijndael.NewCipher(&kx.key).Encrypt(&encryptedDHPublic, &kx.dhPublic)

	l := len(encryptedDHPublic)
	if padding := kx.meetingPlace.Padding(); l > padding {
		return errors.New("panda: initial message too large for meeting place")
	} else if l < padding {
		l = padding
	}

	kx.message1 = make([]byte, l)
	copy(kx.message1, encryptedDHPublic[:])
	if _, err := io.ReadFull(kx.rand, kx.message1[len(encryptedDHPublic):]); err != nil {
		return err
	}

	return nil
}
Esempio n. 3
0
func (kx *KeyExchange) derivePassword() error {
	serialised, err := proto.Marshal(kx.sharedSecret.toProto())
	if err != nil {
		return err
	}

	if kx.Testing {
		h := sha256.New()
		h.Write([]byte{0})
		h.Write(serialised)
		h.Sum(kx.key[:0])

		h.Reset()
		h.Write([]byte{1})
		h.Write(serialised)
		h.Sum(kx.meeting1[:0])

		h.Reset()
		h.Write([]byte{2})
		h.Write(serialised)
		h.Sum(kx.meeting2[:0])
	} else {
		var data []byte
		if runtime.GOARCH == "386" && runtime.GOOS == "linux" {
			// We're having GC problems on 32-bit systems with the
			// scrypt allocation. In order to help the GC out, the
			// scrypt computation is done in a subprocess.
			cmd := exec.Command("/proc/self/exe", "--panda-scrypt")
			var in, out bytes.Buffer
			binary.Write(&in, binary.LittleEndian, uint32(len(serialised)))
			in.Write(serialised)

			cmd.Stdin = &in
			cmd.Stdout = &out
			cmd.Stderr = os.Stderr
			if err := cmd.Run(); err != nil {
				return err
			}
			data = out.Bytes()
			if len(data) != 32*3 {
				return errors.New("scrypt subprocess returned wrong number of bytes: " + strconv.Itoa(len(data)))
			}
		} else {
			if data, err = scrypt.Key(serialised, nil, 1<<17, 16, 4, 32*3); err != nil {
				return err
			}
		}

		copy(kx.key[:], data)
		copy(kx.meeting1[:], data[32:])
		copy(kx.meeting2[:], data[64:])
	}

	var encryptedDHPublic [32]byte
	rijndael.NewCipher(&kx.key).Encrypt(&encryptedDHPublic, &kx.dhPublic)

	l := len(encryptedDHPublic)
	if padding := kx.meetingPlace.Padding(); l > padding {
		return errors.New("panda: initial message too large for meeting place")
	} else if l < padding {
		l = padding
	}

	kx.message1 = make([]byte, l)
	copy(kx.message1, encryptedDHPublic[:])
	if _, err := io.ReadFull(kx.rand, kx.message1[len(encryptedDHPublic):]); err != nil {
		return err
	}

	return nil
}