diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 8fde8aa..9b6d555 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1935,68 +1935,6 @@ function drupal_set_title($title = NULL, $output = CHECK_PLAIN) {
 }
 
 /**
- * Returns a string of highly randomized bytes (over the full 8-bit range).
- *
- * This function is better than simply calling mt_rand() or any other built-in
- * PHP function because it can return a long string of bytes (compared to < 4
- * bytes normally from mt_rand()) and uses the best available pseudo-random
- * source.
- *
- * @param $count
- *   The number of characters (bytes) to return in the string.
- */
-function drupal_random_bytes($count)  {
-  // $random_state does not use drupal_static as it stores random bytes.
-  static $random_state, $bytes, $php_compatible;
-  // Initialize on the first call. The contents of $_SERVER includes a mix of
-  // user-specific and system information that varies a little with each page.
-  if (!isset($random_state)) {
-    $random_state = print_r($_SERVER, TRUE);
-    if (function_exists('getmypid')) {
-      // Further initialize with the somewhat random PHP process ID.
-      $random_state .= getmypid();
-    }
-    $bytes = '';
-  }
-  if (strlen($bytes) < $count) {
-    // PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes()
-    // locking on Windows and rendered it unusable.
-    if (!isset($php_compatible)) {
-      $php_compatible = version_compare(PHP_VERSION, '5.3.4', '>=');
-    }
-    // /dev/urandom is available on many *nix systems and is considered the
-    // best commonly available pseudo-random source.
-    if ($fh = @fopen('/dev/urandom', 'rb')) {
-      // PHP only performs buffered reads, so in reality it will always read
-      // at least 4096 bytes. Thus, it costs nothing extra to read and store
-      // that much so as to speed any additional invocations.
-      $bytes .= fread($fh, max(4096, $count));
-      fclose($fh);
-    }
-    // openssl_random_pseudo_bytes() will find entropy in a system-dependent
-    // way.
-    elseif ($php_compatible && function_exists('openssl_random_pseudo_bytes')) {
-      $bytes .= openssl_random_pseudo_bytes($count - strlen($bytes));
-    }
-    // If /dev/urandom is not available or returns no bytes, this loop will
-    // generate a good set of pseudo-random bytes on any system.
-    // Note that it may be important that our $random_state is passed
-    // through hash() prior to being rolled into $output, that the two hash()
-    // invocations are different, and that the extra input into the first one -
-    // the microtime() - is prepended rather than appended. This is to avoid
-    // directly leaking $random_state via the $output stream, which could
-    // allow for trivial prediction of further "random" numbers.
-    while (strlen($bytes) < $count) {
-      $random_state = hash('sha256', microtime() . mt_rand() . $random_state);
-      $bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
-    }
-  }
-  $output = substr($bytes, 0, $count);
-  $bytes = substr($bytes, $count);
-  return $output;
-}
-
-/**
  * Calculates a base-64 encoded, URL-safe sha-256 hmac.
  *
  * @param $data
diff --git a/core/includes/common.inc b/core/includes/common.inc
index d3a4c55..76105f1 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -5,6 +5,7 @@
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Drupal\Component\PhpStorage\PhpStorageFactory;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Component\Utility\RandomBytes;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\Core\Database\Database;
@@ -4815,7 +4816,7 @@ function drupal_get_hash_salt() {
  */
 function drupal_get_private_key() {
   if (!($key = variable_get('drupal_private_key', 0))) {
-    $key = drupal_hash_base64(drupal_random_bytes(55));
+    $key = drupal_hash_base64(RandomBytes::generate(55));
     variable_set('drupal_private_key', $key);
   }
   return $key;
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 34a9940..56d0816 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Component\Utility\RandomBytes;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\Install\TaskException;
@@ -1107,7 +1108,7 @@ function install_settings_form_submit($form, &$form_state) {
     'required' => TRUE,
   );
   $settings['drupal_hash_salt'] = array(
-    'value'    => drupal_hash_base64(drupal_random_bytes(55)),
+    'value'    => drupal_hash_base64(RandomBytes::generate(55)),
     'required' => TRUE,
   );
 
diff --git a/core/includes/install.inc b/core/includes/install.inc
index d33bb0a..af9b220 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -5,6 +5,7 @@
  * API functions for installing modules and themes.
  */
 
+use Drupal\Component\Utility\RandomBytes;
 use Drupal\Core\Database\Database;
 use Drupal\Core\DrupalKernel;
 use Drupal\locale\Gettext;
@@ -242,7 +243,7 @@ function drupal_install_config_directories() {
   // Add a randomized config directory name to settings.php, unless it was
   // manually defined in the existing already.
   if (empty($config_directories)) {
-    $config_directories_hash = drupal_hash_base64(drupal_random_bytes(55));
+    $config_directories_hash = drupal_hash_base64(RandomBytes::generate(55));
     $settings['config_directories'] = array(
       'value' => array(
         CONFIG_ACTIVE_DIRECTORY => array(
diff --git a/core/includes/session.inc b/core/includes/session.inc
index 31e67a6..8344dc9 100644
--- a/core/includes/session.inc
+++ b/core/includes/session.inc
@@ -16,6 +16,8 @@
  * data should instead be accessed via the $_SESSION superglobal.
  */
 
+use Drupal\Component\Utility\RandomBytes;
+
 /**
  * Session handler assigned by session_set_save_handler().
  *
@@ -357,7 +359,7 @@ function drupal_session_regenerate() {
       $old_insecure_session_id = $_COOKIE[$insecure_session_name];
     }
     $params = session_get_cookie_params();
-    $session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
+    $session_id = drupal_hash_base64(uniqid(mt_rand(), TRUE) . RandomBytes::generate(55));
     // If a session cookie lifetime is set, the session will expire
     // $params['lifetime'] seconds from the current request. If it is not set,
     // it will expire when the browser is closed.
@@ -369,7 +371,7 @@ function drupal_session_regenerate() {
   if (drupal_session_started()) {
     $old_session_id = session_id();
   }
-  session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55)));
+  session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE) . RandomBytes::generate(55)));
 
   if (isset($old_session_id)) {
     $params = session_get_cookie_params();
diff --git a/core/lib/Drupal/Component/Utility/RandomBytes.php b/core/lib/Drupal/Component/Utility/RandomBytes.php
new file mode 100644
index 0000000..85225c1
--- /dev/null
+++ b/core/lib/Drupal/Component/Utility/RandomBytes.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Component\Utility\RandomBytes.
+ */
+
+namespace Drupal\Component\Utility;
+
+/**
+ * Generates randomized bytes.
+ */
+class RandomBytes {
+
+  /**
+   * Returns a string of highly randomized bytes (over the full 8-bit range).
+   *
+   * This function is better than simply calling mt_rand() or any other built-in
+   * PHP function because it can return a long string of bytes (compared to < 4
+   * bytes normally from mt_rand()) and uses the best available pseudo-random
+   * source.
+   *
+   * @param $count
+   *   The number of characters (bytes) to return in the string.
+   */
+  public static function generate($count) {
+    // $random_state does not use drupal_static as it stores random bytes.
+    static $random_state, $bytes, $php_compatible;
+    // Initialize on the first call. The contents of $_SERVER includes a mix of
+    // user-specific and system information that varies a little with each page.
+    if (!isset($random_state)) {
+      $random_state = print_r($_SERVER, TRUE);
+      if (function_exists('getmypid')) {
+        // Further initialize with the somewhat random PHP process ID.
+        $random_state .= getmypid();
+      }
+      $bytes = '';
+    }
+    if (strlen($bytes) < $count) {
+      // PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes()
+      // locking on Windows and rendered it unusable.
+      if (!isset($php_compatible)) {
+        $php_compatible = version_compare(PHP_VERSION, '5.3.4', '>=');
+      }
+      // /dev/urandom is available on many *nix systems and is considered the
+      // best commonly available pseudo-random source.
+      if ($fh = @fopen('/dev/urandom', 'rb')) {
+        // PHP only performs buffered reads, so in reality it will always read
+        // at least 4096 bytes. Thus, it costs nothing extra to read and store
+        // that much so as to speed any additional invocations.
+        $bytes .= fread($fh, max(4096, $count));
+        fclose($fh);
+      }
+      // openssl_random_pseudo_bytes() will find entropy in a system-dependent
+      // way.
+      elseif ($php_compatible && function_exists('openssl_random_pseudo_bytes')) {
+        $bytes .= openssl_random_pseudo_bytes($count - strlen($bytes));
+      }
+      // If /dev/urandom is not available or returns no bytes, this loop will
+      // generate a good set of pseudo-random bytes on any system.
+      // Note that it may be important that our $random_state is passed
+      // through hash() prior to being rolled into $output, that the two hash()
+      // invocations are different, and that the extra input into the first one -
+      // the microtime() - is prepended rather than appended. This is to avoid
+      // directly leaking $random_state via the $output stream, which could
+      // allow for trivial prediction of further "random" numbers.
+      while (strlen($bytes) < $count) {
+        $random_state = hash('sha256', microtime() . mt_rand() . $random_state);
+        $bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
+      }
+    }
+    $output = substr($bytes, 0, $count);
+    $bytes = substr($bytes, $count);
+    return $output;
+  }
+}
diff --git a/core/lib/Drupal/Component/Uuid/Php.php b/core/lib/Drupal/Component/Uuid/Php.php
index fd12fc0..9016a9b 100644
--- a/core/lib/Drupal/Component/Uuid/Php.php
+++ b/core/lib/Drupal/Component/Uuid/Php.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Component\Uuid;
 
+use Drupal\Component\Utility\RandomBytes;
+
 /**
  * Generates a UUID v4 using PHP code.
  *
@@ -20,7 +22,7 @@ class Php implements UuidInterface {
    * Implements Drupal\Component\Uuid\UuidInterface::generate().
    */
   public function generate() {
-    $hex = substr(hash('sha256', drupal_random_bytes(16)), 0, 32);
+    $hex = substr(hash('sha256', RandomBytes::generate(16)), 0, 32);
 
     // The field names refer to RFC 4122 section 4.1.2.
     $time_low = substr($hex, 0, 8);
diff --git a/core/lib/Drupal/Core/Password/PhpassHashedPassword.php b/core/lib/Drupal/Core/Password/PhpassHashedPassword.php
index 157e14c..a06d678 100644
--- a/core/lib/Drupal/Core/Password/PhpassHashedPassword.php
+++ b/core/lib/Drupal/Core/Password/PhpassHashedPassword.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Core\Password;
 
+use Drupal\Component\Utility\RandomBytes;
+
 /**
  * Secure password hashing functions based on the Portable PHP password
  * hashing framework.
@@ -109,7 +111,7 @@ protected function generateSalt() {
     // We encode the final log2 iteration count in base 64.
     $output .= static::$ITOA64[$this->countLog2];
     // 6 bytes is the standard salt for a portable phpass hash.
-    $output .= $this->base64Encode(drupal_random_bytes(6), 6);
+    $output .= $this->base64Encode(RandomBytes::generate(6), 6);
     return $output;
   }
 
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 69102f4..2947034 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -842,6 +842,117 @@ function field_attach_form(EntityInterface $entity, &$form, &$form_state, $langc
 }
 
 /**
+ * Adds form elements for all fields for an entity to a form structure.
+ *
+ * The form elements for the entity's fields are added by reference as direct
+ * children in the $form parameter. This parameter can be a full form structure
+ * (most common case for entity edit forms), or a sub-element of a larger form.
+ *
+ * By default, submitted field values appear at the top-level of
+ * $form_state['values']. A different location within $form_state['values'] can
+ * be specified by setting the '#parents' property on the incoming $form
+ * parameter. Because of name clashes, two instances of the same field cannot
+ * appear within the same $form element, or within the same '#parents' space.
+ *
+ * For each call to field_attach_form(), field values are processed by calling
+ * field_attach_form_validate() and field_attach_extract_form_values() on the
+ * same $form element.
+ *
+ * Sample resulting structure in $form:
+ * @code
+ *   '#parents' => The location of field values in $form_state['values'],
+ *   '#entity_type' => The name of the entity type,
+ *   '#bundle' => The name of the bundle,
+ *   // One sub-array per field appearing in the entity, keyed by field name.
+ *   // The structure of the array differs slightly depending on whether the
+ *   // widget is 'single-value' (provides the input for one field value,
+ *   // most common case), and will therefore be repeated as many times as
+ *   // needed, or 'multiple-values' (one single widget allows the input of
+ *   // several values, e.g checkboxes, select box...).
+ *   // The sub-array is nested into a $langcode key where $langcode has the
+ *   // same value of the $langcode parameter above.
+ *   // The '#language' key holds the same value of $langcode and it is used
+ *   // to access the field sub-array when $langcode is unknown.
+ *   'field_foo' => array(
+ *     '#tree' => TRUE,
+ *     '#field_name' => The name of the field,
+ *     '#language' => $langcode,
+ *     $langcode => array(
+ *       '#field_name' => The name of the field,
+ *       '#language' => $langcode,
+ *       '#field_parents' => The 'parents' space for the field in the form,
+ *          equal to the #parents property of the $form parameter received by
+ *          field_attach_form(),
+ *       '#required' => Whether or not the field is required,
+ *       '#title' => The label of the field instance,
+ *       '#description' => The description text for the field instance,
+ *
+ *       // Only for 'single' widgets:
+ *       '#theme' => 'field_multiple_value_form',
+ *       '#cardinality' => The field cardinality,
+ *       // One sub-array per copy of the widget, keyed by delta.
+ *       0 => array(
+ *         '#entity_type' => The name of the entity type,
+ *         '#bundle' => The name of the bundle,
+ *         '#field_name' => The name of the field,
+ *         '#field_parents' => The 'parents' space for the field in the form,
+ *            equal to the #parents property of the $form parameter received by
+ *            field_attach_form(),
+ *         '#title' => The title to be displayed by the widget,
+ *         '#default_value' => The field value for delta 0,
+ *         '#required' => Whether the widget should be marked required,
+ *         '#delta' => 0,
+ *         '#columns' => The array of field columns,
+ *         // The remaining elements in the sub-array depend on the widget.
+ *         '#type' => The type of the widget,
+ *         ...
+ *       ),
+ *       1 => array(
+ *         ...
+ *       ),
+ *
+ *       // Only for multiple widgets:
+ *       '#entity_type' => The name of the entity type,
+ *       '#bundle' => $instance['bundle'],
+ *       '#columns'  => array_keys($field['columns']),
+ *       // The remaining elements in the sub-array depend on the widget.
+ *       '#type' => The type of the widget,
+ *       ...
+ *     ),
+ *     ...
+ *   ),
+ * )
+ * @endcode
+ *
+ * Additionally, some processing data is placed in $form_state, and can be
+ * accessed by field_form_get_state() and field_form_set_state().
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity for which to load form elements, used to initialize
+ *   default form values.
+ * @param $form
+ *   The form structure to fill in. This can be a full form structure, or a
+ *   sub-element of a larger form. The #parents property can be set to control
+ *   the location of submitted field values within $form_state['values']. If
+ *   not specified, $form['#parents'] is set to an empty array, placing field
+ *   values at the top-level of $form_state['values'].
+ * @param $form_state
+ *   An associative array containing the current state of the form.
+ *
+ */
+function field_attach_bundle_form($entity_type, $bundle, &$form, &$form_state) {
+  $form['#entity_type'] = $entity->entityType();
+  $form['#bundle'] = $entity->bundle();
+
+  // Let other modules make changes to the form.
+  // Avoid module_invoke_all() to let parameters be taken by reference.
+  foreach (module_implements('field_attach_bundle_form') as $module) {
+    $function = $module . '_field_attach_bundle_form';
+    $function($entity_type, $bundle, $form, $form_state);
+  }
+}
+
+/**
  * Loads fields for the current revisions of a group of entities.
  *
  * Loads all fields for each entity object in a group of a single entity type.
diff --git a/core/modules/node/content_types.inc b/core/modules/node/content_types.inc
index e838460..1b7f213 100644
--- a/core/modules/node/content_types.inc
+++ b/core/modules/node/content_types.inc
@@ -281,6 +281,12 @@ function node_type_form($form, &$form_state, $type = NULL) {
   }
   $form['#submit'][] = 'node_type_form_submit';
 
+
+  $form['#entity_type'] = 'node';
+  $form['#bundle'] = $type->name;
+  $form_state['build_info']['base_form_id'] = 'entity_bundle_form';
+  // Allow entity-agnostic modules to alter entity bundle forms.
+
   return $form;
 }
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
index 454e3a2..1bbffd5 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UpgradePathTestBase.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Upgrade;
 
+use Drupal\Component\Utility\RandomBytes;
 use Drupal\Core\Database\Database;
 use Drupal\simpletest\WebTestBase;
 use Exception;
@@ -45,7 +46,7 @@
   protected function prepareD8Session() {
     // Generate and set a D7-compatible session cookie.
     $this->curlInitialize();
-    $sid = drupal_hash_base64(uniqid(mt_rand(), TRUE) . drupal_random_bytes(55));
+    $sid = drupal_hash_base64(uniqid(mt_rand(), TRUE) . RandomBytes::generate(55));
     curl_setopt($this->curlHandle, CURLOPT_COOKIE, rawurlencode(session_name()) . '=' . rawurlencode($sid));
 
     // Force our way into the session of the child site.
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 7f621d4..020679f 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Component\Utility\RandomBytes;
 use Drupal\Core\Database\Database;
 
 /**
@@ -527,7 +528,7 @@ function system_install() {
   config_install_default_config('theme', 'stark');
 
   // Populate the cron key state variable.
-  $cron_key = drupal_hash_base64(drupal_random_bytes(55));
+  $cron_key = drupal_hash_base64(RandomBytes::generate(55));
   state()->set('system.cron_key', $cron_key);
 }
 
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index 6559313..a1b3c15 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -5,6 +5,7 @@
  * User page callback file for the user module.
  */
 
+use Drupal\Component\Utility\RandomBytes;
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -126,7 +127,7 @@ function user_pass_reset($form, &$form_state, $uid, $timestamp, $hashed_pass, $a
           watchdog('user', 'User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp));
           drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
           // Let the user's password be changed without the current password check.
-          $token = drupal_hash_base64(drupal_random_bytes(55));
+          $token = drupal_hash_base64(RandomBytes::generate(55));
           $_SESSION['pass_reset_' . $user->uid] = $token;
           drupal_goto('user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token)));
         }
