Exemple #1
0
 /**
  * Break a public or private key down into its constituant components
  *
  * @access private
  * @see _convertPublicKey()
  * @see _convertPrivateKey()
  * @param String $key
  * @param Integer $type
  * @return Array
  */
 function _parseKey($key, $type)
 {
     switch ($type) {
         case CRYPT_RSA_PUBLIC_FORMAT_RAW:
             if (!is_array($key)) {
                 return false;
             }
             $components = array();
             switch (true) {
                 case isset($key['e']):
                     $components['publicExponent'] = $key['e']->copy();
                     break;
                 case isset($key['exponent']):
                     $components['publicExponent'] = $key['exponent']->copy();
                     break;
                 case isset($key['publicExponent']):
                     $components['publicExponent'] = $key['publicExponent']->copy();
                     break;
                 case isset($key[0]):
                     $components['publicExponent'] = $key[0]->copy();
             }
             switch (true) {
                 case isset($key['n']):
                     $components['modulus'] = $key['n']->copy();
                     break;
                 case isset($key['modulo']):
                     $components['modulus'] = $key['modulo']->copy();
                     break;
                 case isset($key['modulus']):
                     $components['modulus'] = $key['modulus']->copy();
                     break;
                 case isset($key[1]):
                     $components['modulus'] = $key[1]->copy();
             }
             return $components;
         case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
         case CRYPT_RSA_PUBLIC_FORMAT_PKCS1:
             /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
                                "outside the scope" of PKCS#1.  PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
                                protect private keys, however, that's not what OpenSSL* does.  OpenSSL protects private keys by adding
                                two new "fields" to the key - DEK-Info and Proc-Type.  These fields are discussed here:
             
                                http://tools.ietf.org/html/rfc1421#section-4.6.1.1
                                http://tools.ietf.org/html/rfc1421#section-4.6.1.3
             
                                DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
                                DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
                                function.  As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
                                own implementation.  ie. the implementation *is* the standard and any bugs that may exist in that 
                                implementation are part of the standard, as well.
             
                                * OpenSSL is the de facto standard.  It's utilized by OpenSSH and other projects */
             if (preg_match('#DEK-Info: DES-EDE3-CBC,(.+)#', $key, $matches)) {
                 $iv = pack('H*', trim($matches[1]));
                 $symkey = pack('H*', md5($this->password . $iv));
                 // symkey is short for symmetric key
                 $symkey .= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
                 $ciphertext = base64_decode(preg_replace('#.+(\\r|\\n|\\r\\n)\\1|[\\r\\n]|-.+-#s', '', $key));
                 if ($ciphertext === false) {
                     return false;
                 }
                 if (!class_exists('Crypt_TripleDES')) {
                     require_once 'Crypt/TripleDES.php';
                 }
                 $des = new Crypt_TripleDES();
                 $des->setKey($symkey);
                 $des->setIV($iv);
                 $key = $des->decrypt($ciphertext);
             } else {
                 $key = base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $key));
                 if ($key === false) {
                     return false;
                 }
             }
             $private = false;
             $components = array();
             $this->_string_shift($key);
             // skip over CRYPT_RSA_ASN1_SEQUENCE
             $this->_decodeLength($key);
             // skip over the length of the above sequence
             $this->_string_shift($key);
             // skip over CRYPT_RSA_ASN1_INTEGER
             $length = $this->_decodeLength($key);
             $temp = $this->_string_shift($key, $length);
             if (strlen($temp) != 1 || ord($temp) > 2) {
                 $components['modulus'] = new Math_BigInteger($temp, -256);
                 $this->_string_shift($key);
                 // skip over CRYPT_RSA_ASN1_INTEGER
                 $length = $this->_decodeLength($key);
                 $components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
                 return $components;
             }
             $this->_string_shift($key);
             // skip over CRYPT_RSA_ASN1_INTEGER
             $length = $this->_decodeLength($key);
             $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), -256));
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['exponents'] = array(1 => new Math_BigInteger($this->_string_shift($key, $length), -256));
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             $this->_string_shift($key);
             $length = $this->_decodeLength($key);
             $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($key, $length), -256));
             if (!empty($key)) {
                 $key = substr($key, 1);
                 // skip over CRYPT_RSA_ASN1_SEQUENCE
                 $this->_decodeLength($key);
                 while (!empty($key)) {
                     $key = substr($key, 1);
                     // skip over CRYPT_RSA_ASN1_SEQUENCE
                     $this->_decodeLength($key);
                     $key = substr($key, 1);
                     $length = $this->_decodeLength($key);
                     $components['primes'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
                     $this->_string_shift($key);
                     $length = $this->_decodeLength($key);
                     $components['exponents'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
                     $this->_string_shift($key);
                     $length = $this->_decodeLength($key);
                     $components['coefficients'][] = new Math_BigInteger($this->_string_shift($key, $length), -256);
                 }
             }
             return $components;
         case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
             $key = base64_decode(preg_replace('#^ssh-rsa | .+$#', '', $key));
             if ($key === false) {
                 return false;
             }
             $components = array();
             extract(unpack('Nlength', $this->_string_shift($key, 4)));
             $components['modulus'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             extract(unpack('Nlength', $this->_string_shift($key, 4)));
             $components['publicExponent'] = new Math_BigInteger($this->_string_shift($key, $length), -256);
             return $components;
     }
 }
Exemple #2
0
 /**
  * 3-DES Decrypt in EDE-CBC3 Mode
  * 
  * @param string $hexEncryptedData
  *      Encrypted Data in hexadecimal representation
  * @param string $hexKey
  *      Key in hexadecimal representation
  * @param bool   $useDesModeCBC3
  *      Use DES CBC3 Mode
  * 
  * @return string
  *      Decrypted data in hexadecimal representation
  */
 public static function tripleDesDecrypt($hexEncryptedData, $hexKey, $useDesModeCBC3 = false)
 {
     //fix Crypt Library padding
     $hexKey = $hexKey . substr($hexKey, 0, 16);
     if ($useDesModeCBC3) {
         $crypt3DES = new \Crypt_TripleDES(CRYPT_DES_MODE_CBC3);
         // IDTech uses mode CRYPT_DES_MODE_CBC3
     } else {
         $crypt3DES = new \Crypt_TripleDES(CRYPT_DES_MODE_ECB);
         // Chinese uses mode CRYPT_DES_MODE_ECB
     }
     $crypt3DES->setKey(Utility::hex2bin($hexKey));
     $crypt3DES->disablePadding();
     return strtoupper(bin2hex($crypt3DES->decrypt(Utility::hex2bin($hexEncryptedData))));
 }