Subversion Repositories Applications.framework

Rev

Rev 258 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
258 gduche 1
<?php
2
 
3
/**
4
 * Classe utilitaire proposant des fonctions permettant la réalisation d'un
5
 * échange de clé Diffie Hellman
6
 *
7
 * "En cryptographie, l'échange de clés Diffie-Hellman, du nom de ses auteurs
8
 *  Whitfield Diffie et Martin Hellman, est une méthode par laquelle deux
9
 *  personnes peuvent se mettre d'accord sur un nombre (qu'ils peuvent utiliser
10
 *  comme clé pour chiffrer la conversation suivante) sans qu'une troisième
11
 *  personne appelée Ève puisse découvrir le nombre, même en ayant écouté tous
12
 *  leurs échanges."
13
 *
14
 *  Voir http://fr.wikipedia.org/wiki/%C3%89change_de_cl%C3%A9s_Diffie-Hellman
15
 *
16
 * */
17
class DiffieHellmanUtil {
18
 
19
	// Default Diffie-Hellman key generator (1024 bit)
20
    const DH_P   = 'dcf93a0b883972ec0e19989ac5a2ce310e1d37717e8d9571bb7623731866e61ef75a2e27898b057f9891c2e27a639c3f29b60814581cd3b2ca3986d2683705577d45c2e7e52dc81c7a171876e5cea74b1448bfdfaf18828efd2519f14e45e3826634af1949e5b535cc829a483b8a76223e5d490a257f05bdff16f2fb22c583ab';
21
 
22
    //Default Diffie-Hellman prime number (should be 2 or 5)
23
    const DH_G   = '02';
24
 
25
 
26
 
27
 
28
	/**
29
     * Performs the first step of a Diffie-Hellman key exchange by generating
30
     * private and public DH values based on given prime number $p and
31
     * generator $g. Both sides of key exchange MUST have the same prime number
32
     * and generator. In this case they will able to create a random shared
33
     * secret that is never send from one to the other.
34
     *
35
     * @param string $p prime number in binary representation
36
     * @param string $g generator in binary representation
37
     * @param string $priv_key private key in binary representation
38
     * @return mixed
39
     */
40
    public static function createDhKey($p, $g, $priv_key = null)
41
    {
42
        if (function_exists('openssl_dh_compute_key')) {
43
            $dh_details = array(
44
                    'p' => $p,
45
                    'g' => $g
46
                );
47
            if ($priv_key !== null) {
48
                $dh_details['priv_key'] = $priv_key;
49
            }
50
            return openssl_pkey_new(array('dh'=>$dh_details));
51
        } else {
52
            $bn_p        = self::binToBigNum($p);
53
            $bn_g        = self::binToBigNum($g);
54
            if ($priv_key === null) {
55
                $priv_key    = self::randomBytes(self::strlen($p));
56
            }
57
            $bn_priv_key = self::binToBigNum($priv_key);
58
            if (extension_loaded('gmp')) {
59
                $bn_pub_key  = gmp_powm($bn_g, $bn_priv_key, $bn_p);
60
            } else if (extension_loaded('bcmath')) {
61
                $bn_pub_key  = bcpowmod($bn_g, $bn_priv_key, $bn_p);
62
            }
63
            $pub_key     = self::bigNumToBin($bn_pub_key);
64
 
65
            return array(
66
                'p'        => $bn_p,
67
                'g'        => $bn_g,
68
                'priv_key' => $bn_priv_key,
69
                'pub_key'  => $bn_pub_key,
70
                'details'  => array(
71
                    'p'        => $p,
72
                    'g'        => $g,
73
                    'priv_key' => $priv_key,
74
                    'pub_key'  => $pub_key));
75
        }
76
    }
77
 
78
    /**
79
     * Returns an associative array with Diffie-Hellman key components in
80
     * binary representation. The array includes original prime number 'p' and
81
     * generator 'g', random private key 'priv_key' and corresponding public
82
     * key 'pub_key'.
83
     *
84
     * @param mixed $dh Diffie-Hellman key
85
     * @return array
86
     */
87
    public static function getDhKeyDetails($dh)
88
    {
89
        if (function_exists('openssl_dh_compute_key')) {
90
            $details = openssl_pkey_get_details($dh);
91
            if (isset($details['dh'])) {
92
                return $details['dh'];
93
            }
94
        } else {
95
            return $dh['details'];
96
        }
97
    }
98
 
99
 
100
 
101
// Depuis OpenId.php, les fonctions de Diffie-Hellman
102
    // TODO : voir si ça peut être externaliser pour être réutilisé ? => dans utilitaires
103
	/**
104
     * Computes the shared secret from the private DH value $dh and the other
105
     * party's public value in $pub_key
106
     *
107
     * @param string $pub_key other party's public value
108
     * @param mixed $dh Diffie-Hellman key
109
     * @return string
110
     * @throws Zend_OpenId_Exception
111
     */
112
    public function computeDhSecret($pub_key, $dh)
113
    {
114
        if (function_exists('openssl_dh_compute_key')) {
115
            $ret = openssl_dh_compute_key($pub_key, $dh);
116
            if (ord($ret[0]) > 127) {
117
                $ret = "\0" . $ret;
118
            }
119
            return $ret;
120
        } else if (extension_loaded('gmp')) {
121
            $bn_pub_key = self::binToBigNum($pub_key);
122
            $bn_secret  = gmp_powm($bn_pub_key, $dh['priv_key'], $dh['p']);
123
            return self::bigNumToBin($bn_secret);
124
        } else if (extension_loaded('bcmath')) {
125
            $bn_pub_key = self::binToBigNum($pub_key);
126
            $bn_secret  = bcpowmod($bn_pub_key, $dh['priv_key'], $dh['p']);
127
            return self::bigNumToBin($bn_secret);
128
        }
129
        /*require_once "Zend/OpenId/Exception.php";
130
        throw new Zend_OpenId_Exception(
131
            'The system doesn\'t have proper big integer extension',
132
            Zend_OpenId_Exception::UNSUPPORTED_LONG_MATH);*/
133
 
134
        trigger_error('Le système ne gère pas les nombre de taille arbitraire', E_STRICT);
135
    }
136
 
137
	/**
138
     * Takes an arbitrary precision integer and returns its shortest big-endian
139
     * two's complement representation.
140
     *
141
     * Arbitrary precision integers MUST be encoded as big-endian signed two's
142
     * complement binary strings. Henceforth, "btwoc" is a function that takes
143
     * an arbitrary precision integer and returns its shortest big-endian two's
144
     * complement representation. All integers that are used with
145
     * Diffie-Hellman Key Exchange are positive. This means that the left-most
146
     * bit of the two's complement representation MUST be zero. If it is not,
147
     * implementations MUST add a zero byte at the front of the string.
148
     *
149
     * @param string $str binary representation of arbitrary precision integer
150
     * @return string big-endian signed representation
151
     */
152
    public function btwoc($str)
153
    {
154
        if (ord($str[0]) > 127) {
155
            return "\0" . $str;
156
        }
157
        return $str;
158
    }
159
 
160
 
161
 
162
	/**
163
     * Produces string of random byte of given length.
164
     *
165
     * @param integer $len length of requested string
166
     * @return string RAW random binary string
167
     */
168
    public function randomBytes($len)
169
    {
170
        $key = '';
171
        for($i=0; $i < $len; $i++) {
172
            $key .= chr(mt_rand(0, 255));
173
        }
174
        return $key;
175
    }
176
 
177
	/**
178
     * Returns lenght of binary string in bytes
179
     *
180
     * @param string $str
181
     * @return int the string lenght
182
     */
183
    static public function strlen($str)
184
    {
185
        if (extension_loaded('mbstring') &&
186
            (((int)ini_get('mbstring.func_overload')) & 2)) {
187
            return mb_strlen($str, 'latin1');
188
        } else {
189
            return strlen($str);
190
        }
191
    }
192
 
193
 
194
	/**
195
     * Converts binary representation into ext/gmp or ext/bcmath big integer
196
     * representation.
197
     *
198
     * @param string $bin binary representation of big number
199
     * @return mixed
200
     * @throws Zend_OpenId_Exception
201
     */
202
    protected function binToBigNum($bin)
203
    {
204
        if (extension_loaded('gmp')) {
205
            return gmp_init(bin2hex($bin), 16);
206
        } else if (extension_loaded('bcmath')) {
207
            $bn = 0;
208
            $len = self::strlen($bin);
209
            for ($i = 0; $i < $len; $i++) {
210
                $bn = bcmul($bn, 256);
211
                $bn = bcadd($bn, ord($bin[$i]));
212
            }
213
            return $bn;
214
        }
215
        /*require_once "Zend/OpenId/Exception.php";
216
        throw new Zend_OpenId_Exception(
217
            'The system doesn\'t have proper big integer extension',
218
            Zend_OpenId_Exception::UNSUPPORTED_LONG_MATH);*/
219
 
220
        trigger_error('Le système ne gère pas les nombre de taille arbitraire', E_STRICT);
221
    }
222
 
223
}
224
?>