43 const TRIPLEDES_CBC =
'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
44 const AES128_CBC =
'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
45 const AES192_CBC =
'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
46 const AES256_CBC =
'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
47 const RSA_1_5 =
'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
48 const RSA_OAEP_MGF1P =
'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
49 const DSA_SHA1 =
'http://www.w3.org/2000/09/xmldsig#dsa-sha1';
50 const RSA_SHA1 =
'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
51 const RSA_SHA256 =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
52 const RSA_SHA384 =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
53 const RSA_SHA512 =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
54 const HMAC_SHA1 =
'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
56 private $cryptParams = array ();
62 public $passphrase =
"";
68 public $keyChain = null;
70 public $isEncrypted =
false;
72 public $encryptedCtx = null;
81 private $x509Certificate = null;
87 private $X509Thumbprint = null;
99 case (self::TRIPLEDES_CBC) :
100 $this->cryptParams [
'library'] =
'mcrypt';
101 $this->cryptParams [
'cipher'] = MCRYPT_TRIPLEDES;
102 $this->cryptParams [
'mode'] = MCRYPT_MODE_CBC;
103 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmlenc#tripledes-cbc';
104 $this->cryptParams [
'keysize'] = 24;
106 case (self::AES128_CBC) :
107 $this->cryptParams [
'library'] =
'mcrypt';
108 $this->cryptParams [
'cipher'] = MCRYPT_RIJNDAEL_128;
109 $this->cryptParams [
'mode'] = MCRYPT_MODE_CBC;
110 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmlenc#aes128-cbc';
111 $this->cryptParams [
'keysize'] = 16;
113 case (self::AES192_CBC) :
114 $this->cryptParams [
'library'] =
'mcrypt';
115 $this->cryptParams [
'cipher'] = MCRYPT_RIJNDAEL_128;
116 $this->cryptParams [
'mode'] = MCRYPT_MODE_CBC;
117 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmlenc#aes192-cbc';
118 $this->cryptParams [
'keysize'] = 24;
120 case (self::AES256_CBC) :
121 $this->cryptParams [
'library'] =
'mcrypt';
122 $this->cryptParams [
'cipher'] = MCRYPT_RIJNDAEL_128;
123 $this->cryptParams [
'mode'] = MCRYPT_MODE_CBC;
124 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmlenc#aes256-cbc';
125 $this->cryptParams [
'keysize'] = 32;
127 case (self::RSA_1_5) :
128 $this->cryptParams [
'library'] =
'openssl';
129 $this->cryptParams [
'padding'] = OPENSSL_PKCS1_PADDING;
130 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmlenc#rsa-1_5';
131 if (is_array ( $params ) && ! empty ( $params [
'type'] ))
133 if ($params [
'type'] ==
'public' || $params [
'type'] ==
'private')
135 $this->cryptParams [
'type'] = $params [
'type'];
139 throw new Exception (
'Certificate "type" (private/public) must be passed via parameters' );
140 case (self::RSA_OAEP_MGF1P) :
141 $this->cryptParams [
'library'] =
'openssl';
142 $this->cryptParams [
'padding'] = OPENSSL_PKCS1_OAEP_PADDING;
143 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p';
144 $this->cryptParams [
'hash'] = null;
145 if (is_array ( $params ) && ! empty ( $params [
'type'] ))
147 if ($params [
'type'] ==
'public' || $params [
'type'] ==
'private')
149 $this->cryptParams [
'type'] = $params [
'type'];
153 throw new Exception (
'Certificate "type" (private/public) must be passed via parameters' );
154 case (self::RSA_SHA1) :
155 $this->cryptParams [
'library'] =
'openssl';
156 $this->cryptParams [
'method'] =
'http://www.w3.org/2000/09/xmldsig#rsa-sha1';
157 $this->cryptParams [
'padding'] = OPENSSL_PKCS1_PADDING;
158 if (is_array ( $params ) && ! empty ( $params [
'type'] ))
160 if ($params [
'type'] ==
'public' || $params [
'type'] ==
'private')
162 $this->cryptParams [
'type'] = $params [
'type'];
166 throw new Exception (
'Certificate "type" (private/public) must be passed via parameters' );
167 case (self::RSA_SHA256) :
168 $this->cryptParams [
'library'] =
'openssl';
169 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
170 $this->cryptParams [
'padding'] = OPENSSL_PKCS1_PADDING;
171 $this->cryptParams [
'digest'] =
'SHA256';
172 if (is_array ( $params ) && ! empty ( $params [
'type'] ))
174 if ($params [
'type'] ==
'public' || $params [
'type'] ==
'private')
176 $this->cryptParams [
'type'] = $params [
'type'];
180 throw new Exception (
'Certificate "type" (private/public) must be passed via parameters' );
181 case (self::RSA_SHA384) :
182 $this->cryptParams [
'library'] =
'openssl';
183 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384';
184 $this->cryptParams [
'padding'] = OPENSSL_PKCS1_PADDING;
185 $this->cryptParams [
'digest'] =
'SHA384';
186 if (is_array ( $params ) && ! empty ( $params [
'type'] ))
188 if ($params [
'type'] ==
'public' || $params [
'type'] ==
'private')
190 $this->cryptParams [
'type'] = $params [
'type'];
194 throw new Exception (
'Certificate "type" (private/public) must be passed via parameters' );
195 case (self::RSA_SHA512) :
196 $this->cryptParams [
'library'] =
'openssl';
197 $this->cryptParams [
'method'] =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512';
198 $this->cryptParams [
'padding'] = OPENSSL_PKCS1_PADDING;
199 $this->cryptParams [
'digest'] =
'SHA512';
200 if (is_array ( $params ) && ! empty ( $params [
'type'] ))
202 if ($params [
'type'] ==
'public' || $params [
'type'] ==
'private')
204 $this->cryptParams [
'type'] = $params [
'type'];
208 throw new Exception (
'Certificate "type" (private/public) must be passed via parameters' );
209 case (self::HMAC_SHA1) :
210 $this->cryptParams [
'library'] = $type;
211 $this->cryptParams [
'method'] =
'http://www.w3.org/2000/09/xmldsig#hmac-sha1';
214 throw new Exception (
'Invalid Key Type' );
229 if (! isset ( $this->cryptParams [
'keysize'] ))
233 return $this->cryptParams [
'keysize'];
246 if (! isset ( $this->cryptParams [
'keysize'] ))
248 throw new Exception (
'Unknown key size for type "' . $this->type .
'".' );
250 $keysize = $this->cryptParams [
'keysize'];
252 if (function_exists (
'openssl_random_pseudo_bytes' ))
255 $key = openssl_random_pseudo_bytes ( $keysize );
260 $key = mcrypt_create_iv ( $keysize, MCRYPT_RAND );
263 if ($this->type === self::TRIPLEDES_CBC)
269 for($i = 0; $i < strlen ( $key ); $i ++)
271 $byte = ord ( $key [$i] ) & 0xfe;
273 for($j = 1; $j < 8; $j ++)
275 $parity ^= ($byte >> $j) & 1;
278 $key [$i] = chr ( $byte );
294 $arCert = explode (
"\n", $cert );
297 foreach ( $arCert as $curData )
301 if (strncmp ( $curData,
'-----BEGIN CERTIFICATE', 22 ) == 0)
308 if (strncmp ( $curData,
'-----END CERTIFICATE', 20 ) == 0)
312 $data .= trim ( $curData );
315 if (! empty ( $data ))
317 return strtolower ( sha1 ( base64_decode ( $data ) ) );
330 public function loadKey($key, $isFile =
false, $isCert =
false)
334 $this->key = file_get_contents ( $key );
343 $this->key = openssl_x509_read ( $this->key );
344 openssl_x509_export ( $this->key, $str_cert );
345 $this->x509Certificate = $str_cert;
346 $this->key = $str_cert;
350 $this->x509Certificate = null;
352 if ($this->cryptParams [
'library'] ==
'openssl')
354 if ($this->cryptParams [
'type'] ==
'public')
359 $this->X509Thumbprint = self::getRawThumbprint ( $this->key );
361 $this->key = openssl_get_publickey ( $this->key );
364 throw new Exception (
'Unable to extract public key' );
369 $this->key = openssl_get_privatekey ( $this->key, $this->passphrase );
372 else if ($this->cryptParams [
'cipher'] == MCRYPT_RIJNDAEL_128)
377 case (self::AES256_CBC) :
378 if (strlen ( $this->key ) < 25)
380 throw new Exception (
'Key must contain at least 25 characters for this cipher' );
383 case (self::AES192_CBC) :
384 if (strlen ( $this->key ) < 17)
386 throw new Exception (
'Key must contain at least 17 characters for this cipher' );
399 private function encryptMcrypt($data)
401 $td = mcrypt_module_open ( $this->cryptParams [
'cipher'],
'', $this->cryptParams [
'mode'],
'' );
402 $this->iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND );
403 mcrypt_generic_init ( $td, $this->key, $this->iv );
404 if ($this->cryptParams [
'mode'] == MCRYPT_MODE_CBC)
406 $bs = mcrypt_enc_get_block_size ( $td );
407 for($datalen0 = $datalen = strlen ( $data ); (($datalen % $bs) != ($bs - 1)); $datalen ++)
408 $data .= chr ( mt_rand ( 1, 127 ) );
409 $data .= chr ( $datalen - $datalen0 + 1 );
411 $encrypted_data = $this->iv . mcrypt_generic ( $td, $data );
412 mcrypt_generic_deinit ( $td );
413 mcrypt_module_close ( $td );
414 return $encrypted_data;
423 private function decryptMcrypt($data)
425 $td = mcrypt_module_open ( $this->cryptParams [
'cipher'],
'', $this->cryptParams [
'mode'],
'' );
426 $iv_length = mcrypt_enc_get_iv_size ( $td );
427 $this->iv = substr ( $data, 0, $iv_length );
428 $data = substr ( $data, $iv_length );
429 mcrypt_generic_init ( $td, $this->key, $this->iv );
430 $decrypted_data = mdecrypt_generic ( $td, $data );
431 mcrypt_generic_deinit ( $td );
432 mcrypt_module_close ( $td );
433 if ($this->cryptParams [
'mode'] == MCRYPT_MODE_CBC)
435 $dataLen = strlen ( $decrypted_data );
436 $paddingLength = substr ( $decrypted_data, $dataLen - 1, 1 );
437 $decrypted_data = substr ( $decrypted_data, 0, $dataLen - ord ( $paddingLength ) );
439 return $decrypted_data;
449 private function encryptOpenSSL($data)
451 $encrypted_data = null;
453 if ($this->cryptParams [
'type'] ==
'public')
455 if (! openssl_public_encrypt ( $data, $encrypted_data, $this->key, $this->cryptParams [
'padding'] ))
457 throw new Exception (
'Failure encrypting Data' );
462 if (! openssl_private_encrypt ( $data, $encrypted_data, $this->key, $this->cryptParams [
'padding'] ))
464 throw new Exception (
'Failure encrypting Data' );
467 return $encrypted_data;
477 private function decryptOpenSSL($data)
480 if ($this->cryptParams [
'type'] ==
'public')
482 if (! openssl_public_decrypt ( $data, $decrypted, $this->key, $this->cryptParams [
'padding'] ))
484 throw new Exception (
'Failure decrypting Data' );
489 if (! openssl_private_decrypt ( $data, $decrypted, $this->key, $this->cryptParams [
'padding'] ))
491 throw new Exception (
'Failure decrypting Data' );
504 private function signOpenSSL($data)
507 $algo = OPENSSL_ALGO_SHA1;
508 if (! empty ( $this->cryptParams [
'digest'] ))
510 $algo = $this->cryptParams [
'digest'];
512 if (! openssl_sign ( $data, $signature, $this->key, $algo ))
514 throw new Exception (
'Failure Signing Data: ' . openssl_error_string () .
' - ' . $algo );
526 private function verifyOpenSSL($data, $signature)
528 $algo = OPENSSL_ALGO_SHA1;
529 if (! empty ( $this->cryptParams [
'digest'] ))
531 $algo = $this->cryptParams [
'digest'];
533 return openssl_verify ( $data, $signature, $this->key, $algo );
544 switch ($this->cryptParams [
'library'])
547 return $this->encryptMcrypt ( $data );
549 return $this->encryptOpenSSL ( $data );
561 switch ($this->cryptParams [
'library'])
564 return $this->decryptMcrypt ( $data );
566 return $this->decryptOpenSSL ( $data );
578 switch ($this->cryptParams [
'library'])
581 return $this->signOpenSSL ( $data );
582 case (self::HMAC_SHA1) :
583 return hash_hmac (
"sha1", $data, $this->key,
true );
596 switch ($this->cryptParams [
'library'])
599 return $this->verifyOpenSSL ( $data, $signature );
600 case (self::HMAC_SHA1) :
601 $expectedSignature = hash_hmac (
"sha1", $data, $this->key,
true );
602 return strcmp ( $signature, $expectedSignature ) == 0;
624 return $this->cryptParams [
'method'];
638 if (ord ( $string ) > 0x7f)
639 $string = chr ( 0 ) . $string;
642 $string = chr ( 0 ) . $string;
645 $length = strlen ( $string );
648 $output = sprintf (
"%c%c%s", $type, $length, $string );
650 else if ($length < 0x0100)
652 $output = sprintf (
"%c%c%c%s", $type, 0x81, $length, $string );
654 else if ($length < 0x010000)
656 $output = sprintf (
"%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string );
676 $exponentEncoding = self::makeAsnSegment ( 0x02, $exponent );
677 $modulusEncoding = self::makeAsnSegment ( 0x02, $modulus );
678 $sequenceEncoding = self::makeAsnSegment ( 0x30, $modulusEncoding . $exponentEncoding );
679 $bitstringEncoding = self::makeAsnSegment ( 0x03, $sequenceEncoding );
680 $rsaAlgorithmIdentifier = pack (
"H*",
"300D06092A864886F70D0101010500" );
681 $publicKeyInfo = self::makeAsnSegment ( 0x30, $rsaAlgorithmIdentifier . $bitstringEncoding );
683 $publicKeyInfoBase64 = base64_encode ( $publicKeyInfo );
684 $encoding =
"-----BEGIN PUBLIC KEY-----\n";
686 while ( $segment = substr ( $publicKeyInfoBase64, $offset, 64 ) )
688 $encoding = $encoding . $segment .
"\n";
691 return $encoding .
"-----END PUBLIC KEY-----\n";
712 return $this->x509Certificate;
726 return $this->X509Thumbprint;
741 $objenc->setNode ( $element );
742 if (! $objKey = $objenc->locateKey ())
744 throw new Exception (
"Unable to locate algorithm for this Encrypted Key" );
746 $objKey->isEncrypted =
true;
747 $objKey->encryptedCtx = $objenc;
static makeAsnSegment($type, $string)
loadKey($key, $isFile=false, $isCert=false)
verifySignature($data, $signature)
__construct($type, $params=null)
static staticLocateKeyInfo($objBaseKey=null, $node=null)
static convertRSA($modulus, $exponent)
static fromEncryptedKeyElement(DOMElement $element)
static getRawThumbprint($cert)