diff --git a/src/crypto/pkcs1.js b/src/crypto/pkcs1.js
index 38dc0671..71719651 100644
--- a/src/crypto/pkcs1.js
+++ b/src/crypto/pkcs1.js
@@ -54,7 +54,7 @@ function getPkcs1Padding(length) {
   let result = '';
   let randomByte;
   while (result.length < length) {
-    randomByte = random.getSecureRandomOctet();
+    randomByte = random.getRandomBytes(1)[0];
     if (randomByte !== 0) {
       result += String.fromCharCode(randomByte);
     }
diff --git a/src/crypto/random.js b/src/crypto/random.js
index 320c70dd..e00af509 100644
--- a/src/crypto/random.js
+++ b/src/crypto/random.js
@@ -38,49 +38,7 @@ export default {
    * @return {Uint8Array} Random byte array
    */
   getRandomBytes: function(length) {
-    const result = new Uint8Array(length);
-    for (let i = 0; i < length; i++) {
-      result[i] = this.getSecureRandomOctet();
-    }
-    return result;
-  },
-
-  /**
-   * Return a secure random number in the specified range
-   * @param {Integer} from Min of the random number
-   * @param {Integer} to Max of the random number (max 32bit)
-   * @return {Integer} A secure random number
-   */
-  getSecureRandom: function(from, to) {
-    let randUint = this.getSecureRandomUint();
-    const bits = ((to - from)).toString(2).length;
-    while ((randUint & ((2 ** bits) - 1)) > (to - from)) {
-      randUint = this.getSecureRandomUint();
-    }
-    return from + (Math.abs(randUint & ((2 ** bits) - 1)));
-  },
-
-  getSecureRandomOctet: function() {
-    const buf = new Uint8Array(1);
-    this.getRandomValues(buf);
-    return buf[0];
-  },
-
-  getSecureRandomUint: function() {
-    const buf = new Uint8Array(4);
-    const dv = new DataView(buf.buffer);
-    this.getRandomValues(buf);
-    return dv.getUint32(0);
-  },
-
-  /**
-   * Helper routine which calls platform specific crypto random generator
-   * @param {Uint8Array} buf
-   */
-  getRandomValues: function(buf) {
-    if (!(buf instanceof Uint8Array)) {
-      throw new Error('Invalid type: buf not an Uint8Array');
-    }
+    const buf = new Uint8Array(length);
     if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
       window.crypto.getRandomValues(buf);
     } else if (typeof window !== 'undefined' && typeof window.msCrypto === 'object' && typeof window.msCrypto.getRandomValues === 'function') {
@@ -126,15 +84,17 @@ export default {
 function RandomBuffer() {
   this.buffer = null;
   this.size = null;
+  this.callback = null;
 }
 
 /**
  * Initialize buffer
  * @param  {Integer} size size of buffer
  */
-RandomBuffer.prototype.init = function(size) {
+RandomBuffer.prototype.init = function(size, callback) {
   this.buffer = new Uint8Array(size);
   this.size = 0;
+  this.callback = callback;
 };
 
 /**
diff --git a/src/packet/sym_encrypted_aead_protected.js b/src/packet/sym_encrypted_aead_protected.js
index 631ea56a..0557883c 100644
--- a/src/packet/sym_encrypted_aead_protected.js
+++ b/src/packet/sym_encrypted_aead_protected.js
@@ -79,7 +79,7 @@ SymEncryptedAEADProtected.prototype.decrypt = function (sessionKeyAlgorithm, key
  * @return {Promise<undefined>}           Nothing is returned
  */
 SymEncryptedAEADProtected.prototype.encrypt = function (sessionKeyAlgorithm, key) {
-  this.iv = crypto.random.getRandomValues(new Uint8Array(IV_LEN)); // generate new random IV
+  this.iv = crypto.random.getRandomBytes(IV_LEN); // generate new random IV
   return crypto.gcm.encrypt(sessionKeyAlgorithm, this.packets.write(), key, this.iv).then(encrypted => {
     this.encrypted = encrypted;
   });
diff --git a/src/worker/async_proxy.js b/src/worker/async_proxy.js
index 4e68e25c..3e42cd42 100644
--- a/src/worker/async_proxy.js
+++ b/src/worker/async_proxy.js
@@ -20,7 +20,6 @@ import crypto from '../crypto';
 import packet from '../packet';
 
 const INITIAL_RANDOM_SEED = 50000; // random bytes seeded to worker
-const RANDOM_SEED_REQUEST = 20000; // random bytes seeded after worker request
 
 /**
  * Initializes a new proxy and loads the web worker
@@ -75,7 +74,7 @@ AsyncProxy.prototype.onMessage = function(event) {
       delete this.tasks[msg.id];
       break;
     case 'request-seed':
-      this.seedRandom(RANDOM_SEED_REQUEST);
+      this.seedRandom(msg.amount);
       break;
     default:
       throw new Error('Unknown Worker Event.');
@@ -87,24 +86,10 @@ AsyncProxy.prototype.onMessage = function(event) {
  * @param  {Integer} size Number of bytes to send
  */
 AsyncProxy.prototype.seedRandom = function(size) {
-  const buf = this.getRandomBuffer(size);
+  const buf = crypto.random.getRandomBytes(size);
   this.worker.postMessage({ event:'seed-random', buf }, util.getTransferables(buf));
 };
 
-/**
- * Get Uint8Array with random numbers
- * @param  {Integer} size Length of buffer
- * @return {Uint8Array}
- */
-AsyncProxy.prototype.getRandomBuffer = function(size) {
-  if (!size) {
-    return null;
-  }
-  const buf = new Uint8Array(size);
-  crypto.random.getRandomValues(buf);
-  return buf;
-};
-
 /**
  * Terminates the worker
  */
diff --git a/src/worker/worker.js b/src/worker/worker.js
index b0354aac..7b934376 100644
--- a/src/worker/worker.js
+++ b/src/worker/worker.js
@@ -24,10 +24,29 @@ self.window = {}; // to make UMD bundles work
 importScripts('openpgp.js');
 var openpgp = window.openpgp;
 
+var randomQueue = [];
+var randomRequested = false;
 var MIN_SIZE_RANDOM_BUFFER = 40000;
 var MAX_SIZE_RANDOM_BUFFER = 60000;
+var MIN_SIZE_RANDOM_REQUEST = 20000;
 
-openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
+/**
+ * Handle random buffer exhaustion by requesting more random bytes from the main window
+ * @return {Promise<Object>}  Empty promise whose resolution indicates that the buffer has been refilled
+ */
+function randomCallback() {
+
+  if (!randomRequested) {
+    self.postMessage({ event: 'request-seed', amount: MAX_SIZE_RANDOM_BUFFER });
+  }
+  randomRequested = true;
+
+  return new Promise(function(resolve, reject) {
+    randomQueue.push(resolve);
+  });
+}
+
+openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER, randomCallback);
 
 /**
  * Handle messages from the main window.
@@ -43,6 +62,13 @@ self.onmessage = function(event) {
 
     case 'seed-random':
       seedRandom(msg.buf);
+
+      var queueCopy = randomQueue;
+      randomQueue = [];
+      for (var i = 0; i < queueCopy.length; i++) {
+        queueCopy[i]();
+      }
+
       break;
 
     default:
@@ -99,8 +125,8 @@ function delegate(id, method, options) {
  * @param  {Object} event  Contains event type and data
  */
 function response(event) {
-  if (openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
-    self.postMessage({ event: 'request-seed' });
+  if (!randomRequested && openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
+    self.postMessage({ event: 'request-seed', amount: MIN_SIZE_RANDOM_REQUEST });
   }
   self.postMessage(event, openpgp.util.getTransferables(event.data));
 }
diff --git a/test/crypto/crypto.js b/test/crypto/crypto.js
index 0a59504d..fde07520 100644
--- a/test/crypto/crypto.js
+++ b/test/crypto/crypto.js
@@ -309,7 +309,7 @@ describe('API functional testing', function() {
         if(algo.substr(0,3) === 'aes') {
           it(algo, function() {
             const key = crypto.generateSessionKey(algo);
-            const iv = crypto.random.getRandomValues(new Uint8Array(crypto.gcm.ivLength));
+            const iv = crypto.random.getRandomBytes(crypto.gcm.ivLength);
 
             return crypto.gcm.encrypt(
               algo, util.str_to_Uint8Array(plaintext), key, iv