diff --git a/ssh/forms.py b/ssh/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..962146d0aeca86678a574330fff73de10a660885
--- /dev/null
+++ b/ssh/forms.py
@@ -0,0 +1,31 @@
+
+import re
+from django import forms
+from django.core.exceptions import ValidationError
+
+class KeyStringField(forms.CharField):
+    def __init__(self, *args, **kwds):
+        kwds["widget"] = forms.Textarea
+        super().__init__(*args, **kwds)
+
+    def to_python(self, value):
+        """Split keystring on whitespace"""
+        if not value:
+            return []
+
+        return re.split("\s+", value)
+
+    def validate(self, value):
+        """Check if there are at least two tokens"""
+        super().validate(value)
+        if len(value) < 2:
+            raise ValidationError("KeyString needs type and key part")
+
+    
+
+class PublicKeyCreateForm(forms.Form):
+    keystring = KeyStringField()
+    hostname = forms.CharField(max_length=128)
+    port = forms.IntegerField(required=False)
+    client_cert = forms.BooleanField(required=False)
+    public = forms.BooleanField(required=False)
diff --git a/ssh/templates/ssh/sshpublickey_create.html b/ssh/templates/ssh/sshpublickey_create.html
new file mode 100644
index 0000000000000000000000000000000000000000..7334027cb92d9b27fc57cdb37ddcc1f859e6d3cd
--- /dev/null
+++ b/ssh/templates/ssh/sshpublickey_create.html
@@ -0,0 +1,11 @@
+{% extends 'keys/base.html' %}
+
+{% block content %}
+<h2>Add public key</h2>
+<form action="" method="post">
+  {% csrf_token %}
+  {{ form.as_p }}
+  <button type="submit">Add</button>
+</form>
+
+{% endblock %}
diff --git a/ssh/templates/ssh/sshpublickey_list.html b/ssh/templates/ssh/sshpublickey_list.html
index 478fd5743d6671cd3ad3ebec54c9be26982e357c..0f6195d5f3e45a4829c9ae08b414e3dc06f5bc17 100644
--- a/ssh/templates/ssh/sshpublickey_list.html
+++ b/ssh/templates/ssh/sshpublickey_list.html
@@ -1,6 +1,11 @@
 {% extends 'keys/base.html' %}
 
 {% block content %}
+
+{% if perms.ssh.add_sshpublickey %}
+<a href="{% url 'ssh-create' %}">Add public key</a>
+{% endif %}
+
 {% if sshpublickey_list %}
 <ul>
 {% for publickey in sshpublickey_list %}
diff --git a/ssh/urls.py b/ssh/urls.py
index 409a87280651c41cdd4e45d18c2f8d7d41cd3b20..8e1257d0b738407be1db6574021e1d614e37118c 100644
--- a/ssh/urls.py
+++ b/ssh/urls.py
@@ -5,5 +5,5 @@ from . import views
 
 urlpatterns = [
     path("", views.PublicKeyListView.as_view(), name="ssh-list"),
-    path("<int:pk>", views.PublicKeyDetailView.as_view(), name="ssh-detail"),
+    path("new", views.publickey_create, name="ssh-create"),
 ]
diff --git a/ssh/views.py b/ssh/views.py
index 9725af443f195cc766bf2402e73b6fa5f0a094e1..3a8cd2bf657d7571ba00ede81e6dc7034832bea8 100644
--- a/ssh/views.py
+++ b/ssh/views.py
@@ -1,14 +1,43 @@
-from django.shortcuts import render
+from django.shortcuts import render, reverse
 from django.views.generic import DetailView, ListView, CreateView
+from django.http import HttpResponseRedirect
 from guardian.mixins import PermissionRequiredMixin, PermissionListMixin
+from guardian.decorators import permission_required
+from guardian.shortcuts import assign_perm
+from guardian.utils import get_anonymous_user
 from . import models
+from . import forms
 
 
 class PublicKeyListView(PermissionListMixin, ListView):
     model = models.SSHPublicKey
     permission_required = ['view_sshpublickey']
 
-class PublicKeyDetailView(PermissionRequiredMixin, DetailView):
-    model = models.SSHPublicKey
-    permission_required = ['view_sshpublickey']
+@permission_required('ssh.add_sshpublickey')
+def publickey_create(request):
+    if request.method == 'POST':
+        form = forms.PublicKeyCreateForm(request.POST)
+        if form.is_valid():
+            pk = models.SSHPublicKey()
+            pk.hostname = form.cleaned_data['hostname']
+            pk.port = form.cleaned_data['port']
+            pk.client_cert = form.cleaned_data['client_cert']
+            pk.keytype, pk.key = form.cleaned_data['keystring'][:2]
+            pk.save()
+
+            assign_perm('view_sshpublickey', request.user, pk)
+            assign_perm('change_sshpublickey', request.user, pk)
+
+            if form.cleaned_data['public']:
+                assign_perm('view_sshpublickey',
+                            get_anonymous_user(),
+                            pk)
+            return HttpResponseRedirect(reverse('ssh-list'))
+
+    # if a GET (or any other method) we'll create a blank form
+    else:
+        form = forms.PublicKeyCreateForm()
 
+    return render(request,
+                  'ssh/sshpublickey_create.html',
+                  {'form': form})