diff --git a/res/css/_components.scss b/res/css/_components.scss
index e017d4b95a..ee55c000ff 100644
--- a/res/css/_components.scss
+++ b/res/css/_components.scss
@@ -107,6 +107,7 @@
 @import "./views/rooms/_AppsDrawer.scss";
 @import "./views/rooms/_Autocomplete.scss";
 @import "./views/rooms/_AuxPanel.scss";
+@import "./views/rooms/_E2EIcon.scss";
 @import "./views/rooms/_EntityTile.scss";
 @import "./views/rooms/_EventTile.scss";
 @import "./views/rooms/_JumpToBottomButton.scss";
diff --git a/res/css/structures/_RoomStatusBar.scss b/res/css/structures/_RoomStatusBar.scss
index 2a9cc9f6c7..1054654670 100644
--- a/res/css/structures/_RoomStatusBar.scss
+++ b/res/css/structures/_RoomStatusBar.scss
@@ -121,7 +121,7 @@ limitations under the License.
 
 .mx_RoomStatusBar_connectionLostBar img {
     padding-left: 10px;
-    padding-right: 22px;
+    padding-right: 10px;
     vertical-align: middle;
     float: left;
 }
diff --git a/res/css/views/rooms/_E2EIcon.scss b/res/css/views/rooms/_E2EIcon.scss
new file mode 100644
index 0000000000..cd577df87b
--- /dev/null
+++ b/res/css/views/rooms/_E2EIcon.scss
@@ -0,0 +1,33 @@
+/*
+Copyright 2019 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_E2EIcon {
+    width: 25px;
+    height: 25px;
+    mask-repeat: no-repeat;
+    mask-position: center 0;
+    margin: 0 9px;
+}
+
+.mx_E2EIcon_verified {
+    mask-image: url('$(res)/img/feather-icons/e2e/lock-verified.svg');
+    background-color: $accent-color;
+}
+
+.mx_E2EIcon_warning {
+    mask-image: url('$(res)/img/feather-icons/e2e/lock-warning.svg');
+    background-color: $warning-color;
+}
diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss
index c920d6e390..7c9a6babea 100644
--- a/res/css/views/rooms/_EventTile.scss
+++ b/res/css/views/rooms/_EventTile.scss
@@ -281,9 +281,24 @@ limitations under the License.
 .mx_EventTile_e2eIcon {
     display: block;
     position: absolute;
-    top: 9px;
+    top: 8px;
     left: 46px;
+    width: 15px;
+    height: 15px;
     cursor: pointer;
+    mask-size: 14px;
+    mask-repeat: no-repeat;
+    mask-position: 0;
+}
+
+.mx_EventTile_e2eIcon_undecryptable, .mx_EventTile_e2eIcon_unverified {
+    mask-image: url('$(res)/img/feather-icons/e2e/warning.svg');
+    background-color: $warning-color;
+}
+
+.mx_EventTile_e2eIcon_unencrypted {
+    mask-image: url('$(res)/img/feather-icons/e2e/warning.svg');
+    background-color: $composer-e2e-icon-color;
 }
 
 .mx_EventTile_e2eIcon_hidden {
diff --git a/res/css/views/rooms/_MemberDeviceInfo.scss b/res/css/views/rooms/_MemberDeviceInfo.scss
index 6ccc4c7ae3..f780c50410 100644
--- a/res/css/views/rooms/_MemberDeviceInfo.scss
+++ b/res/css/views/rooms/_MemberDeviceInfo.scss
@@ -20,6 +20,25 @@ limitations under the License.
     align-items: start;
 }
 
+.mx_MemberDeviceInfo_icon {
+    margin-top: 4px;
+    width: 12px;
+    height: 12px;
+    mask-repeat: no-repeat;
+}
+.mx_MemberDeviceInfo_icon_blacklisted {
+    mask-image: url('$(res)/img/feather-icons/e2e/blacklisted.svg');
+    background-color: $warning-color;
+}
+.mx_MemberDeviceInfo_icon_verified {
+    mask-image: url('$(res)/img/feather-icons/e2e/verified.svg');
+    background-color: $accent-color;
+}
+.mx_MemberDeviceInfo_icon_unverified {
+    mask-image: url('$(res)/img/feather-icons/e2e/warning.svg');
+    background-color: $warning-color;
+}
+
 .mx_MemberDeviceInfo > .mx_DeviceVerifyButtons {
     display: flex;
     flex-direction: column;
diff --git a/res/css/views/rooms/_MemberInfo.scss b/res/css/views/rooms/_MemberInfo.scss
index 99771fece0..707c186518 100644
--- a/res/css/views/rooms/_MemberInfo.scss
+++ b/res/css/views/rooms/_MemberInfo.scss
@@ -26,6 +26,10 @@ limitations under the License.
     display: flex;
 }
 
+.mx_MemberInfo_name > .mx_E2EIcon {
+    margin-left: 0;
+}
+
 .mx_MemberInfo_cancel {
     height: 16px;
     padding: 10px 15px;
diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss
index dc4aec691b..7ee7efcaff 100644
--- a/res/css/views/rooms/_MessageComposer.scss
+++ b/res/css/views/rooms/_MessageComposer.scss
@@ -23,6 +23,10 @@ limitations under the License.
     padding-left: 84px;
 }
 
+.mx_MessageComposer_wrapper.mx_MessageComposer_hasE2EIcon {
+    padding-left: 109px;
+}
+
 .mx_MessageComposer_replaced_wrapper {
     margin-left: auto;
     margin-right: auto;
@@ -71,9 +75,10 @@ limitations under the License.
     width: 100%;
 }
 
-.mx_MessageComposer_e2eIcon {
+.mx_MessageComposer_e2eIcon.mx_E2EIcon {
     position: absolute;
     left: 60px;
+    background-color: $composer-e2e-icon-color;
 }
 
 .mx_MessageComposer_noperm_error {
diff --git a/res/img/feather-icons/e2e/blacklisted.svg b/res/img/feather-icons/e2e/blacklisted.svg
new file mode 100644
index 0000000000..63897c2227
--- /dev/null
+++ b/res/img/feather-icons/e2e/blacklisted.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
+    <defs>
+        <path id="a" d="M5 10A5 5 0 1 0 5 0a5 5 0 0 0 0 10zM2.5 3.5h5a1.5 1.5 0 0 1 0 3h-5a1.5 1.5 0 0 1 0-3z"/>
+    </defs>
+    <use fill="#F56679" fill-rule="evenodd" stroke="#F56679" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2" transform="translate(1 1)" xlink:href="#a"/>
+</svg>
diff --git a/res/img/feather-icons/e2e/lock-verified.svg b/res/img/feather-icons/e2e/lock-verified.svg
new file mode 100644
index 0000000000..4cd4684ea2
--- /dev/null
+++ b/res/img/feather-icons/e2e/lock-verified.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="22" height="25" viewBox="0 0 22 25">
+    <g fill="none" fill-rule="evenodd" stroke="#7AC9A1" stroke-linecap="round" stroke-linejoin="round">
+        <path stroke-width="2" d="M8.23 21.01l-5.233-.007a1.995 1.995 0 0 1-1.997-2V11a2 2 0 0 1 2-2h14c1.259 0 2 .939 2 1M5 9V6a5 5 0 1 1 10 0v3"/>
+        <path fill="#7AC9A1" d="M15.5 24s5.5-2.4 5.5-6v-4.2L15.5 12 10 13.8V18c0 3.6 5.5 6 5.5 6z"/>
+    </g>
+</svg>
diff --git a/res/img/feather-icons/e2e/lock-warning.svg b/res/img/feather-icons/e2e/lock-warning.svg
new file mode 100644
index 0000000000..507c532f9d
--- /dev/null
+++ b/res/img/feather-icons/e2e/lock-warning.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="23" height="25" viewBox="0 0 23 25">
+    <defs>
+        <path id="a" d="M15 23a6 6 0 1 0 0-12 6 6 0 0 0 0 12zm0-10.5a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-3 0v-3a1.5 1.5 0 0 1 1.5-1.5zm0 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/>
+    </defs>
+    <g fill="none" fill-rule="evenodd" stroke="#F56679" stroke-linecap="round" stroke-linejoin="round" transform="translate(1 1)">
+        <path stroke-width="2" d="M7.23 20.01l-5.233-.007a2 2 0 0 1-1.997-2V10a2 2 0 0 1 2-2h14c1.259 0 2 .939 2 1M4 8V5a5 5 0 1 1 10 0v3"/>
+        <use fill="#F56679" xlink:href="#a"/>
+    </g>
+</svg>
diff --git a/res/img/feather-icons/e2e/verified.svg b/res/img/feather-icons/e2e/verified.svg
new file mode 100644
index 0000000000..f143f854e6
--- /dev/null
+++ b/res/img/feather-icons/e2e/verified.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="11" height="12" viewBox="0 0 11 12">
+    <path fill="#7AC9A1" fill-rule="evenodd" stroke="#7AC9A1" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2" d="M5.5 11S10 9 10 6V2.5L5.5 1 1 2.5V6c0 3 4.5 5 4.5 5z"/>
+</svg>
diff --git a/res/img/feather-icons/e2e/warning.svg b/res/img/feather-icons/e2e/warning.svg
new file mode 100644
index 0000000000..e6c246dba9
--- /dev/null
+++ b/res/img/feather-icons/e2e/warning.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12">
+    <defs>
+        <path id="a" d="M5 10A5 5 0 1 0 5 0a5 5 0 0 0 0 10zM5 .5A1.5 1.5 0 0 1 6.5 2v3a1.5 1.5 0 0 1-3 0V2A1.5 1.5 0 0 1 5 .5zm0 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/>
+    </defs>
+    <use fill="#F56679" fill-rule="evenodd" stroke="#F56679" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.2" transform="translate(1 1)" xlink:href="#a"/>
+</svg>
diff --git a/res/themes/dharma/css/_dharma.scss b/res/themes/dharma/css/_dharma.scss
index f976180144..482b3c51cb 100644
--- a/res/themes/dharma/css/_dharma.scss
+++ b/res/themes/dharma/css/_dharma.scss
@@ -142,6 +142,8 @@ $roomheader-addroom-color: #91A1C0;
 $roomtopic-color: #9fa9ba;
 $eventtile-meta-color: $roomtopic-color;
 
+$composer-e2e-icon-color: #c9ced6;
+
 // ********************
 
 $roomtile-name-color: #61708b;
diff --git a/res/themes/light/css/_base.scss b/res/themes/light/css/_base.scss
index 998325e1b7..8185ba0ace 100644
--- a/res/themes/light/css/_base.scss
+++ b/res/themes/light/css/_base.scss
@@ -134,6 +134,9 @@ $roomheader-color: $primary-fg-color;
 $roomheader-addroom-color: $primary-bg-color;
 $roomtopic-color: $settings-grey-fg-color;
 $eventtile-meta-color: $roomtopic-color;
+
+$composer-e2e-icon-color: #c9ced6;
+
 // ********************
 
 $roomtile-name-color: rgba(69, 69, 69, 0.8);
diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js
index b57bac805e..ab7f472931 100644
--- a/src/components/structures/RoomStatusBar.js
+++ b/src/components/structures/RoomStatusBar.js
@@ -290,7 +290,7 @@ module.exports = React.createClass({
         }
 
         return <div className="mx_RoomStatusBar_connectionLostBar">
-            <img src={require("../../../res/img/warning.svg")} width="24" height="23" title={_t("Warning")} alt="" />
+            <img src={require("../../../res/img/feather-icons/e2e/warning.svg")} width="24" height="24" title={_t("Warning")} alt="" />
             <div>
                 <div className="mx_RoomStatusBar_connectionLostBar_title">
                     { title }
@@ -309,7 +309,7 @@ module.exports = React.createClass({
         if (this._shouldShowConnectionError()) {
             return (
                 <div className="mx_RoomStatusBar_connectionLostBar">
-                    <img src={require("../../../res/img/warning.svg")} width="24" height="23" title="/!\ " alt="/!\ " />
+                    <img src={require("../../../res/img/feather-icons/e2e/warning.svg")} width="24" height="24" title="/!\ " alt="/!\ " />
                     <div>
                         <div className="mx_RoomStatusBar_connectionLostBar_title">
                             { _t('Connectivity to the server has been lost.') }
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index 26ef3da739..b6513f0418 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -168,6 +168,7 @@ module.exports = React.createClass({
         MatrixClientPeg.get().on("Room.myMembership", this.onMyMembership);
         MatrixClientPeg.get().on("accountData", this.onAccountData);
         MatrixClientPeg.get().on("crypto.keyBackupStatus", this.onKeyBackupStatus);
+        MatrixClientPeg.get().on("deviceVerificationChanged", this.onDeviceVerificationChanged);
         this._fetchMediaConfig();
         // Start listening for RoomViewStore updates
         this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate);
@@ -457,6 +458,7 @@ module.exports = React.createClass({
             MatrixClientPeg.get().removeListener("RoomState.members", this.onRoomStateMember);
             MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
             MatrixClientPeg.get().removeListener("crypto.keyBackupStatus", this.onKeyBackupStatus);
+            MatrixClientPeg.get().removeListener("deviceVerificationChanged", this.onDeviceVerificationChanged);
         }
 
         window.removeEventListener('beforeunload', this.onPageUnload);
@@ -589,6 +591,10 @@ module.exports = React.createClass({
             this._updatePreviewUrlVisibility(room);
         }
 
+        if (ev.getType() === "m.room.encryption") {
+            this._updateE2EStatus(room);
+        }
+
         // ignore anything but real-time updates at the end of the room:
         // updates from pagination will happen when the paginate completes.
         if (toStartOfTimeline || !data || !data.liveEvent) return;
@@ -642,6 +648,7 @@ module.exports = React.createClass({
         this._updatePreviewUrlVisibility(room);
         this._loadMembersIfJoined(room);
         this._calculateRecommendedVersion(room);
+        this._updateE2EStatus(room);
     },
 
     _calculateRecommendedVersion: async function(room) {
@@ -733,6 +740,23 @@ module.exports = React.createClass({
         });
     },
 
+    onDeviceVerificationChanged: function(userId, device) {
+        const room = this.state.room;
+        if (!room.currentState.getMember(userId)) {
+            return;
+        }
+        this._updateE2EStatus(room);
+    },
+
+    _updateE2EStatus: function(room) {
+        if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) {
+            return;
+        }
+        room.hasUnverifiedDevices().then((hasUnverifiedDevices) => {
+            this.setState({e2eStatus: hasUnverifiedDevices ? "warning" : "verified"});
+        });
+    },
+
     updateTint: function() {
         const room = this.state.room;
         if (!room) return;
@@ -1575,6 +1599,7 @@ module.exports = React.createClass({
                             room={this.state.room}
                             oobData={this.props.oobData}
                             collapsedRhs={this.props.collapsedRhs}
+                            e2eStatus={this.state.e2eStatus}
                         />
                         <div className="mx_RoomView_body">
                             <div className="mx_RoomView_auxPanel">
@@ -1622,6 +1647,7 @@ module.exports = React.createClass({
                             ref="header"
                             room={this.state.room}
                             collapsedRhs={this.props.collapsedRhs}
+                            e2eStatus={this.state.e2eStatus}
                         />
                         <div className="mx_RoomView_body">
                             <div className="mx_RoomView_auxPanel">
@@ -1767,6 +1793,7 @@ module.exports = React.createClass({
                     disabled={this.props.disabled}
                     showApps={this.state.showApps}
                     uploadAllowed={this.isFileUploadAllowed}
+                    e2eStatus={this.state.e2eStatus}
                 />;
         }
 
@@ -1917,6 +1944,7 @@ module.exports = React.createClass({
                     onCancelClick={(aux && !hideCancel) ? this.onCancelClick : null}
                     onForgetClick={(myMembership === "leave") ? this.onForgetClick : null}
                     onLeaveClick={(myMembership === "join") ? this.onLeaveClick : null}
+                    e2eStatus={this.state.e2eStatus}
                 />
                 <MainSplit panel={rightPanel} collapsedRhs={this.props.collapsedRhs}>
                     <div className={fadableSectionClasses}>
diff --git a/src/components/views/rooms/E2EIcon.js b/src/components/views/rooms/E2EIcon.js
new file mode 100644
index 0000000000..30891e84b7
--- /dev/null
+++ b/src/components/views/rooms/E2EIcon.js
@@ -0,0 +1,39 @@
+/*
+Copyright 2019 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import classNames from 'classnames';
+import { _t } from '../../../languageHandler';
+
+export default function(props) {
+    const isWarning = props.status === "warning";
+    const isVerified = props.status === "verified";
+    const e2eIconClasses = classNames({
+        mx_E2EIcon: true,
+        mx_E2EIcon_warning: isWarning,
+        mx_E2EIcon_verified: isVerified,
+    }, props.className);
+    let e2eTitle;
+    if (isWarning) {
+        e2eTitle = props.isUser ?
+            _t("Some devices for this user are not trusted") :
+            _t("Some devices in this encrypted room are not trusted");
+    } else if (isVerified) {
+        e2eTitle = props.isUser ?
+            _t("All devices for this user are trusted") :
+            _t("All devices in this encrypted room are trusted");
+    }
+    return (<div className={e2eIconClasses} title={e2eTitle} />);
+}
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index acb122ad4e..e4a6695ff5 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -459,17 +459,21 @@ module.exports = withMatrixClient(React.createClass({
 
         // event is encrypted, display padlock corresponding to whether or not it is verified
         if (ev.isEncrypted()) {
-            return this.state.verified ? <E2ePadlockVerified {...props} /> : <E2ePadlockUnverified {...props} />;
+            if (this.state.verified) {
+                return; // no icon for verified
+            } else {
+                return (<E2ePadlockUnverified {...props} />);
+            }
         }
 
         if (this.props.matrixClient.isRoomEncrypted(ev.getRoomId())) {
             // else if room is encrypted
             // and event is being encrypted or is not_sent (Unknown Devices/Network Error)
             if (ev.status === EventStatus.ENCRYPTING) {
-                return <E2ePadlockEncrypting {...props} />;
+                return;
             }
             if (ev.status === EventStatus.NOT_SENT) {
-                return <E2ePadlockNotSent {...props} />;
+                return;
             }
             // if the event is not encrypted, but it's an e2e room, show the open padlock
             return <E2ePadlockUnencrypted {...props} />;
@@ -767,57 +771,29 @@ module.exports.haveTileForEvent = function(e) {
 
 function E2ePadlockUndecryptable(props) {
     return (
-        <E2ePadlock alt={_t("Undecryptable")}
-            src={require("../../../../res/img/e2e-blocked.svg")} width="12" height="12"
-            style={{ marginLeft: "-1px" }} {...props} />
-    );
-}
-
-function E2ePadlockEncrypting(props) {
-    return (
-        <E2ePadlock alt={_t("Encrypting")}
-            src={require("../../../../res/img/e2e-encrypting.svg")} width="10" height="12"
-            {...props} />
-    );
-}
-
-function E2ePadlockNotSent(props) {
-    return (
-        <E2ePadlock alt={_t("Encrypted, not sent")}
-            src={require("../../../../res/img/e2e-not_sent.svg")} width="10" height="12"
-            {...props} />
-    );
-}
-
-function E2ePadlockVerified(props) {
-    return (
-        <E2ePadlock alt={_t("Encrypted by a verified device")}
-            src={require("../../../../res/img/e2e-verified.svg")} width="10" height="12"
-            {...props} />
+        <E2ePadlock title={_t("Undecryptable")} icon="undecryptable" />
     );
 }
 
 function E2ePadlockUnverified(props) {
     return (
-        <E2ePadlock alt={_t("Encrypted by an unverified device")}
-            src={require("../../../../res/img/e2e-warning.svg")} width="15" height="12"
-            style={{ marginLeft: "-2px" }} {...props} />
+        <E2ePadlock title={_t("Encrypted by an unverified device")} icon="unverified" />
     );
 }
 
 function E2ePadlockUnencrypted(props) {
     return (
-        <E2ePadlock alt={_t("Unencrypted message")}
-            src={require("../../../../res/img/e2e-unencrypted.svg")} width="12" height="12"
-            {...props} />
+        <E2ePadlock title={_t("Unencrypted message")} icon="unencrypted" />
     );
 }
 
 function E2ePadlock(props) {
     if (SettingsStore.getValue("alwaysShowEncryptionIcons")) {
-        return <img className="mx_EventTile_e2eIcon" {...props} />;
+        return <div
+            className={`mx_EventTile_e2eIcon mx_EventTile_e2eIcon_${props.icon}`}
+            title={props.title} onClick={props.onClick} />;
     } else {
-        return <img className="mx_EventTile_e2eIcon mx_EventTile_e2eIcon_hidden" {...props} />;
+        return <div className="mx_EventTile_e2eIcon mx_EventTile_e2eIcon_hidden" onClick={props.onClick} />;
     }
 }
 
diff --git a/src/components/views/rooms/MemberDeviceInfo.js b/src/components/views/rooms/MemberDeviceInfo.js
index b9c276f0d1..67f99e4d1d 100644
--- a/src/components/views/rooms/MemberDeviceInfo.js
+++ b/src/components/views/rooms/MemberDeviceInfo.js
@@ -18,32 +18,18 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
+import classNames from 'classnames';
 
 export default class MemberDeviceInfo extends React.Component {
     render() {
-        let indicator = null;
         const DeviceVerifyButtons = sdk.getComponent('elements.DeviceVerifyButtons');
-
-        if (this.props.device.isBlocked()) {
-            indicator = (
-                    <div className="mx_MemberDeviceInfo_blacklisted">
-                    <img src={require("../../../../res/img/e2e-blocked.svg")} width="12" height="12" style={{ marginLeft: "-1px" }} alt={_t("Blacklisted")} />
-                    </div>
-            );
-        } else if (this.props.device.isVerified()) {
-            indicator = (
-                    <div className="mx_MemberDeviceInfo_verified">
-                    <img src={require("../../../../res/img/e2e-verified.svg")} width="10" height="12" alt={_t("Verified")} />
-                    </div>
-            );
-        } else {
-            indicator = (
-                    <div className="mx_MemberDeviceInfo_unverified">
-                    <img src={require("../../../../res/img/e2e-warning.svg")} width="15" height="12" style={{ marginLeft: "-2px" }} alt={_t("Unverified")} />
-                    </div>
-            );
-        }
-
+        const iconClasses = classNames({
+            mx_MemberDeviceInfo_icon: true,
+            mx_MemberDeviceInfo_icon_blacklisted: this.props.device.isBlocked(),
+            mx_MemberDeviceInfo_icon_verified: this.props.device.isVerified(),
+            mx_MemberDeviceInfo_icon_unverified: this.props.device.isUnverified(),
+        });
+        const indicator = (<div className={iconClasses} />);
         const deviceName = this.props.device.ambiguous ?
             (this.props.device.getDisplayName() ? this.props.device.getDisplayName() : "") + " (" + this.props.device.deviceId + ")" :
             this.props.device.getDisplayName();
@@ -52,10 +38,10 @@ export default class MemberDeviceInfo extends React.Component {
         return (
             <div className="mx_MemberDeviceInfo"
                     title={_t("device id: ") + this.props.device.deviceId} >
+                { indicator }
                 <div className="mx_MemberDeviceInfo_deviceInfo">
                     <div className="mx_MemberDeviceInfo_deviceId">
                         { deviceName }
-                        { indicator }
                     </div>
                 </div>
                 <DeviceVerifyButtons userId={this.props.userId} device={this.props.device} />
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index 9859861870..5df0da7491 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -43,6 +43,7 @@ import RoomViewStore from '../../../stores/RoomViewStore';
 import SdkConfig from '../../../SdkConfig';
 import MultiInviter from "../../../utils/MultiInviter";
 import SettingsStore from "../../../settings/SettingsStore";
+import E2EIcon from "./E2EIcon";
 
 module.exports = withMatrixClient(React.createClass({
     displayName: 'MemberInfo',
@@ -153,11 +154,19 @@ module.exports = withMatrixClient(React.createClass({
             // Promise.resolve to handle transition from static result to promise; can be removed
             // in future
             Promise.resolve(this.props.matrixClient.getStoredDevicesForUser(userId)).then((devices) => {
-                this.setState({devices: devices});
+                this.setState({
+                    devices: devices,
+                    e2eStatus: this._getE2EStatus(devices),
+                });
             });
         }
     },
 
+    _getE2EStatus: function(devices) {
+        const hasUnverifiedDevice = devices.some((device) => device.isUnverified());
+        return hasUnverifiedDevice ? "warning" : "verified";
+    },
+
     onRoom: function(room) {
         this.forceUpdate();
     },
@@ -234,8 +243,13 @@ module.exports = withMatrixClient(React.createClass({
                 // we got cancelled - presumably a different user now
                 return;
             }
+
             self._disambiguateDevices(devices);
-            self.setState({devicesLoading: false, devices: devices});
+            self.setState({
+                devicesLoading: false,
+                devices: devices,
+                e2eStatus: self._getE2EStatus(devices),
+            });
         }, function(err) {
             console.log("Error downloading devices", err);
             self.setState({devicesLoading: false});
@@ -965,6 +979,7 @@ module.exports = withMatrixClient(React.createClass({
                         <AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}>
                             <img src={require("../../../../res/img/minimise.svg")} width="10" height="16" className="mx_filterFlipColor" alt={_t('Close')} />
                         </AccessibleButton>
+                        { this.state.e2eStatus ? <E2EIcon status={this.state.e2eStatus} isUser={true} /> : undefined }
                         <EmojiText element="h2">{ memberName }</EmojiText>
                     </div>
                     { avatarElement }
diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js
index 7681c2dc13..7117825d76 100644
--- a/src/components/views/rooms/MessageComposer.js
+++ b/src/components/views/rooms/MessageComposer.js
@@ -26,6 +26,9 @@ import RoomViewStore from '../../../stores/RoomViewStore';
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
 import Stickerpicker from './Stickerpicker';
 import { makeRoomPermalink } from '../../../matrix-to';
+import classNames from 'classnames';
+
+import E2EIcon from './E2EIcon';
 
 const formatButtonList = [
     _td("bold"),
@@ -316,25 +319,14 @@ export default class MessageComposer extends React.Component {
             );
         }
 
-        let e2eImg; let e2eTitle; let e2eClass;
-        const roomIsEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
-        if (roomIsEncrypted) {
-            // FIXME: show a /!\ if there are untrusted devices in the room...
-            e2eImg = require("../../../../res/img/e2e-verified.svg");
-            e2eTitle = _t('Encrypted room');
-            e2eClass = 'mx_MessageComposer_e2eIcon';
-        } else {
-            e2eImg = require("../../../../res/img/e2e-unencrypted.svg");
-            e2eTitle = _t('Unencrypted room');
-            e2eClass = 'mx_MessageComposer_e2eIcon mx_filterFlipColor';
+        if (this.props.e2eStatus) {
+            controls.push(<E2EIcon
+                status={this.props.e2eStatus}
+                key="e2eIcon"
+                className="mx_MessageComposer_e2eIcon" />
+            );
         }
 
-        controls.push(
-            <img key="e2eIcon" className={e2eClass} src={e2eImg} width="12" height="12"
-                alt={e2eTitle} title={e2eTitle}
-            />,
-        );
-
         let callButton;
         let videoCallButton;
         let hangupButton;
@@ -413,6 +405,7 @@ export default class MessageComposer extends React.Component {
                      key="controls_formatting" />
             ) : null;
 
+            const roomIsEncrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.room.roomId);
             let placeholderText;
             if (this.state.isQuoting) {
                 if (roomIsEncrypted) {
@@ -509,9 +502,13 @@ export default class MessageComposer extends React.Component {
                 </div>;
         }
 
+        const wrapperClasses = classNames({
+            mx_MessageComposer_wrapper: true,
+            mx_MessageComposer_hasE2EIcon: !!this.props.e2eStatus,
+        });
         return (
             <div className="mx_MessageComposer">
-                <div className="mx_MessageComposer_wrapper">
+                <div className={wrapperClasses}>
                     <div className="mx_MessageComposer_row">
                         { controls }
                     </div>
diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js
index 3cdb9237be..cee1814011 100644
--- a/src/components/views/rooms/RoomHeader.js
+++ b/src/components/views/rooms/RoomHeader.js
@@ -33,6 +33,7 @@ import ManageIntegsButton from '../elements/ManageIntegsButton';
 import {CancelButton} from './SimpleRoomHeader';
 import SettingsStore from "../../../settings/SettingsStore";
 import RoomHeaderButtons from '../right_panel/RoomHeaderButtons';
+import E2EIcon from './E2EIcon';
 
 linkifyMatrix(linkify);
 
@@ -52,6 +53,7 @@ module.exports = React.createClass({
         onSearchClick: PropTypes.func,
         onLeaveClick: PropTypes.func,
         onCancelClick: PropTypes.func,
+        e2eStatus: PropTypes.string,
     },
 
     getDefaultProps: function() {
@@ -237,6 +239,10 @@ module.exports = React.createClass({
             );
         }
 
+        const e2eIcon = this.props.e2eStatus ?
+            <E2EIcon status={this.props.e2eStatus} /> :
+            undefined;
+
         if (this.props.onCancelClick) {
             cancelButton = <CancelButton onClick={this.props.onCancelClick} />;
         }
@@ -413,6 +419,7 @@ module.exports = React.createClass({
             <div className={"mx_RoomHeader light-panel " + (this.props.editing ? "mx_RoomHeader_editing" : "")}>
                 <div className="mx_RoomHeader_wrapper">
                     <div className="mx_RoomHeader_avatar">{ roomAvatar }</div>
+                    { e2eIcon }
                     { name }
                     { topicElement }
                     { spinner }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 8fe1b926f9..f1d7296d03 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -571,6 +571,10 @@
     " (unsupported)": " (unsupported)",
     "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.": "Join as <voiceText>voice</voiceText> or <videoText>video</videoText>.",
     "Ongoing conference call%(supportedText)s.": "Ongoing conference call%(supportedText)s.",
+    "Some devices for this user are not trusted": "Some devices for this user are not trusted",
+    "Some devices in this encrypted room are not trusted": "Some devices in this encrypted room are not trusted",
+    "All devices for this user are trusted": "All devices for this user are trusted",
+    "All devices in this encrypted room are trusted": "All devices in this encrypted room are trusted",
     "This event could not be displayed": "This event could not be displayed",
     "%(senderName)s sent an image": "%(senderName)s sent an image",
     "%(senderName)s sent a video": "%(senderName)s sent a video",
@@ -582,16 +586,10 @@
     "Key request sent.": "Key request sent.",
     "<requestLink>Re-request encryption keys</requestLink> from your other devices.": "<requestLink>Re-request encryption keys</requestLink> from your other devices.",
     "Undecryptable": "Undecryptable",
-    "Encrypting": "Encrypting",
-    "Encrypted, not sent": "Encrypted, not sent",
-    "Encrypted by a verified device": "Encrypted by a verified device",
     "Encrypted by an unverified device": "Encrypted by an unverified device",
     "Unencrypted message": "Unencrypted message",
     "Please select the destination room for this message": "Please select the destination room for this message",
     "Scroll to bottom of page": "Scroll to bottom of page",
-    "Blacklisted": "Blacklisted",
-    "Verified": "Verified",
-    "Unverified": "Unverified",
     "device id: ": "device id: ",
     "Disinvite": "Disinvite",
     "Kick": "Kick",
@@ -643,8 +641,6 @@
     "Are you sure you want to upload the following files?": "Are you sure you want to upload the following files?",
     "The following files cannot be uploaded:": "The following files cannot be uploaded:",
     "Upload Files": "Upload Files",
-    "Encrypted room": "Encrypted room",
-    "Unencrypted room": "Unencrypted room",
     "Hangup": "Hangup",
     "Voice call": "Voice call",
     "Video call": "Video call",
@@ -1437,6 +1433,7 @@
     "Users": "Users",
     "unknown device": "unknown device",
     "NOT verified": "NOT verified",
+    "Blacklisted": "Blacklisted",
     "verified": "verified",
     "Name": "Name",
     "Verification": "Verification",