diff -Naur yubikey.orig/yubikey.inc yubikey/yubikey.inc
--- yubikey.orig/yubikey.inc	2009-02-04 00:23:35.000000000 -0600
+++ yubikey/yubikey.inc	2011-02-08 17:22:53.981264359 -0600
@@ -2,16 +2,55 @@
 
 // $Id: yubikey.inc,v 1.1.2.1 2009/02/04 06:23:35 rubinj Exp $
 
-/*
+/**
  * @file
  * YubiKey utility functions.
  */
 
+/**
+ * Parse the OTP for it's parts
+ */
+function yubikey_parseOTP($str, $delim = '[:]') {
+  if (!preg_match("/^((.*)" . $delim . ")?" .
+      "(([cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{0,16})" .
+      "([cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{32}))$/",
+      $str, $matches)) {
+    return FALSE;
+  }
+  $ret['password'] = $matches[2];
+  $ret['otp'] = $matches[3];
+  $ret['prefix'] = $matches[4];
+  $ret['ciphertext'] = $matches[5];
+  return $ret;
+}
+
+/**
+ * Get the yubikey prefix
+ * DEPRECIATED Kept for Backwards compatibility
+ */
 function yubikey_keyid($otp) {
-  return drupal_substr($otp, 0, drupal_strlen($otp) - 32);
+  $ret = yubikey_parseOTP($otp);
+  return $ret['prefix'];
 }
 
+
+/**
+ * Wrapper to call the actual validate for the proper API
+ * If the URL includes 2.0 call the 2.0 validator
+ */
 function yubikey_validate($otp, &$errstr) {
+  if (strpos(variable_get('yubikey_apiurl', 'https://api.yubico.com/wsapi/verify'), '2.0') !== FALSE) {
+    return yubikey_validate_2_0($otp, $errstr);
+  }
+  else {
+    return yubikey_validate_1_1($otp, $errstr);
+  }
+}
+
+/**
+ * Validate the yubikey using 1.0/1.1 api
+ */
+function yubikey_validate_1_1($otp, &$errstr) {
 
   if (!variable_get('yubikey_enabled', FALSE)) {
     $errstr = "YubiKey Authentication Not Enabled";
@@ -22,7 +61,7 @@
   $id      = variable_get('yubikey_apiid', NULL);
   $timeout = variable_get('yubikey_timeout', 10);
 
-  $api_url = "https://api.yubico.com/wsapi/verify";
+  $api_url = variable_get('yubikey_apiurl', 'https://api.yubico.com/wsapi/verify');
   $sig_key = base64_decode($api_key);
 
   $hash = urlencode(base64_encode(hash_hmac("sha1", "id=$id&otp=$otp", $sig_key, TRUE)));
@@ -77,6 +116,88 @@
   return TRUE;
 }
 
+/**
+ * Validate the OTP using 2.0 api
+ */
+function yubikey_validate_2_0($otp, &$errstr) {
+
+  if (!variable_get('yubikey_enabled', FALSE)) {
+    $errstr = "YubiKey Authentication Not Enabled";
+    return FALSE;
+  }
+
+  $api_key = variable_get('yubikey_apikey', NULL);
+  $id      = variable_get('yubikey_apiid', NULL);
+  $timeout = variable_get('yubikey_timeout', 10);
+
+  $api_url = variable_get('yubikey_apiurl', 'https://api.yubico.com/wsapi/verify');
+  $sig_key = base64_decode($api_key);
+  $nonce   = md5(uniqid(rand()));
+
+  $hash = urlencode(base64_encode(hash_hmac("sha1", "id=$id&nonce=$nonce&otp=$otp", $sig_key, TRUE)));
+
+  $url  = "$api_url?id=$id&nonce=$nonce&otp=$otp&h=$hash";
+
+  $ch = curl_init($url);
+  curl_setopt($ch, CURLOPT_TIMEOUT,        $timeout);
+  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
+  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
+  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
+
+  $result = explode("\n", curl_exec($ch));
+  $error = curl_errno($ch);
+  curl_close($ch);
+  if ($error) {
+    $errstr = "ERROR CONNECTING TO YUBICO - ". $error;
+    return FALSE;
+  }
+
+  foreach ($result as $param) {
+    if (drupal_substr($param, 0, 2) == "h=") {
+      $signature = drupal_substr(trim($param), 2);
+    }
+    elseif (drupal_substr($param, 0, 6) == "nonce=") {
+      $nonce = drupal_substr(trim($param), 6);
+    }
+    elseif (drupal_substr($param, 0, 4) == "otp=") {
+      $otp = drupal_substr(trim($param), 4);
+    }
+    elseif (drupal_substr($param, 0, 3) == "sl=") {
+      $sl = drupal_substr(trim($param), 3);
+    }
+    elseif (drupal_substr($param, 0, 2) == "t=") {
+      $timestamp = drupal_substr(trim($param), 2);
+    }
+    elseif (drupal_substr($param, 0, 7) == "status=") {
+      $status = drupal_substr(trim($param), 7);
+    }
+  }
+
+  $signed = "nonce=$nonce&otp=$otp&sl=$sl&status=$status&t=$timestamp";
+  
+  if (!(base64_encode(hash_hmac("sha1", $signed, $sig_key, TRUE)) == $signature)) {
+    $errstr = 'BAD RESPONSE SIGNATURE';
+    return FALSE;
+  }
+
+  if (!yubico_validate_timestamp($timestamp)) {
+    $errstr = 'BAD TIMESTAMP';
+    return FALSE;
+  }
+  
+  if ($status != "OK") {
+    $errstr = $status;
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * Validte the timestamp in the reply
+ */
 function yubico_validate_timestamp($timestamp) {
   $tolerance = variable_get('yubikey_tolerance', 150);
   $now = date("U");
diff -Naur yubikey.orig/yubikey.pages.inc yubikey/yubikey.pages.inc
--- yubikey.orig/yubikey.pages.inc	2009-02-04 00:23:35.000000000 -0600
+++ yubikey/yubikey.pages.inc	2011-02-08 17:04:22.866389552 -0600
@@ -140,6 +140,14 @@
     '#title'         => t('Enable Yubikey Authentication'),
     '#default_value' => variable_get('yubikey_enabled', FALSE)
   );
+  $form['yubikey']['apiurl'] = array(
+    '#type'          => 'textfield',
+    '#title'         => t('API URL'),
+    '#default_value' => variable_get('yubikey_apiurl', 'https://api.yubico.com/wsapi/verify'),
+    '#size'          => 32,
+    '#required'      => TRUE,
+    '#prefix'        => '<div id="api_fields_div">'
+  );
   $form['yubikey']['apikey'] = array(
     '#type'          => 'textfield',
     '#title'         => t('API Key'),
@@ -147,7 +155,6 @@
     '#size'          => 32,
     '#maxlength'     => 128,
     '#required'      => TRUE,
-    '#prefix'        => '<div id="api_fields_div">'
   );
   $form['yubikey']['apiid'] = array(
     '#type'          => 'textfield',
@@ -181,6 +188,7 @@
 function yubikey_admin_page_submit($form_id, &$form_state) {
   if ($form_state['values']['op'] == t('Reset to defaults')) {
     variable_del('yubikey_enabled');
+    variable_del('yubikey_apiurl');
     variable_del('yubikey_apikey');
     variable_del('yubikey_apiid');
     variable_del('yubikey_tolerance');
@@ -188,11 +196,13 @@
   }
   else {
     $enabled   = $form_state['values']['yubikey']['enable'];
+    $apiurl    = $form_state['values']['yubikey']['apiurl'];
     $apikey    = $form_state['values']['yubikey']['apikey'];
     $apiid     = $form_state['values']['yubikey']['apiid'];
     $tolerance = $form_state['values']['yubikey']['tolerance'];
     $timeout   = $form_state['values']['yubikey']['timeout'];
     variable_set('yubikey_enabled',   $enabled);
+    variable_set('yubikey_apiurl',    $apiurl);
     variable_set('yubikey_apikey',    $apikey);
     variable_set('yubikey_apiid',     $apiid);
     variable_set('yubikey_tolerance', $tolerance);
