Flint
Check-in [ebb06e3403]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Switch to bcrypt for password hashing and provide password migration
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ebb06e34034ffc673988ce7c0fb411ba05102827
User & Date: james 2012-07-08 03:45:06
Context
2012-07-08
04:03
Add missing where clause to hash update check-in: 639060f344 user: james tags: trunk
03:45
Switch to bcrypt for password hashing and provide password migration check-in: ebb06e3403 user: james tags: trunk
2012-06-12
00:48
Spell check check-in: 02ac16a103 user: james tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to README.

2
3
4
5
6
7
8
9



10




11
12
13
14
15
16
17
18
19
COPYING for more information.

Flint was developed for Apache, PHP5 and SQLite. It also uses the
PDO_SQLITE driver for PHP5. All you should have to do to get it up and
running is to use the db/schema.sql file to create the db/flint.db
database and setup a virtual host under Apache.

Something like this should work:








<VirtualHost *:80>
    ServerName flint.tld 
    ServerAlias www.flint.tld
    ServerAdmin you@flint.tld
    DocumentRoot /var/www/htdocs/flint/public
    ErrorLog /var/www/logs/flint.tld/error_log
    CustomLog /var/www/logs/flint.tld/access_log combined

    ScriptAliasMatch ^/user/(.*)/repository/(.*) \







|
>
>
>

>
>
>
>

|







2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
COPYING for more information.

Flint was developed for Apache, PHP5 and SQLite. It also uses the
PDO_SQLITE driver for PHP5. All you should have to do to get it up and
running is to use the db/schema.sql file to create the db/flint.db
database and setup a virtual host under Apache.

Flint now uses bcrypt for password hashing which relies on the openssl
extension to generate random bytes. If you are upgrading from a previous
version of Flint you will need to run the following SQL statement
against db/flint.db:

ALTER TABLE users ADD COLUMN hash text;

Here is an example VirtualHost:

<VirtualHost *:80>
    ServerName flint.tld
    ServerAlias www.flint.tld
    ServerAdmin you@flint.tld
    DocumentRoot /var/www/htdocs/flint/public
    ErrorLog /var/www/logs/flint.tld/error_log
    CustomLog /var/www/logs/flint.tld/access_log combined

    ScriptAliasMatch ^/user/(.*)/repository/(.*) \

Changes to db/schema.sql.

21
22
23
24
25
26
27
28
29
30

CREATE TABLE users (
    id integer primary key autoincrement,
    first_name text,
    last_name text,
    email text,
    username text,
    password text,
    salt text
);







<
|

21
22
23
24
25
26
27

28
29

CREATE TABLE users (
    id integer primary key autoincrement,
    first_name text,
    last_name text,
    email text,
    username text,

    hash text
);

Changes to nano/session.php.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73

74
75
76
77
78
79
80
..
94
95
96
97
98
99
100




101
















102
103
104
105
106
107
108
...
290
291
292
293
294
295
296





297
298
299
        if (!session_id()) {
            session_start();
        }
    }

    public static function create($user)
    {
        $user['salt']     = base_convert(rand(), 10, 36);
        $user['password'] = hash_hmac('md5', $user['password'], $user['salt']);

        $sql = "INSERT INTO users
                       (first_name, last_name, email, username, password, salt)
                VALUES (:first, :last, :email, :username, :password, :salt)";

        $bind             = array();
        $bind['first']    = $user['firstname'];
        $bind['last']     = $user['lastname'];
        $bind['email']    = $user['email'];
        $bind['username'] = $user['username'];
        $bind['password'] = $user['password'];
        $bind['salt']     = $user['salt'];

        if (Nano_Db::execute($sql, $bind)) {
            return true;
        }

        return false;
    }
................................................................................

        $sql = "UPDATE users
                   SET first_name = :first,
                       last_name  = :last,
                       email      = :email";

        if (isset($info['password'])) {
            $info['salt']     = base_convert(rand(), 10, 36);
            $info['password'] = hash_hmac('md5', $info['password'], $info['salt']);

            $bind['password'] = $info['password'];
            $bind['salt']     = $info['salt'];


            $sql .= ", password = :password,
                       salt     = :salt";

        }

        $sql .= " WHERE id = :id";

        $bind['first']    = $info['firstname'];
        $bind['last']     = $info['lastname'];
        $bind['email']    = $info['email'];
................................................................................
                 WHERE username = :username";

        $bind             = array();
        $bind['username'] = $username;

        if ($result = Nano_Db::query($sql, $bind)) {
            $result = array_pop($result);




            if (hash_hmac('md5', $password, $result['salt']) == $result['password']) {
















                $sql = "REPLACE INTO sessions
                                (user_id, session_id, session_date)
                         VALUES (:user, :session, datetime('now'))";

                $bind            = array();
                $bind['user']    = $result['id'];
                $bind['session'] = session_id();
................................................................................
    {
        if (self::getUserByEmail($email)) {
            return false;
        }

        return true;
    }





}

Nano_Session::init();







|
<


|
|






<
|







 







|
<

<
<
>

|
|
>







 







>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>



7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
..
57
58
59
60
61
62
63
64

65


66
67
68
69
70
71
72
73
74
75
76
77
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
        if (!session_id()) {
            session_start();
        }
    }

    public static function create($user)
    {
        $user['hash'] = crypt($user['password'], self::generateSalt());


        $sql = "INSERT INTO users
                       (first_name, last_name, email, username, hash)
                VALUES (:first, :last, :email, :username, :hash)";

        $bind             = array();
        $bind['first']    = $user['firstname'];
        $bind['last']     = $user['lastname'];
        $bind['email']    = $user['email'];
        $bind['username'] = $user['username'];

        $bind['hash']     = $user['hash'];

        if (Nano_Db::execute($sql, $bind)) {
            return true;
        }

        return false;
    }
................................................................................

        $sql = "UPDATE users
                   SET first_name = :first,
                       last_name  = :last,
                       email      = :email";

        if (isset($info['password'])) {
            $info['hash'] = crypt($info['password'], self::generateSalt());




            $bind['hash'] = $info['hash'];

            $sql .= ", password = '',
                       salt     = '',
                       hash     = :hash";
        }

        $sql .= " WHERE id = :id";

        $bind['first']    = $info['firstname'];
        $bind['last']     = $info['lastname'];
        $bind['email']    = $info['email'];
................................................................................
                 WHERE username = :username";

        $bind             = array();
        $bind['username'] = $username;

        if ($result = Nano_Db::query($sql, $bind)) {
            $result = array_pop($result);

            if (!empty($result['hash'])) {
                $verify = (crypt($password, $result['hash']) == $result['hash']);
            } else {
                $verify = (hash_hmac('md5', $password, $result['salt']) == $result['password']);
            }

            if ($verify) {
                if (empty($result['hash'])) {
                    $hash = crypt($password, self::generateSalt());

                    $sql = "UPDATE users
                               SET password = '',
                                   salt     = '',
                                   hash     = :hash";

                    $bind = array('hash' => $hash);

                    Nano_Db::execute($sql, $bind);
                }

                $sql = "REPLACE INTO sessions
                                (user_id, session_id, session_date)
                         VALUES (:user, :session, datetime('now'))";

                $bind            = array();
                $bind['user']    = $result['id'];
                $bind['session'] = session_id();
................................................................................
    {
        if (self::getUserByEmail($email)) {
            return false;
        }

        return true;
    }

    protected static function generateSalt()
    {
        return '$2a$12$' . substr(str_replace('+', '.', base64_encode(openssl_random_pseudo_bytes(16))), 0, 22);
    }
}

Nano_Session::init();