diff --git a/Gruntfile.js b/Gruntfile.js
index dfaf8ea8..0e1e2f98 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -142,7 +142,7 @@ module.exports = function(grunt) {
         expand: true,
         flatten: true,
         cwd: 'node_modules/',
-        src: ['mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js'],
+        src: ['mocha/mocha.css', 'mocha/mocha.js', 'chai/chai.js', 'whatwg-fetch/fetch.js'],
         dest: 'test/lib/'
       },
       unittests: {
diff --git a/README.md b/README.md
index b08db326..120beee7 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,8 @@ OpenPGP.js only supports browsers that implement `window.crypto.getRandomValues`
 
 OpenPGP.js uses ES6 promises which are available in [most modern browsers](http://caniuse.com/#feat=promises). If you need to support browsers that do not support Promises, fear not! There is a [polyfill](https://github.com/jakearchibald/es6-promise), which is included in the build step. So no action required on the developer's part for promises!
 
+For the OpenPGP HTTP Key Server (HKP) client the new [fetch api](https://fetch.spec.whatwg.org) is used. There is a polyfill for both [browsers](https://github.com/github/fetch) and [node.js](https://github.com/bitinn/node-fetch) runtimes. These are not bundled in the library however and users must add these themselves. See the unit tests for examples of how to integrate them.
+
 
 ### Examples
 
diff --git a/package.json b/package.json
index 1c87fe15..4b0404c6 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,9 @@
     "grunt-saucelabs": "8.6.1",
     "grunt-text-replace": "~0.4.0",
     "istanbul": "^0.3.13",
-    "mocha": "~2.2.4"
+    "mocha": "~2.2.4",
+    "node-fetch": "^1.3.3",
+    "whatwg-fetch": "^0.10.1"
   },
   "dependencies": {
     "es6-promise": "^1.0.0",
diff --git a/src/config/config.js b/src/config/config.js
index 17e2298b..7c300466 100644
--- a/src/config/config.js
+++ b/src/config/config.js
@@ -44,7 +44,7 @@ module.exports = {
   versionstring: "OpenPGP.js VERSION",
   commentstring: "http://openpgpjs.org",
 
-  keyserver: "keyserver.linux.it", // "pgp.mit.edu:11371"
+  keyserver: "https://keyserver.ubuntu.com",
   node_store: './openpgp.store',
 
   debug: false
diff --git a/src/hkp/hkp.js b/src/hkp/hkp.js
new file mode 100644
index 00000000..384b3f96
--- /dev/null
+++ b/src/hkp/hkp.js
@@ -0,0 +1,89 @@
+// OpenPGP.js - An OpenPGP implementation in javascript
+// Copyright (C) 2015 Tankred Hase
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3.0 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+'use strict';
+
+/**
+ * This class implements a client for the OpenPGP HTTP Keyserver Protocol (HKP)
+ *   in order to lookup and upload keys on standard public key servers.
+ * @module hkp/hkp
+ */
+module.exports = HKP;
+
+var config = require('../config');
+
+/**
+ * Initialize the HKP client and configure it with the key server url and fetch function.
+ * @constructor
+ * @param {String}    keyServerBaseUrl  (optional) The HKP key server base url including
+ *   the protocol to use e.g. https://pgp.mit.edu
+ * @param {function}  fetch             (optional) The fetch function is an easier way
+ *   to make web requests and handle responses than using an XMLHttpRequest. You can
+ *   pass in a custom implementaion or just leave the parameter empty to fall back to
+ *   window.fetch (https://fetch.spec.whatwg.org).
+ */
+function HKP(keyServerBaseUrl, fetch) {
+  this._baseUrl = keyServerBaseUrl ? keyServerBaseUrl : config.keyserver;
+  this._fetch = fetch ? fetch : typeof window !== 'undefined' && window.fetch;
+}
+
+/**
+ * Search for a public key on the key server either by key ID or part of the user ID.
+ * @param  {String}   options.keyID   The long public key ID.
+ * @param  {String}   options.query   This can be any part of the key user ID such as name.
+ *   or email address
+ * @return {Promise<String>}          The ascii armored public key.
+ */
+HKP.prototype.lookup = function(options) {
+  var uri = this._baseUrl + '/pks/lookup?op=get&options=mr&search=',
+    fetch = this._fetch;
+
+  if (options.keyId) {
+    uri += '0x' + options.keyId;
+  } else if (options.query) {
+    uri += options.query;
+  } else {
+    throw new Error('You must provide a query parameter!');
+  }
+
+  return fetch(uri).then(function(response) {
+    return response.text();
+  }).then(function(publicKeyArmored) {
+    if (!publicKeyArmored || publicKeyArmored.indexOf('-----END PGP PUBLIC KEY BLOCK-----') < 0) {
+      return;
+    }
+    return publicKeyArmored.trim();
+  });
+};
+
+/**
+ * Upload a public key to the server.
+ * @param  {String}   publicKeyArmored  An ascii armored public key to be uploaded.
+ * @return {Promise}
+ */
+HKP.prototype.upload = function(publicKeyArmored) {
+  var uri = this._baseUrl + '/pks/add',
+    fetch = this._fetch;
+
+  return fetch(uri, {
+    method: 'post',
+    headers: {
+      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
+    },
+    body: 'keytext=' + encodeURIComponent(publicKeyArmored)
+  });
+};
diff --git a/src/hkp/index.js b/src/hkp/index.js
new file mode 100644
index 00000000..c3098000
--- /dev/null
+++ b/src/hkp/index.js
@@ -0,0 +1,5 @@
+/**
+ * @see module:hkp/hkp
+ * @module hkp
+ */
+module.exports = require('./hkp.js');
diff --git a/src/index.js b/src/index.js
index e995aa6d..8ee48d8c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -71,3 +71,8 @@ module.exports.Keyring = require('./keyring');
  * @name module:openpgp.AsyncProxy
  */
 module.exports.AsyncProxy = require('./worker/async_proxy.js');
+/**
+ * @see module:hkp
+ * @name module:openpgp.HKP
+ */
+module.exports.HKP = require('./hkp');
diff --git a/test/general/hkp.js b/test/general/hkp.js
new file mode 100644
index 00000000..cbe71bcd
--- /dev/null
+++ b/test/general/hkp.js
@@ -0,0 +1,153 @@
+'use strict';
+
+var openpgp = typeof window !== 'undefined' && window.openpgp ? window.openpgp : require('openpgp');
+var fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch');
+
+var chai = require('chai'),
+  expect = chai.expect;
+
+describe('HKP unit tests', function() {
+  this.timeout(60000);
+
+  var hkp;
+
+  var pub_key = '-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n' +
+      'Version: SKS 1.1.5\r\n' +
+      'Comment: Hostname: keyserver.ubuntu.com\r\n' +
+      '\r\n' +
+      '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\r\n' +
+      'uw9LVuvHh8RGCH2NZY48zdfB\r\n' +
+      '=5obP\r\n' +
+      '-----END PGP PUBLIC KEY BLOCK-----';
+
+  beforeEach(function() {
+    hkp = new openpgp.HKP(openpgp.config.keyserver, fetch);
+  });
+
+  afterEach(function() {});
+
+  describe('lookup', function() {
+    it('by email address should work', function(done) {
+      hkp.lookup({
+        query: 'safewithme.testuser@gmail.com'
+      }).then(function(key) {
+        expect(key).to.exist;
+        done();
+      });
+    });
+
+    it('by email address should not find a key', function(done) {
+      hkp.lookup({
+        query: 'safewithme.testuse@gmail.com'
+      }).then(function(key) {
+        expect(key).to.be.undefined;
+        done();
+      });
+    });
+
+    it('by key id should work', function(done) {
+      hkp.lookup({
+        keyId: 'D7FB93FCDFBFC23C'
+      }).then(function(key) {
+        expect(key).to.exist;
+        done();
+      });
+    });
+  });
+
+  describe('upload', function() {
+    it('should work', function(done) {
+      hkp.upload(pub_key).then(function() {
+        done();
+      });
+    });
+  });
+
+});
diff --git a/test/general/index.js b/test/general/index.js
index 3c88f33d..a9684c6b 100644
--- a/test/general/index.js
+++ b/test/general/index.js
@@ -5,5 +5,6 @@ describe('General', function () {
   require('./keyring.js');
   require('./packet.js');
   require('./signature.js');
+  require('./hkp.js');
 });
 
diff --git a/test/unittests.html b/test/unittests.html
index 04929df3..06db2137 100644
--- a/test/unittests.html
+++ b/test/unittests.html
@@ -13,6 +13,7 @@
     <script src="../dist/openpgp.js"></script>
     <script src="lib/chai.js"></script>
     <script src="lib/mocha.js"></script>
+    <script src="lib/fetch.js"></script>
     <script>
         mocha.setup('bdd');
         mocha.timeout(20000);