[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r3818: It's actually easier to just compute the salted hash of the (in vidalia/trunk: . src/common src/vidalia/config)



Author: edmanm
Date: 2009-06-06 13:46:49 -0400 (Sat, 06 Jun 2009)
New Revision: 3818

Modified:
   vidalia/trunk/CHANGELOG
   vidalia/trunk/src/common/crypto.cpp
   vidalia/trunk/src/common/crypto.h
   vidalia/trunk/src/vidalia/config/TorSettings.cpp
Log:

It's actually easier to just compute the salted hash of the control
password ourself, rather than launching Tor just to hash it. Saves us from
having to play all those games to set environment variables properly,
specify the DataDirectory for Tors that write their state file even if all
they're doing is hashing a password, slurping stdout, and then sifting
through the output for the magic token.


Modified: vidalia/trunk/CHANGELOG
===================================================================
--- vidalia/trunk/CHANGELOG	2009-06-05 23:44:51 UTC (rev 3817)
+++ vidalia/trunk/CHANGELOG	2009-06-06 17:46:49 UTC (rev 3818)
@@ -9,6 +9,9 @@
     now defaults to using port 443 in such cases.
   o Add support for viewing the map as a full screen widget when built
     with KDE Marble support.
+  o Compute the salted hash of the control password ourself when starting
+    Tor, rather than launching Tor once to hash the password, parsing the
+    output, and then again to actually start Tor.
   o Add a signal handler that allows Vidalia to clean up and exit normally
     when it catches a SIGINT or SIGTERM signal. (Ticket #481)
   o Renamed the 'make win32-installer' CMake target to 'make dist-win32'

Modified: vidalia/trunk/src/common/crypto.cpp
===================================================================
--- vidalia/trunk/src/common/crypto.cpp	2009-06-05 23:44:51 UTC (rev 3817)
+++ vidalia/trunk/src/common/crypto.cpp	2009-06-06 17:46:49 UTC (rev 3818)
@@ -54,6 +54,7 @@
 
 #include <QFile>
 #include <QStringList>
+#include <QCryptographicHash>
 #include <QtDebug>
 
 #if defined(Q_OS_WIN32)
@@ -157,3 +158,33 @@
   return str;
 }
 
+/** Generates a salted hash of <b>secret</b> using the random <b>salt</b>
+ * according to the iterated and salted S2K algorithm in RFC 2440. <b>c</b>
+ * is the one-octet coded count value that specifies how much data to hash. 
+ * <b>salt</b> must contain at least 8 bytes, otherwise this method will
+ * return a default-constructed QByteArray. */
+QByteArray
+crypto_secret_to_key(const QString &secret, const QByteArray &salt, quint8 c)
+{
+  if (salt.size() < 8)
+    return QByteArray();
+
+#define EXPBIAS 6
+  int count = ((quint32)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
+#undef EXPBIAS
+
+  QCryptographicHash hash(QCryptographicHash::Sha1);
+  QByteArray tmp = salt.left(8).append(secret.toAscii());
+  while (count) {
+    if (count > tmp.length()) {
+      hash.addData(tmp);
+      count -= tmp.length();
+    } else {
+      hash.addData(tmp.left(count));
+      count = 0;
+    }
+  }
+
+  return hash.result();
+}
+

Modified: vidalia/trunk/src/common/crypto.h
===================================================================
--- vidalia/trunk/src/common/crypto.h	2009-06-05 23:44:51 UTC (rev 3817)
+++ vidalia/trunk/src/common/crypto.h	2009-06-06 17:46:49 UTC (rev 3818)
@@ -67,6 +67,13 @@
 /** Generates a pseudorandom string of length <b>len</b> containing printable
  * ASCII characters from the range '!' (0x21) to '~' (0x7e). */
 QString crypto_rand_string(int len);
+/** Generates a salted hash of <b>secret</b> using the random <b>salt</b>
+ * according to the iterated and salted S2K algorithm in RFC 2440. <b>c</b>
+ * is the one-octet coded count value that specifies how much data to hash. 
+ * <b>salt</b> must contain at least 8 bytes, otherwise this method will
+ * return a default-constructed QByteArray. */
+QByteArray 
+crypto_secret_to_key(const QString &secret, const QByteArray &salt, quint8 c);
 
 #endif
 

Modified: vidalia/trunk/src/vidalia/config/TorSettings.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/TorSettings.cpp	2009-06-05 23:44:51 UTC (rev 3817)
+++ vidalia/trunk/src/vidalia/config/TorSettings.cpp	2009-06-06 17:46:49 UTC (rev 3818)
@@ -18,6 +18,7 @@
 #include "Vidalia.h"
 #include "crypto.h"
 #include "file.h"
+#include "stringutil.h"
 #if defined(Q_OS_WIN32)
 #include "win32.h"
 #include <QFileInfo>
@@ -357,42 +358,27 @@
 QString
 TorSettings::hashPassword(const QString &password)
 {
-  TorSettings settings;
-  QProcess tor;
-  QString dataDirectory, line;
-  QStringList args;
-
-  QStringList env = QProcess::systemEnvironment();
-#if !defined(Q_OS_WIN32)
-  /* Add "/usr/sbin" to an existing $PATH, so this works on Debian too. */
-  for (int i = 0; i < env.size(); i++) {
-    QString envVar = env.at(i);
-    if (envVar.startsWith("PATH="))
-      env.replace(i, envVar += ":/usr/sbin");
+  QByteArray salt;
+  
+  /* Generate an 8 octet salt value. Bail if we fail to generate enough
+   * random bytes (unlikely). */
+  while (salt.size() < 8) {
+    QByteArray bytes = crypto_rand_bytes(8-salt.size());
+    if (bytes.isNull())
+      return QString();
+    salt.append(bytes);
   }
-#endif
-  tor.setEnvironment(env);
 
-  /* Tor writes its state file even if all we're doing is --hash-password. So
-   * if the user has configured a non-default data directory, then include
-   * that in the list of command line arguments. */
-  dataDirectory = settings.getDataDirectory();
-  if (!dataDirectory.isEmpty())
-    args << "DataDirectory" << dataDirectory;
-  args << "--hash-password" << password;
-  
-  /* Run Tor, tell it to hash the given password, and then wait for it to
-   * finish. */
-  tor.start(expand_filename(settings.getExecutable()), args);
-  if (!tor.waitForStarted() || !tor.waitForFinished())
+  /* Generate the salted hash of the specified password. 96 is the one-octet
+   * RFC 2440 coded count value hardcoded into Tor. Specifies that we should
+   * hash 64K worth of data. */
+  QByteArray key = crypto_secret_to_key(password, salt, 96);
+  if (key.isNull())
     return QString();
+  salt.append(96); /* Append the coded count value to the salt */
 
-  /* The hashed password will (hopefully) be the line that starts with "16:" */
-  while (tor.canReadLine()) {
-    line = tor.readLine();
-    if (line.startsWith("16:"))
-      return line.trimmed();
-  }
-  return QString();
+  /* Convert the result to hexadecimal and put it in the format Tor wants. */
+  return QString("16:%1%2").arg(base16_encode(salt))
+                           .arg(base16_encode(key));
 }