diff --git a/mollom.admin.inc b/mollom.admin.inc
index 6d8b880..d6ff6be 100644
--- a/mollom.admin.inc
+++ b/mollom.admin.inc
@@ -718,12 +718,14 @@ function mollom_admin_settings(&$form_state) {
     '#type' => 'textfield',
     '#title' => t('Public key'),
     '#default_value' => variable_get('mollom_public_key', ''),
+    '#element_validate' => array('mollom_admin_settings_validate_key'),
     '#description' => t('Used to uniquely identify you.'),
   );
   $form['access-keys']['mollom_private_key'] = array(
     '#type' => 'textfield',
     '#title' => t('Private key'),
     '#default_value' => variable_get('mollom_private_key', ''),
+    '#element_validate' => array('mollom_admin_settings_validate_key'),
     '#description' => t('Used to prevent someone else from hijacking your requests. Similar to a password, it should never be shared with anyone.'),
   );
 
@@ -765,6 +767,23 @@ function mollom_admin_settings(&$form_state) {
 }
 
 /**
+ * Element validation handler for API key text fields.
+ */
+function mollom_admin_settings_validate_key($element, &$form_state) {
+  if ($element['#value'] !== '') {
+    // Remove any leading/trailing white-space and override submitted value.
+    $element['#value'] = trim($element['#value']);
+    form_set_value($element, $element['#value'], $form_state);
+    // Verify the key has a length of 32 characters.
+    if (drupal_strlen($element['#value']) != 32) {
+      form_error($element, t('!title must be 32 characters. Ensure you copied the key correctly.', array(
+        '!title' => $element['#title'],
+      )));
+    }
+  }
+}
+
+/**
  * Form submit handler to mass-report and unpublish or delete comments.
  */
 function mollom_comment_admin_overview_submit($form, &$form_state) {
diff --git a/tests/mollom.test b/tests/mollom.test
index ba852d1..319f76d 100644
--- a/tests/mollom.test
+++ b/tests/mollom.test
@@ -793,8 +793,8 @@ class MollomInstallationTestCase extends MollomWebTestCase {
 
     // Configure invalid keys.
     $edit = array(
-      'mollom_public_key' => 'foo',
-      'mollom_private_key' => 'bar',
+      'mollom_public_key' => 'the-invalid-mollom-api-key-value',
+      'mollom_private_key' => 'the-invalid-mollom-api-key-value',
     );
     $this->drupalGet('admin/settings/mollom/settings');
     $this->drupalPost(NULL, $edit, t('Save configuration'), array('watchdog' => WATCHDOG_EMERG));
@@ -1083,10 +1083,25 @@ class MollomAccessTestCase extends MollomWebTestCase {
     $this->drupalLogin($this->admin_user);
     $this->drupalGet('admin/settings/mollom/settings');
 
+    // Try to setup completely invalid keys.
+    $edit = array(
+      'mollom_public_key' => 'foo',
+      'mollom_private_key' => 'bar',
+    );
+    $this->drupalPost(NULL, $edit, t('Save configuration'));
+    $this->assertText(t('!title must be 32 characters. Ensure you copied the key correctly.', array(
+      '!title' => t('Public key'),
+    )));
+    $this->assertText(t('!title must be 32 characters. Ensure you copied the key correctly.', array(
+      '!title' => t('Private key'),
+    )));
+    $this->assertNoText(t('The configuration options have been saved.'));
+    $this->assertNoText('The configured Mollom API keys are invalid.');
+
     // Set up invalid test keys and check that an error message is shown.
     $edit = array(
-      'mollom_public_key' => 'invalid-public-key',
-      'mollom_private_key' => 'invalid-private-key',
+      'mollom_public_key' => 'the-invalid-mollom-api-key-value',
+      'mollom_private_key' => 'the-invalid-mollom-api-key-value',
     );
     $this->drupalPost(NULL, $edit, t('Save configuration'), array('watchdog' => WATCHDOG_EMERG));
     $this->assertText(t('The configuration options have been saved.'));
