func DecryptAuth(in []byte, ratch *ratchet.Ratchet) (*ratchet.Ratchet, []byte, error) { msg, err := ratch.Decrypt(in) if err != nil { return nil, nil, err } unpadMsg := proto.Unpad(msg) return ratch, unpadMsg, nil }
func receiveProtobuf(conn *transport.Conn, inBuf []byte, t *testing.T) *proto.ServerToClient { response := new(proto.ServerToClient) conn.SetDeadline(time.Now().Add(time.Second)) num, err := conn.ReadFrame(inBuf) handleError(err, t) unpadMsg := proto.Unpad(inBuf[:num]) if err := response.Unmarshal(unpadMsg); err != nil { t.Error(err) } if response.Status == nil { t.Error("Server returned nil status.") } if *response.Status == proto.ServerToClient_PARSE_ERROR { t.Error("Server threw a parse error.") } return response }
func ReceiveProtobuf(conn *transport.Conn, inBuf []byte) (*proto.ServerToClient, error) { response := new(proto.ServerToClient) conn.SetDeadline(time.Now().Add(time.Hour)) num, err := conn.ReadFrame(inBuf) if err != nil { return nil, err } unpadMsg := proto.Unpad(inBuf[:num]) if err := response.Unmarshal(unpadMsg); err != nil { return nil, err } if response.Status == nil { return nil, errors.New("Server returned nil status.") } if *response.Status != proto.ServerToClient_OK { return nil, errors.New("Server did not return OK") } return response, nil }
// readClientCommands reads client commands from a connnection and sends them // to channel commands. On error, the error is sent to channel disconnect and // both channels (but not the connection are closed). // commands is a TWO-WAY channel! the reader must reach return each cmd after // interpreting it, readClientCommands will call cmd.Reset() and reuse it. func (server *Server) readClientCommands(conn *transport.Conn, commands chan *proto.ClientToServer, disconnected chan error) { defer server.wg.Done() defer close(commands) defer close(disconnected) inBuf := make([]byte, proto.SERVER_MESSAGE_SIZE) cmd := new(proto.ClientToServer) for { num, err := conn.ReadFrame(inBuf) if err != nil { disconnected <- err return } unpadMsg := proto.Unpad(inBuf[:num]) if err := cmd.Unmarshal(unpadMsg); err != nil { disconnected <- err return } commands <- cmd cmd = <-commands cmd.Reset() } }
func CheckAuthWith(prt ProfileRatchet) func([]byte, []byte, []byte, *[32]byte) error { return func(tag, data, msg []byte, ourAuthPrivate *[32]byte) error { var sharedAuthKey [32]byte message := new(proto.Message) unpadMsg := proto.Unpad(msg) err := message.Unmarshal(unpadMsg) if err != nil { return err } profile, err := prt(message.Dename, message.DenameLookup) if err != nil { return err } chatProfileBytes, err := client.GetProfileField(profile, PROFILE_FIELD_ID) if err != nil { return err } chatProfile := new(proto.Profile) if err := chatProfile.Unmarshal(chatProfileBytes); err != nil { return err } theirAuthPublic := (*[32]byte)(&chatProfile.MessageAuthKey) curve25519.ScalarMult(&sharedAuthKey, ourAuthPrivate, theirAuthPublic) h := hmac.New(sha256.New, sharedAuthKey[:]) h.Write(data) if subtle.ConstantTimeCompare(tag, h.Sum(nil)[:len(tag)]) == 0 { return errors.New("Authentication failed: failed to reproduce envelope auth tag using the current auth pubkey from dename") } return nil } }
func DecryptAuthFirst(in []byte, pkList []*[32]byte, skList []*[32]byte, skAuth *[32]byte, prt ProfileRatchet) (*ratchet.Ratchet, []byte, int, error) { ratch := &ratchet.Ratchet{ FillAuth: FillAuthWith(skAuth), CheckAuth: CheckAuthWith(prt), } if len(in) < 32 { return nil, nil, -1, errors.New("Message length incorrect.") } var pkAuth [32]byte copy(pkAuth[:], in[:32]) envelope := in[32:] for i, pk := range pkList { if *pk == pkAuth { msg, err := ratch.DecryptFirst(envelope, skList[i]) if err == nil { unpadMsg := proto.Unpad(msg) return ratch, unpadMsg, i, nil } } } return nil, nil, -1, errors.New("Invalid first message received.") //TODO: Should I make the error message something different? }