diff --git a/apps/files_external/ajax/addRootCertificate.php b/apps/files_external/ajax/addRootCertificate.php
deleted file mode 100644
index 38b18605945457f844b787b561188e89a7117711..0000000000000000000000000000000000000000
--- a/apps/files_external/ajax/addRootCertificate.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-OCP\JSON::checkAppEnabled('files_external');
-OCP\JSON::callCheck();
-
-if (!($filename = $_FILES['rootcert_import']['name'])) {
-	header('Location:' . OCP\Util::linkToRoute("settings_personal"));
-	exit;
-}
-
-$fh = fopen($_FILES['rootcert_import']['tmp_name'], 'r');
-$data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name']));
-fclose($fh);
-$filename = $_FILES['rootcert_import']['name'];
-
-$certificateManager = \OC::$server->getCertificateManager();
-
-if (!$certificateManager->addCertificate($data, $filename)) {
-	OCP\Util::writeLog('files_external',
-		'Couldn\'t import SSL root certificate (' . $filename . '), allowed formats: PEM and DER',
-		OCP\Util::WARN);
-}
-
-header('Location:' . OCP\Util::linkToRoute("settings_personal"));
-exit;
diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php
index 9965303f21c7813f9e09b0f37301cbfcb30a0a9c..a279163ff701a2e79d6e3a7adf8893b50e6c7cc4 100755
--- a/apps/files_external/personal.php
+++ b/apps/files_external/personal.php
@@ -23,12 +23,10 @@
 OCP\Util::addScript('files_external', 'settings');
 OCP\Util::addStyle('files_external', 'settings');
 $backends = OC_Mount_Config::getPersonalBackends();
-$certificateManager = \OC::$server->getCertificateManager();
 
 $tmpl = new OCP\Template('files_external', 'settings');
 $tmpl->assign('isAdminPage', false);
 $tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
-$tmpl->assign('certs', $certificateManager->listCertificates());
 $tmpl->assign('dependencies', OC_Mount_Config::checkDependencies());
 $tmpl->assign('backends', $backends);
 return $tmpl->fetchPage();
diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php
index dd283f9ff558c2f964feb4a961a3e895b84a9891..072f856dfbdeea7b4eee731f060737960e34292e 100644
--- a/apps/files_external/templates/settings.php
+++ b/apps/files_external/templates/settings.php
@@ -119,30 +119,3 @@
 		</p>
 	<?php endif; ?>
 </form>
-
-<?php if ( ! $_['isAdminPage']):  ?>
-<form id="files_external" class="section"
-	  method="post"
-	  enctype="multipart/form-data"
-	  action="<?php p(OCP\Util::linkTo('files_external', 'ajax/addRootCertificate.php')); ?>">
-		<h2><?php p($l->t('SSL root certificates'));?></h2>
-		<table id="sslCertificate" data-admin='<?php print_unescaped(json_encode($_['isAdminPage'])); ?>'>
-			<tbody>
-			<?php foreach ($_['certs'] as $rootCert): ?>
-			<tr id="<?php p($rootCert) ?>">
-			<td class="rootCert"><?php p($rootCert) ?></td>
-			<td <?php if ($rootCert != ''): ?>class="remove"
-				<?php else: ?>style="visibility:hidden;"
-				<?php endif; ?>><img alt="<?php p($l->t('Delete')); ?>"
-									 title="<?php p($l->t('Delete')); ?>"
-									 class="svg action"
-									 src="<?php print_unescaped(image_path('core', 'actions/delete.svg')); ?>" /></td>
-			</tr>
-			<?php endforeach; ?>
-			</tbody>
-		</table>
-		<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']); ?>">
-		<input type="file" id="rootcert_import" name="rootcert_import">
-		<input type="submit" name="cert_import" value="<?php p($l->t('Import Root Certificate')); ?>" />
-</form>
-<?php endif; ?>
diff --git a/lib/private/certificatemanager.php b/lib/private/certificatemanager.php
index 3a934945786cfb9c3778f115578f4cf04ce8d020..90a30182c65a6ea1965da20bd5571734fded9caf 100644
--- a/lib/private/certificatemanager.php
+++ b/lib/private/certificatemanager.php
@@ -29,7 +29,7 @@ class CertificateManager implements ICertificateManager {
 	/**
 	 * Returns all certificates trusted by the user
 	 *
-	 * @return string[]
+	 * @return \OCP\ICertificate[]
 	 */
 	public function listCertificates() {
 		$path = $this->user->getHome() . '/files_external/uploads/';
@@ -45,7 +45,9 @@ class CertificateManager implements ICertificateManager {
 			return array();
 		}
 		while (false !== ($file = readdir($handle))) {
-			if ($file != '.' && $file != '..') $result[] = $file;
+			if ($file != '.' && $file != '..') {
+				$result[] = new Certificate(file_get_contents($path . $file), $file);
+			}
 		}
 		return $result;
 	}
@@ -75,7 +77,7 @@ class CertificateManager implements ICertificateManager {
 	/**
 	 * @param string $certificate the certificate data
 	 * @param string $name the filename for the certificate
-	 * @return bool
+	 * @return bool | \OCP\ICertificate
 	 */
 	public function addCertificate($certificate, $name) {
 		if (!\OC\Files\Filesystem::isValidPath($name)) {
@@ -93,7 +95,7 @@ class CertificateManager implements ICertificateManager {
 			$file = $this->user->getHome() . '/files_external/uploads/' . $name;
 			file_put_contents($file, $certificate);
 			$this->createCertificateBundle();
-			return true;
+			return new Certificate($certificate, $name);
 		} else {
 			return false;
 		}
diff --git a/lib/private/l10n.php b/lib/private/l10n.php
index 28b35e92a2f74316b482f84c2ce14b1ca21152f6..57886a796cd15ae4b72cebc9305ef96edf013ebc 100644
--- a/lib/private/l10n.php
+++ b/lib/private/l10n.php
@@ -354,7 +354,7 @@ class OC_L10N implements \OCP\IL10N {
 			case 'datetime':
 			case 'time':
 				if($data instanceof DateTime) {
-					return $data->format($this->localizations[$type]);
+					$data = $data->getTimestamp();
 				} elseif(is_string($data) && !is_numeric($data)) {
 					$data = strtotime($data);
 				}
diff --git a/lib/public/icertificatemanager.php b/lib/public/icertificatemanager.php
index 9ce7d721178e882aa0d26e0aea496740b98681d6..24b8d1236341863542038b6a8dc1467c599b68ab 100644
--- a/lib/public/icertificatemanager.php
+++ b/lib/public/icertificatemanager.php
@@ -15,14 +15,14 @@ interface ICertificateManager {
 	/**
 	 * Returns all certificates trusted by the user
 	 *
-	 * @return string[]
+	 * @return \OCP\ICertificate[]
 	 */
 	public function listCertificates();
 
 	/**
 	 * @param string $certificate the certificate data
 	 * @param string $name the filename for the certificate
-	 * @return bool
+	 * @return bool | \OCP\ICertificate
 	 */
 	public function addCertificate($certificate, $name);
 
diff --git a/settings/ajax/addRootCertificate.php b/settings/ajax/addRootCertificate.php
new file mode 100644
index 0000000000000000000000000000000000000000..9be8fd0025b7611207c34e63b886eeef2cb88da9
--- /dev/null
+++ b/settings/ajax/addRootCertificate.php
@@ -0,0 +1,34 @@
+<?php
+
+OCP\JSON::checkAppEnabled('files_external');
+OCP\JSON::callCheck();
+
+$l = new OC_L10N('core');
+
+if (!($filename = $_FILES['rootcert_import']['name'])) {
+	header('Location:' . OCP\Util::linkToRoute("settings_personal"));
+	exit;
+}
+
+$fh = fopen($_FILES['rootcert_import']['tmp_name'], 'r');
+$data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name']));
+fclose($fh);
+$filename = $_FILES['rootcert_import']['name'];
+
+$certificateManager = \OC::$server->getCertificateManager();
+
+if ($cert = $certificateManager->addCertificate($data, $filename)) {
+	OCP\JSON::success(array(
+		'name' => $cert->getName(),
+		'commonName' => $cert->getCommonName(),
+		'organization' => $cert->getOrganization(),
+		'validFrom' => $cert->getIssueDate()->getTimestamp(),
+		'validTill' => $cert->getExpireDate()->getTimestamp(),
+		'validFromString' => $l->l('date', $cert->getIssueDate()),
+		'validTillString' => $l->l('date', $cert->getExpireDate()),
+		'issuer' => $cert->getIssuerName(),
+		'issuerOrganization' => $cert->getIssuerOrganization()
+	));
+} else {
+	OCP\JSON::error(array('error' => 'Couldn\'t import SSL root certificate, allowed formats: PEM and DER'));
+}
diff --git a/apps/files_external/ajax/removeRootCertificate.php b/settings/ajax/removeRootCertificate.php
similarity index 100%
rename from apps/files_external/ajax/removeRootCertificate.php
rename to settings/ajax/removeRootCertificate.php
diff --git a/settings/css/settings.css b/settings/css/settings.css
index a62a971b831eb2de435c6ef98b8b417fe854309b..95fab85df97766dd504a1b2c133f42e40cedf19d 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -6,9 +6,11 @@ select#languageinput, select#timezone { width:15em; }
 input#openid, input#webdav { width:20em; }
 
 /* PERSONAL */
-#rootcert_import {
-	margin: 0 0 10px 0;
-	display: block;
+#sslCertificate tr.expired {
+	background-color: rgba(255, 0, 0, 0.5);
+}
+#sslCertificate td {
+	padding: 5px;
 }
 
 /* Sync clients */
diff --git a/settings/js/personal.js b/settings/js/personal.js
index f56dd3425f7666cc7946878af42cd53b55389e08..d6763cdb2955318624503bd7668b09063c7c566c 100644
--- a/settings/js/personal.js
+++ b/settings/js/personal.js
@@ -13,12 +13,12 @@
  *
  * @param callback
  */
-jQuery.fn.keyUpDelayedOrEnter = function(callback){
+jQuery.fn.keyUpDelayedOrEnter = function (callback) {
 	var cb = callback;
 	var that = this;
 	this.keyup(_.debounce(function (event) {
 		// enter is already handled in keypress
-		if(event.keyCode === 13) {
+		if (event.keyCode === 13) {
 			return;
 		}
 		if (that.val() !== '') {
@@ -27,7 +27,7 @@ jQuery.fn.keyUpDelayedOrEnter = function(callback){
 	}, 1000));
 
 	this.keypress(function (event) {
-		if (event.keyCode === 13 && that.val() !== '' ){
+		if (event.keyCode === 13 && that.val() !== '') {
 			event.preventDefault();
 			cb();
 		}
@@ -38,48 +38,48 @@ jQuery.fn.keyUpDelayedOrEnter = function(callback){
 /**
  * Post the email address change to the server.
  */
-function changeEmailAddress(){
-    var emailInfo = $('#email');
-    if (emailInfo.val() === emailInfo.defaultValue){
-        return;
-    }
-    emailInfo.defaultValue = emailInfo.val();
-    OC.msg.startSaving('#lostpassword .msg');
-    var post = $( "#lostpassword" ).serialize();
-    $.post( 'ajax/lostpassword.php', post, function(data){
-        OC.msg.finishedSaving('#lostpassword .msg', data);
-    });
+function changeEmailAddress () {
+	var emailInfo = $('#email');
+	if (emailInfo.val() === emailInfo.defaultValue) {
+		return;
+	}
+	emailInfo.defaultValue = emailInfo.val();
+	OC.msg.startSaving('#lostpassword .msg');
+	var post = $("#lostpassword").serialize();
+	$.post('ajax/lostpassword.php', post, function (data) {
+		OC.msg.finishedSaving('#lostpassword .msg', data);
+	});
 }
 
 /**
  * Post the display name change to the server.
  */
-function changeDisplayName(){
-    if ($('#displayName').val() !== '' ) {
-        OC.msg.startSaving('#displaynameform .msg');
-        // Serialize the data
-        var post = $( "#displaynameform" ).serialize();
-        // Ajax foo
-        $.post( 'ajax/changedisplayname.php', post, function(data){
-            if( data.status === "success" ){
-                $('#oldDisplayName').val($('#displayName').val());
-                // update displayName on the top right expand button
-                $('#expandDisplayName').text($('#displayName').val());
-                updateAvatar();
-            }
-            else{
-                $('#newdisplayname').val(data.data.displayName);
-            }
-            OC.msg.finishedSaving('#displaynameform .msg', data);
-        });
-    }
+function changeDisplayName () {
+	if ($('#displayName').val() !== '') {
+		OC.msg.startSaving('#displaynameform .msg');
+		// Serialize the data
+		var post = $("#displaynameform").serialize();
+		// Ajax foo
+		$.post('ajax/changedisplayname.php', post, function (data) {
+			if (data.status === "success") {
+				$('#oldDisplayName').val($('#displayName').val());
+				// update displayName on the top right expand button
+				$('#expandDisplayName').text($('#displayName').val());
+				updateAvatar();
+			}
+			else {
+				$('#newdisplayname').val(data.data.displayName);
+			}
+			OC.msg.finishedSaving('#displaynameform .msg', data);
+		});
+	}
 }
 
 function updateAvatar (hidedefault) {
 	var $headerdiv = $('#header .avatardiv');
 	var $displaydiv = $('#displayavatar .avatardiv');
 
-	if(hidedefault) {
+	if (hidedefault) {
 		$headerdiv.hide();
 		$('#header .avatardiv').removeClass('avatardiv-shown');
 	} else {
@@ -93,16 +93,16 @@ function updateAvatar (hidedefault) {
 	$('#removeavatar').show();
 }
 
-function showAvatarCropper() {
+function showAvatarCropper () {
 	var $cropper = $('#cropper');
 	$cropper.prepend("<img>");
 	var $cropperImage = $('#cropper img');
 
 	$cropperImage.attr('src',
-		OC.generateUrl('/avatar/tmp')+'?requesttoken='+oc_requesttoken+'#'+Math.floor(Math.random()*1000));
+		OC.generateUrl('/avatar/tmp') + '?requesttoken=' + oc_requesttoken + '#' + Math.floor(Math.random() * 1000));
 
 	// Looks weird, but on('load', ...) doesn't work in IE8
-	$cropperImage.ready(function(){
+	$cropperImage.ready(function () {
 		$('#displayavatar').hide();
 		$cropper.show();
 
@@ -117,7 +117,7 @@ function showAvatarCropper() {
 	});
 }
 
-function sendCropData() {
+function sendCropData () {
 	cleanCropper();
 
 	var cropperData = $('#cropper').data();
@@ -130,11 +130,11 @@ function sendCropData() {
 	$.post(OC.generateUrl('/avatar/cropped'), {crop: data}, avatarResponseHandler);
 }
 
-function saveCoords(c) {
+function saveCoords (c) {
 	$('#cropper').data(c);
 }
 
-function cleanCropper() {
+function cleanCropper () {
 	var $cropper = $('#cropper');
 	$('#displayavatar').show();
 	$cropper.hide();
@@ -143,7 +143,7 @@ function cleanCropper() {
 	$('#cropper img').remove();
 }
 
-function avatarResponseHandler(data) {
+function avatarResponseHandler (data) {
 	var $warning = $('#avatar .warning');
 	$warning.hide();
 	if (data.status === "success") {
@@ -156,20 +156,20 @@ function avatarResponseHandler(data) {
 	}
 }
 
-$(document).ready(function(){
-	$("#passwordbutton").click( function(){
+$(document).ready(function () {
+	$("#passwordbutton").click(function () {
 		if ($('#pass1').val() !== '' && $('#pass2').val() !== '') {
 			// Serialize the data
-			var post = $( "#passwordform" ).serialize();
+			var post = $("#passwordform").serialize();
 			$('#passwordchanged').hide();
 			$('#passworderror').hide();
 			// Ajax foo
-			$.post(OC.generateUrl('/settings/personal/changepassword'), post, function(data){
-				if( data.status === "success" ){
+			$.post(OC.generateUrl('/settings/personal/changepassword'), post, function (data) {
+				if (data.status === "success") {
 					$('#pass1').val('');
 					$('#pass2').val('');
 					$('#passwordchanged').show();
-				} else{
+				} else {
 					if (typeof(data.data) !== "undefined") {
 						$('#passworderror').html(data.data.message);
 					} else {
@@ -190,22 +190,22 @@ $(document).ready(function(){
 	$('#displayName').keyUpDelayedOrEnter(changeDisplayName);
 	$('#email').keyUpDelayedOrEnter(changeEmailAddress);
 
-	$("#languageinput").change( function(){
+	$("#languageinput").change(function () {
 		// Serialize the data
-		var post = $( "#languageinput" ).serialize();
+		var post = $("#languageinput").serialize();
 		// Ajax foo
-		$.post( 'ajax/setlanguage.php', post, function(data){
-			if( data.status === "success" ){
+		$.post('ajax/setlanguage.php', post, function (data) {
+			if (data.status === "success") {
 				location.reload();
 			}
-			else{
-				$('#passworderror').html( data.data.message );
+			else {
+				$('#passworderror').html(data.data.message);
 			}
 		});
 		return false;
 	});
 
-	$('button:button[name="submitDecryptAll"]').click(function() {
+	$('button:button[name="submitDecryptAll"]').click(function () {
 		var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
 		$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
 		$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
@@ -213,23 +213,23 @@ $(document).ready(function(){
 	});
 
 
-	$('button:button[name="submitRestoreKeys"]').click(function() {
+	$('button:button[name="submitRestoreKeys"]').click(function () {
 		$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true);
 		$('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true);
 		OC.Encryption.restoreKeys();
 	});
 
-	$('button:button[name="submitDeleteKeys"]').click(function() {
+	$('button:button[name="submitDeleteKeys"]').click(function () {
 		$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", true);
 		$('#restoreBackupKeys button:button[name="submitRestoreKeys"]').prop("disabled", true);
 		OC.Encryption.deleteKeys();
 	});
 
-	$('#decryptAll input:password[name="privateKeyPassword"]').keyup(function(event) {
+	$('#decryptAll input:password[name="privateKeyPassword"]').keyup(function (event) {
 		var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
-		if (privateKeyPassword !== '' ) {
+		if (privateKeyPassword !== '') {
 			$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", false);
-			if(event.which === 13) {
+			if (event.which === 13) {
 				$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
 				$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
 				OC.Encryption.decryptAll(privateKeyPassword);
@@ -240,21 +240,21 @@ $(document).ready(function(){
 	});
 
 	var uploadparms = {
-		done: function(e, data) {
+		done: function (e, data) {
 			avatarResponseHandler(data.result);
 		}
 	};
 
-	$('#uploadavatarbutton').click(function(){
+	$('#uploadavatarbutton').click(function () {
 		$('#uploadavatar').click();
 	});
 
 	$('#uploadavatar').fileupload(uploadparms);
 
-	$('#selectavatar').click(function(){
+	$('#selectavatar').click(function () {
 		OC.dialogs.filepicker(
 			t('settings', "Select a profile picture"),
-			function(path){
+			function (path) {
 				$.post(OC.generateUrl('/avatar/'), {path: path}, avatarResponseHandler);
 			},
 			false,
@@ -262,27 +262,27 @@ $(document).ready(function(){
 		);
 	});
 
-	$('#removeavatar').click(function(){
+	$('#removeavatar').click(function () {
 		$.ajax({
-			type:	'DELETE',
-			url:	OC.generateUrl('/avatar/'),
-			success: function() {
+			type: 'DELETE',
+			url: OC.generateUrl('/avatar/'),
+			success: function () {
 				updateAvatar(true);
 				$('#removeavatar').hide();
 			}
 		});
 	});
 
-	$('#abortcropperbutton').click(function(){
+	$('#abortcropperbutton').click(function () {
 		cleanCropper();
 	});
 
-	$('#sendcropperbutton').click(function(){
+	$('#sendcropperbutton').click(function () {
 		sendCropData();
 	});
 
 	$('#pass2').strengthify({
-		zxcvbn: OC.linkTo('3rdparty','zxcvbn/js/zxcvbn.js'),
+		zxcvbn: OC.linkTo('3rdparty', 'zxcvbn/js/zxcvbn.js'),
 		titles: [
 			t('core', 'Very weak password'),
 			t('core', 'Weak password'),
@@ -298,18 +298,59 @@ $(document).ready(function(){
 		'/avatar/{user}/{size}',
 		{user: OC.currentUser, size: 1}
 	) + '?requesttoken=' + oc_requesttoken;
-	$.get(url, function(result) {
+	$.get(url, function (result) {
 		if (typeof(result) === 'object') {
 			$('#removeavatar').hide();
 		}
 	});
-} );
+
+	$('#sslCertificate').on('click', 'td.remove > img', function () {
+		var row = $(this).parent().parent();
+		$.post(OC.filePath('settings', 'ajax', 'removeRootCertificate.php'), {
+			cert: row.data('name')
+		});
+		row.remove();
+		return true;
+	});
+
+	$('#sslCertificate tr > td').tipsy({fade: true, gravity: 'n', live: true});
+
+	$('#rootcert_import').fileupload({
+		done: function (e, data) {
+			console.log(data.result);
+			var issueDate = new Date(data.result.validFrom * 1000);
+			var expireDate = new Date(data.result.validTill * 1000);
+			var now = new Date();
+			var isExpired = !(issueDate <= now && now <= expireDate);
+
+			var row = $('<tr/>');
+			row.addClass(isExpired? 'expired': 'valid');
+			row.append($('<td/>').attr('title', data.result.organization).text(data.result.commonName));
+			row.append($('<td/>').attr('title', t('core,', 'Valid from {date}', {date: data.result.validFromString}))
+				.text(data.result.validTillString));
+			row.append($('<td/>').attr('title', data.result.issuerOrganization).text(data.result.issuer));
+			row.append($('<td/>').addClass('remove').append(
+				$('<img/>').attr({
+					alt: t('core', 'Delete'),
+					title: t('core', 'Delete'),
+					src: OC.imagePath('core', 'actions/delete.svg')
+				}).addClass('action')
+			));
+
+			$('#sslCertificate tbody').append(row);
+		}
+	});
+
+	$('#rootcert_import_button').click(function () {
+		$('#rootcert_import').click();
+	});
+});
 
 OC.Encryption = {
-	decryptAll: function(password) {
+	decryptAll: function (password) {
 		var message = t('settings', 'Decrypting files... Please wait, this can take some time.');
 		OC.Encryption.msg.start('#decryptAll .msg', message);
-		$.post('ajax/decryptall.php', {password:password}, function(data) {
+		$.post('ajax/decryptall.php', {password: password}, function (data) {
 			if (data.status === "error") {
 				OC.Encryption.msg.finished('#decryptAll .msg', data);
 				$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", false);
@@ -320,10 +361,10 @@ OC.Encryption = {
 		});
 	},
 
-	deleteKeys: function() {
+	deleteKeys: function () {
 		var message = t('settings', 'Delete encryption keys permanently.');
 		OC.Encryption.msg.start('#restoreBackupKeys .msg', message);
-		$.post('ajax/deletekeys.php', null, function(data) {
+		$.post('ajax/deletekeys.php', null, function (data) {
 			if (data.status === "error") {
 				OC.Encryption.msg.finished('#restoreBackupKeys .msg', data);
 				$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false);
@@ -334,10 +375,10 @@ OC.Encryption = {
 		});
 	},
 
-	restoreKeys: function() {
+	restoreKeys: function () {
 		var message = t('settings', 'Restore encryption keys.');
 		OC.Encryption.msg.start('#restoreBackupKeys .msg', message);
-		$.post('ajax/restorekeys.php', {}, function(data) {
+		$.post('ajax/restorekeys.php', {}, function (data) {
 			if (data.status === "error") {
 				OC.Encryption.msg.finished('#restoreBackupKeys .msg', data);
 				$('#restoreBackupKeys button:button[name="submitDeleteKeys"]').prop("disabled", false);
@@ -349,24 +390,24 @@ OC.Encryption = {
 	}
 };
 
-OC.Encryption.msg={
-	start:function(selector, msg){
-		var spinner = '<img src="'+ OC.imagePath('core', 'loading-small.gif') +'">';
+OC.Encryption.msg = {
+	start: function (selector, msg) {
+		var spinner = '<img src="' + OC.imagePath('core', 'loading-small.gif') + '">';
 		$(selector)
-			.html( msg + ' ' + spinner )
+			.html(msg + ' ' + spinner)
 			.removeClass('success')
 			.removeClass('error')
 			.stop(true, true)
 			.show();
 	},
-	finished:function(selector, data){
-		if( data.status === "success" ){
-			$(selector).html( data.data.message )
+	finished: function (selector, data) {
+		if (data.status === "success") {
+			$(selector).html(data.data.message)
 				.addClass('success')
 				.stop(true, true)
 				.delay(3000);
-		}else{
-			$(selector).html( data.data.message ).addClass('error');
+		} else {
+			$(selector).html(data.data.message).addClass('error');
 		}
 	}
 };
diff --git a/settings/personal.php b/settings/personal.php
index a72b293413a363606fcbf071469040da488758ea..d426fd7f359afb221c874474ebbbc9a5d4b2d56d 100644
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -8,6 +8,7 @@
 OC_Util::checkLoggedIn();
 
 $defaults = new OC_Defaults(); // initialize themable default strings and urls
+$certificateManager = \OC::$server->getCertificateManager();
 
 // Highlight navigation entry
 OC_Util::addScript( 'settings', 'personal' );
@@ -98,6 +99,7 @@ $tmpl->assign('backupKeysExists' , $backupKeysExists);
 $tmpl->assign('filesStillEncrypted' , $filesStillEncrypted);
 $tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
 $tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
+$tmpl->assign('certs', $certificateManager->listCertificates());
 
 $forms=OC_App::getForms('personal');
 $tmpl->assign('forms', array());
diff --git a/settings/routes.php b/settings/routes.php
index 1c8ad1b3fe8801fad32d5ea40bd138bf5748c1ef..c7bab409d4b5e9c97db67d96c934aa0c19186b43 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -62,6 +62,10 @@ $this->create('settings_ajax_restorekeys', '/settings/ajax/restorekeys.php')
 	->actionInclude('settings/ajax/restorekeys.php');
 $this->create('settings_ajax_deletekeys', '/settings/ajax/deletekeys.php')
 	->actionInclude('settings/ajax/deletekeys.php');
+$this->create('core_cert_post', '/settings/ajax/addRootCertificate.php')
+	->actionInclude('settings/ajax/addRootCertificate.php');
+$this->create('core_cert_remove', '/settings/ajax/removeRootCertificate.php')
+	->actionInclude('settings/ajax/removeRootCertificate.php');
 // apps
 $this->create('settings_ajax_apps_ocs', '/settings/ajax/apps/ocs.php')
 	->actionInclude('settings/ajax/apps/ocs.php');
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index c1fb20dce05187b13864c2938bff95925ab67a55..6d07b89954476456c81a66725ba7bc7ff3d8d681 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -150,6 +150,44 @@ if($_['passwordChangeSupported']) {
 	print_unescaped($form);
 };?>
 
+<div class="section">
+	<h2><?php p($l->t('SSL root certificates')); ?></h2>
+	<table id="sslCertificate" class="grid">
+		<thead>
+			<th><?php p($l->t('Common Name')); ?></th>
+			<th><?php p($l->t('Valid until')); ?></th>
+			<th><?php p($l->t('Issued By')); ?></th>
+			<th/>
+		</thead>
+		<tbody>
+			<?php foreach ($_['certs'] as $rootCert): /**@var \OCP\ICertificate $rootCert*/?>
+				<tr class="<?php echo ($rootCert->isExpired()) ? 'expired' : 'valid' ?>" data-name="<?php p($rootCert->getName()) ?>">
+					<td class="rootCert" title="<?php p($rootCert->getOrganization())?>">
+						<?php p($rootCert->getCommonName()) ?>
+					</td>
+					<td title="<?php p($l->t('Valid from %s', $l->l('date', $rootCert->getExpireDate()))) ?>">
+						<?php echo $l->l('date', $rootCert->getExpireDate()) ?>
+					</td>
+					<td title="<?php p($rootCert->getIssuerOrganization()) ?>">
+						<?php p($rootCert->getIssuerName()) ?>
+					</td>
+					<td <?php if ($rootCert != ''): ?>class="remove"
+						<?php else: ?>style="visibility:hidden;"
+						<?php endif; ?>><img alt="<?php p($l->t('Delete')); ?>"
+											 title="<?php p($l->t('Delete')); ?>"
+											 class="svg action"
+											 src="<?php print_unescaped(image_path('core', 'actions/delete.svg')); ?>"/>
+					</td>
+				</tr>
+			<?php endforeach; ?>
+		</tbody>
+	</table>
+	<form class="uploadButton" method="post" action="<?php p(\OC_Helper::linkToRoute('core_cert_post')); ?>" target="certUploadFrame">
+		<input type="file" id="rootcert_import" name="rootcert_import" class="hidden">
+		<input type="button" id="rootcert_import_button" value="<?php p($l->t('Import Root Certificate')); ?>"/>
+	</form>
+</div>
+
 <?php if($_['enableDecryptAll']): ?>
 <div class="section">
 
@@ -177,11 +215,8 @@ if($_['passwordChangeSupported']) {
 	</p>
 	<br />
 	</div>
-
 	<?php endif; ?>
 
-
-
 	<div id="restoreBackupKeys" <?php $_['backupKeysExists'] ? '' : print_unescaped("class='hidden'") ?>>
 
 	<?php p($l->t( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." )); ?>