diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php
index ffddd61..4829420 100644
--- a/core/lib/Drupal/Core/Config/Config.php
+++ b/core/lib/Drupal/Core/Config/Config.php
@@ -92,11 +92,6 @@ class Config {
    *   would return array('bar' => 'baz').
    *   If no key is specified, then the entire data array is returned.
    *
-   * The configuration system does not retain data types. Every saved value is
-   * casted to a string. In most cases this is not an issue; however, it can
-   * cause issues with Booleans, which are casted to "1" (TRUE) or "0" (FALSE).
-   * In particular, code relying on === or !== will no longer function properly.
-   *
    * @see http://php.net/manual/language.operators.comparison.php.
    *
    * @return
@@ -149,9 +144,6 @@ class Config {
    *   @todo
    */
   public function set($key, $value) {
-    // Type-cast value into a string.
-    $value = $this->castValue($value);
-
     // The dot/period is a reserved character; it may appear between keys, but
     // not within keys.
     $parts = explode('.', $key);
@@ -165,45 +157,6 @@ class Config {
   }
 
   /**
-   * Casts a saved value to a string.
-   *
-   * The configuration system only saves strings or arrays. Any scalar
-   * non-string value is cast to a string. The one exception is boolean FALSE
-   * which would normally become '' when cast to a string, but is manually
-   * cast to '0' here for convenience and consistency.
-   *
-   * Any non-scalar value that is not an array (aka objects) gets cast
-   * to an array.
-   *
-   * @param $value
-   *   A value being saved into the configuration system.
-   * @param $value
-   *   The value cast to a string or array.
-   */
-  public function castValue($value) {
-    if (is_scalar($value)) {
-      // Handle special case of FALSE, which should be '0' instead of ''.
-      if ($value === FALSE) {
-        $value = '0';
-      }
-      else {
-        $value = (string) $value;
-      }
-    }
-    else {
-      // Any non-scalar value must be an array.
-      if (!is_array($value)) {
-        $value = (array) $value;
-      }
-      // Recurse into any nested keys.
-      foreach ($value as $key => $nested_value) {
-        $value[$key] = $this->castValue($nested_value);
-      }
-    }
-    return $value;
-  }
-
-  /**
    * Unsets value in this config object.
    *
    * @param $key
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index f30011c..a6c4322 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -13,7 +13,7 @@ use Exception;
 /**
  * Defines the Database storage controller.
  */
-class DatabaseStorage implements StorageInterface {
+class DatabaseStorage extends StorageBase {
 
   /**
    * Database connection options for this storage controller.
@@ -77,6 +77,7 @@ class DatabaseStorage implements StorageInterface {
    * @todo Ignore slave targets for data manipulation operations.
    */
   public function write($name, array $data) {
+    $this->validateData($name, $data);
     $data = $this->encode($data);
     $options = array('return' => Database::RETURN_AFFECTED) + $this->options;
     return (bool) $this->getConnection()->merge('config', $options)
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index 033555d..0fc800e 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -12,7 +12,7 @@ use Symfony\Component\Yaml\Yaml;
 /**
  * Defines the file storage controller.
  */
-class FileStorage implements StorageInterface {
+class FileStorage extends StorageBase {
 
   /**
    * Configuration options for this storage controller.
@@ -86,6 +86,7 @@ class FileStorage implements StorageInterface {
    * @throws Drupal\Core\Config\StorageException
    */
   public function write($name, array $data) {
+    $this->validateData($name, $data);
     $data = $this->encode($data);
     $status = @file_put_contents($this->getFilePath($name), $data);
     if ($status === FALSE) {
diff --git a/core/lib/Drupal/Core/Config/NullStorage.php b/core/lib/Drupal/Core/Config/NullStorage.php
index fede4f0..5e58239 100644
--- a/core/lib/Drupal/Core/Config/NullStorage.php
+++ b/core/lib/Drupal/Core/Config/NullStorage.php
@@ -21,7 +21,7 @@ namespace Drupal\Core\Config;
  *
  * This also can be used for testing purposes.
  */
-class NullStorage implements StorageInterface {
+class NullStorage extends StorageBase {
   /**
    * Implements Drupal\Core\Config\StorageInterface::__construct().
    */
diff --git a/core/lib/Drupal/Core/Config/StorageBase.php b/core/lib/Drupal/Core/Config/StorageBase.php
new file mode 100644
index 0000000..65cb056
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/StorageBase.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Config\StorageBase.
+ */
+
+namespace Drupal\Core\Config;
+
+/**
+ * Defines an abstract class for configuration storage controllers.
+ *
+ * Classes extending this allow reading, writing and validating configuration
+ * data from and to the storage.
+ */
+abstract class StorageBase implements StorageInterface {
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::validateData().
+   */
+  public function validateData($name, array $data) {
+    array_walk_recursive($data, array('self', 'validateValue'), $name);
+  }
+
+  /**
+   * Implements Drupal\Core\Config\StorageInterface::validateValue().
+   */
+  public function validateValue($value, $key, $name) {
+    if (!is_scalar($value)) {
+      throw new StorageException(sprintf('Unsupported non-scalar value of type %s in key %s in config object %s', gettype($value), $key, $name));
+    }
+  }
+}
+
+?>
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index 806ee87..051092b 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -89,6 +89,36 @@ interface StorageInterface {
   public static function decode($raw);
 
   /**
+   * Validates configuration data.
+   *
+   * @param string $name
+   *   The name of a configuration object to validate.
+   * @param array $data
+   *   The configuration data to validate.
+   *
+   * @throws StorageException
+   */
+  public function validateData($name, array $data);
+
+  /**
+   * Validates a configuration value.
+   *
+   * Helper callback for array_walk_recursive().
+   *
+   * @param mixed $value
+   *   The configuration data value to validate.
+   * @param string $key
+   *   The key of the value.
+   * @param string $name
+   *   The name of the configuration object.
+   *
+   * @throws StorageException
+   *
+   * @see StorageBase::validateData()
+   */
+  public function validateValue($value, $key, $name);
+
+  /**
    * Gets configuration object names starting with a given prefix.
    *
    * Given the following configuration objects:
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
index 37aa854..694b4f0 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigCRUDTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\config\Tests;
 
 use Drupal\Core\Config\DatabaseStorage;
+use Drupal\Core\Config\StorageException;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -22,6 +23,10 @@ class ConfigCRUDTest extends WebTestBase {
     );
   }
 
+  function setUp() {
+    parent::setUp(array('config_test'));
+  }
+
   /**
    * Tests CRUD operations.
    */
@@ -112,4 +117,72 @@ class ConfigCRUDTest extends WebTestBase {
     // their order must be identical.
     $this->assertIdentical($new_config->get(), $config->get());
   }
+
+  /**
+   * Tests data type preservation.
+   */
+  function testDataTypePreservation() {
+    $config = config('config_test.types');
+
+    // Test typed varaibles.
+    $data = array(
+      'array' => array(),
+      'boolean' => TRUE,
+      'exp' => 1.2e+34,
+      'float' => 3.14159,
+      'hex' => 0xC,
+      'int' => 99,
+      'octal' => 0775,
+      'string' => 'string',
+    );
+
+    // Test data provided by config_test.types.yml.
+    $this->assertIdentical($config->get(), $data);
+
+    // Set each key using config::set().
+    foreach($data as $key => $value) {
+      $config->set($key, $value);
+    }
+    $config->save();
+    $this->assertIdentical($config->get(), $data);
+
+    // Set data using config::setData().
+    $config->setData($data)->save();
+    $this->assertIdentical($config->get(), $data);
+  }
+
+  /**
+   * Tests data type validation.
+   */
+  function testDataTypeValidation() {
+    $config = config('config_test.invalid_data');
+
+    // Config can't save resources.
+    $data = array(
+      'valid_data_type' => 1,
+      'invalid_type' => fopen(__FILE__, 'r'),
+    );
+    // Test using config::set()
+    foreach ($data as $key => $value) {
+      $config->set($key, $value);
+    }
+    try {
+      $config->save();
+    }
+    catch (StorageException $e) {
+      $message = $e->getMessage();
+    }
+    $this->assertEqual($message, 'Unsupported non-scalar value of type resource in key invalid_type in config object config_test.invalid_data');
+
+    // Config can't save objects.
+    $data['invalid_type'] = new \stdClass();
+    // Test using config::setData().
+    try {
+      $config->setData($data)->save();
+    }
+    catch (StorageException $e) {
+      $message = $e->getMessage();
+    }
+    $this->assertEqual($message, 'Unsupported non-scalar value of type object in key invalid_type in config object config_test.invalid_data');
+  }
 }
diff --git a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
index 2dbc627..db7480d 100644
--- a/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
+++ b/core/modules/config/lib/Drupal/config/Tests/Storage/ConfigStorageTestBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\config\Tests\Storage;
 
 use Drupal\simpletest\WebTestBase;
+use Drupal\Core\Config\StorageException;
 
 /**
  * Base class for testing storage controller operations.
@@ -111,6 +112,46 @@ abstract class ConfigStorageTestBase extends WebTestBase {
     }
   }
 
+  /**
+   * Tests storage controller writing and reading data preserving data type.
+   */
+  function testDataTypes() {
+    $name = 'config_test.types';
+    $data = array(
+      'array' => array(),
+      'boolean' => TRUE,
+      'exp' => 1.2e+34,
+      'float' => 3.14159,
+      'hex' => 0xC,
+      'int' => 99,
+      'octal' => 0775,
+      'string' => 'string',
+    );
+
+    $result = $this->storage->write($name, $data);
+    $this->assertIdentical($result, TRUE);
+
+    $read_data = $this->storage->read($name);
+    $this->assertIdentical($read_data, $data);
+  }
+
+  /**
+   * Tests storage controller writing an invalid data type.
+   */
+  function testInvalidData() {
+    $name = 'config_test.invalid_data';
+    $data = array(
+      'invalid_key' => new \stdClass(),
+    );
+    try {
+      $data = $this->storage->write($name, $data);
+    }
+    catch (StorageException $e) {
+      $message = $e->getMessage();
+    }
+    $this->assertEqual($message, sprintf('Unsupported non-scalar value of type object in key invalid_key in config object %s', $name));
+  }
+
   abstract protected function read($name);
 
   abstract protected function insert($name, $data);
diff --git a/core/modules/config/tests/config_test/config/config_test.types.yml b/core/modules/config/tests/config_test/config/config_test.types.yml
new file mode 100644
index 0000000..d4005b1
--- /dev/null
+++ b/core/modules/config/tests/config_test/config/config_test.types.yml
@@ -0,0 +1,8 @@
+array: []
+boolean: true
+exp: 1.2e+34
+float: 3.14159
+hex: 0xC
+int: 99
+octal: 0775
+string: string
