Vidalia 0.3.1
crypto.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9**
10** * * *
11**
12** Pseudorandom number generation support in this file is derived from
13** Tor's crypto.[ch]. Tor is distributed under this license.
14**
15** Copyright (c) 2001-2004, Roger Dingledine
16** Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson
17**
18** Redistribution and use in source and binary forms, with or without
19** modification, are permitted provided that the following conditions are
20** met:
21**
22** * Redistributions of source code must retain the above copyright
23** notice, this list of conditions and the following disclaimer.
24**
25** * Redistributions in binary form must reproduce the above
26** copyright notice, this list of conditions and the following disclaimer
27** in the documentation and/or other materials provided with the
28** distribution.
29**
30** * Neither the names of the copyright owners nor the names of its
31** contributors may be used to endorse or promote products derived from
32** this software without specific prior written permission.
33**
34** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*/
46
47/*
48** \file crypto.cpp
49** \brief Provides support for pseuodrandom number generation.
50*/
51
52#include "crypto.h"
53
54#include <QFile>
55#include <QStringList>
56#include <QCryptographicHash>
57#include <QtDebug>
58
59#if defined(Q_OS_WIN32)
60#include <windows.h>
61#include <wincrypt.h>
62#endif
63
64
65/** Returns up to <b>len</b> bytes of pseudorandom data on success, or an empty
66 * QByteArray on failure. The caller should verify that the returned
67 * QByteArray contains the requested number of bytes. This function is based on
68 * crypto_seed_rng() from Tor's crypto.c. See LICENSE for details on Tor's
69 * license. */
70QByteArray
72{
73 QByteArray buf(len, 0);
74#if defined(Q_OS_WIN32)
75 static int provider_set = 0;
76 static HCRYPTPROV provider;
77#else
78 static QStringList filenames =
79 QStringList() << "/dev/srandom" << "/dev/urandom" << "/dev/random";
80#endif
81 Q_ASSERT(len > 0);
82
83#if defined(Q_OS_WIN32)
84 if (!provider_set) {
85 if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
86 CRYPT_VERIFYCONTEXT)) {
87 if ((unsigned long)GetLastError() != (unsigned long)NTE_BAD_KEYSET) {
88 qWarning("Can't get CryptoAPI provider.");
89 return QByteArray();
90 }
91 }
92 provider_set = 1;
93 }
94 if (!CryptGenRandom(provider, buf.size(), (BYTE *)buf.data())) {
95 qWarning("Can't get entropy from CryptoAPI.");
96 return QByteArray();
97 }
98 return buf;
99#else
100 foreach (QString fname, filenames) {
101 QFile file(fname);
102 if (!file.open(QIODevice::ReadOnly))
103 continue;
104
105 qint64 bytes_read;
106 qint64 total = 0;
107 while (total < buf.size()) {
108 bytes_read = file.read(buf.data()+total, buf.size()-total);
109 if (bytes_read < 0)
110 return QByteArray();
111 else if (bytes_read == 0) {
112 buf.resize(total);
113 return buf;
114 }
115 total += bytes_read;
116 }
117 return buf;
118 }
119 qWarning("Can't read from /dev/*random.");
120 return QByteArray();
121#endif
122}
123
124/** Returns a pseudorandom integer, chosen uniformly from the the values in
125 * the range [0, max). This function is based on crypto_rand_int() from Tor's
126 * crypto.c. See LICENSE for details on Tor's license. */
129{
130 QByteArray buf;
131 quint32 val;
132 quint32 cutoff;
133 Q_ASSERT(max > 0);
134
135 cutoff = 0xffffffffu - (0xffffffffu % max);
136 forever {
137 buf = crypto_rand_bytes(sizeof(quint32));
138 Q_ASSERT(buf.size() == sizeof(quint32));
139
140 val = *((quint32 *)buf.constData());
141 if (val < cutoff)
142 break;
143 }
144 return (val % max);
145}
146
147/** Generates a pseudorandom string of length <b>len</b> containing printable
148 * ASCII characters from the range '!' (0x21) to '~' (0x7e). */
149QString
151{
152 QString str;
153 Q_ASSERT(len >= 0);
154
155 for (int i = 0; i < len; i++)
156 str += QChar('!' + crypto_rand_quint32('~'-'!'+1));
157 return str;
158}
159
160/** Generates a salted hash of <b>secret</b> using the random <b>salt</b>
161 * according to the iterated and salted S2K algorithm in RFC 2440. <b>c</b>
162 * is the one-octet coded count value that specifies how much data to hash.
163 * <b>salt</b> must contain at least 8 bytes, otherwise this method will
164 * return a default-constructed QByteArray. */
165QByteArray
166crypto_secret_to_key(const QString &secret, const QByteArray &salt, quint8 c)
167{
168 if (salt.size() < 8)
169 return QByteArray();
170
171#define EXPBIAS 6
172 int count = ((quint32)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
173#undef EXPBIAS
174
175 QCryptographicHash hash(QCryptographicHash::Sha1);
176 QByteArray tmp = salt.left(8).append(secret.toAscii());
177 while (count) {
178 if (count > tmp.length()) {
179 hash.addData(tmp);
180 count -= tmp.length();
181 } else {
182 hash.addData(tmp.left(count));
183 count = 0;
184 }
185 }
186
187 return hash.result();
188}
189
#define EXPBIAS
quint32 crypto_rand_quint32(quint32 max)
Definition: crypto.cpp:128
QByteArray crypto_secret_to_key(const QString &secret, const QByteArray &salt, quint8 c)
Definition: crypto.cpp:166
QString crypto_rand_string(int len)
Definition: crypto.cpp:150
QByteArray crypto_rand_bytes(int len)
Definition: crypto.cpp:71
QString i(QString str)
Definition: html.cpp:32