1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * DNS Library for handling lookups and updates. 6 * 7 * PHP Version 5 8 * 9 * Copyright (c) 2010, Mike Pultz <mike@mikepultz.com>. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * * Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * * Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in 21 * the documentation and/or other materials provided with the 22 * distribution. 23 * 24 * * Neither the name of Mike Pultz nor the names of his contributors 25 * may be used to endorse or promote products derived from this 26 * software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 32 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 34 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 36 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGE. 40 * 41 * @category Networking 42 * @package Net_DNS2 43 * @author Mike Pultz <mike@mikepultz.com> 44 * @copyright 2011 Mike Pultz <mike@mikepultz.com> 45 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 46 * @version SVN: $Id$ 47 * @link http://pear.php.net/package/Net_DNS2 48 * @since File available since Release 1.1.0 49 * 50 */ 51 52/** 53 * SSL Private Key container class 54 * 55 * @category Networking 56 * @package Net_DNS2 57 * @author Mike Pultz <mike@mikepultz.com> 58 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 59 * @link http://pear.php.net/package/Net_DNS2 60 * 61 */ 62class Net_DNS2_PrivateKey 63{ 64 /* 65 * the filename that was loaded; stored for reference 66 */ 67 public $filename; 68 69 /* 70 * the keytag for the signature 71 */ 72 public $keytag; 73 74 /* 75 * the sign name for the signature 76 */ 77 public $signname; 78 79 /* 80 * the algorithm used for the signature 81 */ 82 public $algorithm; 83 84 /* 85 * the key format fo the signature 86 */ 87 public $key_format; 88 89 /* 90 * the openssl private key id 91 */ 92 public $instance; 93 94 /* 95 * RSA: modulus 96 */ 97 private $_modulus; 98 99 /* 100 * RSA: public exponent 101 */ 102 private $_public_exponent; 103 104 /* 105 * RSA: rivate exponent 106 */ 107 private $_private_exponent; 108 109 /* 110 * RSA: prime1 111 */ 112 private $_prime1; 113 114 /* 115 * RSA: prime2 116 */ 117 private $_prime2; 118 119 /* 120 * RSA: exponent 1 121 */ 122 private $_exponent1; 123 124 /* 125 * RSA: exponent 2 126 */ 127 private $_exponent2; 128 129 /* 130 * RSA: coefficient 131 */ 132 private $_coefficient; 133 134 /* 135 * DSA: prime 136 */ 137 public $prime; 138 139 /* 140 * DSA: subprime 141 */ 142 public $subprime; 143 144 /* 145 * DSA: base 146 */ 147 public $base; 148 149 /* 150 * DSA: private value 151 */ 152 public $private_value; 153 154 /* 155 * DSA: public value 156 */ 157 public $public_value; 158 159 /** 160 * Constructor - base constructor the private key container class 161 * 162 * @param string $file path to a private-key file to parse and load 163 * 164 * @throws Net_DNS2_Exception 165 * @access public 166 * 167 */ 168 public function __construct($file = null) 169 { 170 if (isset($file)) { 171 $this->parseFile($file); 172 } 173 } 174 175 /** 176 * parses a private key file generated by dnssec-keygen 177 * 178 * @param string $file path to a private-key file to parse and load 179 * 180 * @return boolean 181 * @throws Net_DNS2_Exception 182 * @access public 183 * 184 */ 185 public function parseFile($file) 186 { 187 // 188 // check for OpenSSL 189 // 190 if (extension_loaded('openssl') === false) { 191 192 throw new Net_DNS2_Exception( 193 'the OpenSSL extension is required to use parse private key.', 194 Net_DNS2_Lookups::E_OPENSSL_UNAVAIL 195 ); 196 } 197 198 // 199 // check to make sure the file exists 200 // 201 if (is_readable($file) == false) { 202 203 throw new Net_DNS2_Exception( 204 'invalid private key file: ' . $file, 205 Net_DNS2_Lookups::E_OPENSSL_INV_PKEY 206 ); 207 } 208 209 // 210 // get the base filename, and parse it for the local value 211 // 212 $keyname = basename($file); 213 if (strlen($keyname) == 0) { 214 215 throw new Net_DNS2_Exception( 216 'failed to get basename() for: ' . $file, 217 Net_DNS2_Lookups::E_OPENSSL_INV_PKEY 218 ); 219 } 220 221 // 222 // parse the keyname 223 // 224 if (preg_match("/K(.*)\.\+(\d{3})\+(\d*)\.private/", $keyname, $matches)) { 225 226 $this->signname = $matches[1]; 227 $this->algorithm = intval($matches[2]); 228 $this->keytag = intval($matches[3]); 229 230 } else { 231 232 throw new Net_DNS2_Exception( 233 'file ' . $keyname . ' does not look like a private key file!', 234 Net_DNS2_Lookups::E_OPENSSL_INV_PKEY 235 ); 236 } 237 238 // 239 // read all the data from the 240 // 241 $data = file($file, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); 242 if (count($data) == 0) { 243 244 throw new Net_DNS2_Exception( 245 'file ' . $keyname . ' is empty!', 246 Net_DNS2_Lookups::E_OPENSSL_INV_PKEY 247 ); 248 } 249 250 foreach ($data as $line) { 251 252 list($key, $value) = explode(':', $line); 253 254 $key = trim($key); 255 $value = trim($value); 256 257 switch(strtolower($key)) { 258 259 case 'private-key-format': 260 $this->_key_format = $value; 261 break; 262 263 case 'algorithm': 264 if ($this->algorithm != $value) { 265 throw new Net_DNS2_Exception( 266 'Algorithm mis-match! filename is ' . $this->algorithm . 267 ', contents say ' . $value, 268 Net_DNS2_Lookups::E_OPENSSL_INV_ALGO 269 ); 270 } 271 break; 272 273 // 274 // RSA 275 // 276 case 'modulus': 277 $this->_modulus = $value; 278 break; 279 280 case 'publicexponent': 281 $this->_public_exponent = $value; 282 break; 283 284 case 'privateexponent': 285 $this->_private_exponent = $value; 286 break; 287 288 case 'prime1': 289 $this->_prime1 = $value; 290 break; 291 292 case 'prime2': 293 $this->_prime2 = $value; 294 break; 295 296 case 'exponent1': 297 $this->_exponent1 = $value; 298 break; 299 300 case 'exponent2': 301 $this->_exponent2 = $value; 302 break; 303 304 case 'coefficient': 305 $this->_coefficient = $value; 306 break; 307 308 // 309 // DSA - this won't work in PHP until the OpenSSL extension is better 310 // 311 case 'prime(p)': 312 $this->prime = $value; 313 break; 314 315 case 'subprime(q)': 316 $this->subprime = $value; 317 break; 318 319 case 'base(g)': 320 $this->base = $value; 321 break; 322 323 case 'private_value(x)': 324 $this->private_value = $value; 325 break; 326 327 case 'public_value(y)': 328 $this->public_value = $value; 329 break; 330 331 default: 332 throw new Net_DNS2_Exception( 333 'unknown private key data: ' . $key . ': ' . $value, 334 Net_DNS2_Lookups::E_OPENSSL_INV_PKEY 335 ); 336 } 337 } 338 339 // 340 // generate the private key 341 // 342 $args = array(); 343 344 switch($this->algorithm) { 345 346 // 347 // RSA 348 // 349 case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5: 350 case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1: 351 case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA256: 352 case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA512: 353 354 $args = array( 355 356 'rsa' => array( 357 358 'n' => base64_decode($this->_modulus), 359 'e' => base64_decode($this->_public_exponent), 360 'd' => base64_decode($this->_private_exponent), 361 'p' => base64_decode($this->_prime1), 362 'q' => base64_decode($this->_prime2), 363 'dmp1' => base64_decode($this->_exponent1), 364 'dmq1' => base64_decode($this->_exponent2), 365 'iqmp' => base64_decode($this->_coefficient) 366 ) 367 ); 368 369 break; 370 371 // 372 // DSA - this won't work in PHP until the OpenSSL extension is better 373 // 374 case Net_DNS2_Lookups::DNSSEC_ALGORITHM_DSA: 375 376 $args = array( 377 378 'dsa' => array( 379 380 'p' => base64_decode($this->prime), 381 'q' => base64_decode($this->subprime), 382 'g' => base64_decode($this->base), 383 'priv_key' => base64_decode($this->private_value), 384 'pub_key' => base64_decode($this->public_value) 385 ) 386 ); 387 388 break; 389 390 default: 391 throw new Net_DNS2_Exception( 392 'we only currently support RSAMD5 and RSASHA1 encryption.', 393 Net_DNS2_Lookups::E_OPENSSL_INV_PKEY 394 ); 395 } 396 397 // 398 // generate and store the key 399 // 400 $this->instance = openssl_pkey_new($args); 401 if ($this->instance === false) { 402 throw new Net_DNS2_Exception( 403 openssl_error_string(), 404 Net_DNS2_Lookups::E_OPENSSL_ERROR 405 ); 406 } 407 408 // 409 // store the filename incase we need it for something 410 // 411 $this->filename = $file; 412 413 return true; 414 } 415} 416 417/* 418 * Local variables: 419 * tab-width: 4 420 * c-basic-offset: 4 421 * c-hanging-comment-ender-p: nil 422 * End: 423 */ 424?> 425