1<?php
2
3/**
4 * CryptUtil: A suite of wrapper utility functions for the OpenID
5 * library.
6 *
7 * PHP versions 4 and 5
8 *
9 * LICENSE: See the COPYING file included in this distribution.
10 *
11 * @access private
12 * @package OpenID
13 * @author JanRain, Inc. <openid@janrain.com>
14 * @copyright 2005-2008 Janrain, Inc.
15 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
16 */
17
18if (!defined('Auth_OpenID_RAND_SOURCE')) {
19    /**
20     * The filename for a source of random bytes. Define this yourself
21     * if you have a different source of randomness.
22     */
23    define('Auth_OpenID_RAND_SOURCE', '/dev/urandom');
24}
25
26class Auth_OpenID_CryptUtil {
27    /**
28     * Get the specified number of random bytes.
29     *
30     * Attempts to use a cryptographically secure (not predictable)
31     * source of randomness if available. If there is no high-entropy
32     * randomness source available, it will fail. As a last resort,
33     * for non-critical systems, define
34     * <code>Auth_OpenID_RAND_SOURCE</code> as <code>null</code>, and
35     * the code will fall back on a pseudo-random number generator.
36     *
37     * @param int $num_bytes The length of the return value
38     * @return string $bytes random bytes
39     */
40    static function getBytes($num_bytes)
41    {
42        static $f = null;
43        $bytes = '';
44        if ($f === null) {
45            if (Auth_OpenID_RAND_SOURCE === null) {
46                $f = false;
47            } else {
48                $f = @fopen(Auth_OpenID_RAND_SOURCE, "r");
49                if ($f === false) {
50                    $msg = 'Define Auth_OpenID_RAND_SOURCE as null to ' .
51                        ' continue with an insecure random number generator.';
52                    trigger_error($msg, E_USER_ERROR);
53                }
54            }
55        }
56        if ($f === false) {
57            // pseudorandom used
58            $bytes = '';
59            for ($i = 0; $i < $num_bytes; $i += 4) {
60                $bytes .= pack('L', mt_rand());
61            }
62            $bytes = substr($bytes, 0, $num_bytes);
63        } else {
64            $bytes = fread($f, $num_bytes);
65        }
66        return $bytes;
67    }
68
69    /**
70     * Produce a string of length random bytes, chosen from chrs.  If
71     * $chrs is null, the resulting string may contain any characters.
72     *
73     * @param integer $length The length of the resulting
74     * randomly-generated string
75     * @param string $chrs A string of characters from which to choose
76     * to build the new string
77     * @return string $result A string of randomly-chosen characters
78     * from $chrs
79     */
80    static function randomString($length, $population = null)
81    {
82        if ($population === null) {
83            return Auth_OpenID_CryptUtil::getBytes($length);
84        }
85
86        $popsize = strlen($population);
87
88        if ($popsize > 256) {
89            $msg = 'More than 256 characters supplied to ' . __FUNCTION__;
90            trigger_error($msg, E_USER_ERROR);
91        }
92
93        $duplicate = 256 % $popsize;
94
95        $str = "";
96        for ($i = 0; $i < $length; $i++) {
97            do {
98                $n = ord(Auth_OpenID_CryptUtil::getBytes(1));
99            } while ($n < $duplicate);
100
101            $n %= $popsize;
102            $str .= $population[$n];
103        }
104
105        return $str;
106    }
107
108    static function constEq($s1, $s2)
109    {
110        if (strlen($s1) != strlen($s2)) {
111            return false;
112        }
113
114        $result = true;
115        $length = strlen($s1);
116        for ($i = 0; $i < $length; $i++) {
117            $result &= ($s1[$i] == $s2[$i]);
118        }
119        return $result;
120    }
121}
122
123