1
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* The Encrypt library provides two-way encryption of text and binary strings
* using the MCrypt extension.
* @see http://php.net/mcrypt
*
* $Id$
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Encrypt_Core {
// OS-dependant RAND type to use
protected static $rand;
// Configuration
protected $config;
/**
* Returns a singleton instance of Encrypt.
*
* @param array configuration options
* @return Encrypt_Core
*/
public static function instance($config = NULL)
{
static $instance;
// Create the singleton
empty($instance) and $instance = new Encrypt((array) $config);
return $instance;
}
/**
* Loads encryption configuration and validates the data.
*
* @param array|string custom configuration or config group name
* @throws Kohana_Exception
*/
public function __construct($config = FALSE)
{
if ( ! defined('MCRYPT_ENCRYPT'))
throw new Kohana_Exception('encrypt.requires_mcrypt');
if (is_string($config))
{
$name = $config;
// Test the config group name
if (($config = Kohana::config('encryption.'.$config)) === NULL)
throw new Kohana_Exception('encrypt.undefined_group', $name);
}
if (is_array($config))
{
// Append the default configuration options
$config += Kohana::config('encryption.default');
}
else
{
// Load the default group
$config = Kohana::config('encryption.default');
}
if (empty($config['key']))
throw new Kohana_Exception('encrypt.no_encryption_key');
// Find the max length of the key, based on cipher and mode
$size = mcrypt_get_key_size($config['cipher'], $config['mode']);
if (strlen($config['key']) > $size)
{
// Shorten the key to the maximum size
$config['key'] = substr($config['key'], 0, $size);
}
// Find the initialization vector size
$config['iv_size'] = mcrypt_get_iv_size($config['cipher'], $config['mode']);
// Cache the config in the object
$this->config = $config;
Kohana::log('debug', 'Encrypt Library initialized');
}
/**
* Encrypts a string and returns an encrypted string that can be decoded.
*
* @param string data to be encrypted
* @return string encrypted data
*/
public function encode($data)
{
// Set the rand type if it has not already been set
if (Encrypt::$rand === NULL)
{
if (KOHANA_IS_WIN)
{
// Windows only supports the system random number generator
Encrypt::$rand = MCRYPT_RAND;
}
else
{
if (defined('MCRYPT_DEV_URANDOM'))
{
// Use /dev/urandom
Encrypt::$rand = MCRYPT_DEV_URANDOM;
}
elseif (defined('MCRYPT_DEV_RANDOM'))
{
// Use /dev/random
Encrypt::$rand = MCRYPT_DEV_RANDOM;
}
else
{
// Use the system random number generator
Encrypt::$rand = MCRYPT_RAND;
}
}
}
if (Encrypt::$rand === MCRYPT_RAND)
{
// The system random number generator must always be seeded each
// time it is used, or it will not produce true random results
mt_srand();
}
// Create a random initialization vector of the proper size for the current cipher
$iv = mcrypt_create_iv($this->config['iv_size'], Encrypt::$rand);
// Encrypt the data using the configured options and generated iv
$data = mcrypt_encrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv);
// Use base64 encoding to convert to a string
return base64_encode($iv.$data);
}
/**
* Decrypts an encoded string back to its original value.
*
* @param string encoded string to be decrypted
* @return string decrypted data
*/
public function decode($data)
{
// Convert the data back to binary
$data = base64_decode($data);
// Extract the initialization vector from the data
$iv = substr($data, 0, $this->config['iv_size']);
// Remove the iv from the data
$data = substr($data, $this->config['iv_size']);
// Return the decrypted data, trimming the \0 padding bytes from the end of the data
return rtrim(mcrypt_decrypt($this->config['cipher'], $this->config['key'], $data, $this->config['mode'], $iv), "\0");
}
} // End Encrypt
|