예제 #1
0
 public function loadKey($key, $type = false)
 {
     if ($type === false) {
         $types = array(CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PRIVATE_FORMAT_PKCS1, CRYPT_RSA_PRIVATE_FORMAT_XML, CRYPT_RSA_PRIVATE_FORMAT_PUTTY, CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
         foreach ($types as $type) {
             $components = $this->_parseKey($key, $type);
             if ($components !== false) {
                 break;
             }
         }
     } else {
         $components = $this->_parseKey($key, $type);
     }
     if ($components === false) {
         return false;
     }
     if (isset($components['comment']) && $components['comment'] !== false) {
         $this->comment = $components['comment'];
     }
     $this->modulus = $components['modulus'];
     $this->k = strlen($this->modulus->toBytes());
     $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
     if (isset($components['primes'])) {
         $this->primes = $components['primes'];
         $this->exponents = $components['exponents'];
         $this->coefficients = $components['coefficients'];
         $this->publicExponent = $components['publicExponent'];
     } else {
         $this->primes = array();
         $this->exponents = array();
         $this->coefficients = array();
         $this->publicExponent = false;
     }
     return true;
 }
예제 #2
0
파일: DSA.php 프로젝트: raz0rsdge/horde
 /**
  * Generate a number that lies between 0 and q-1.
  *
  * @param Math_BigInteger $q  Max number.
  *
  * @return Math_BigInteger  Generated number.
  */
 public static function randomNumber($q)
 {
     $bytes = strlen($q->toBytes()) + 8;
     $ints = $bytes + 1 >> 2;
     $cstring = crypt_random_string($ints);
     $random = '';
     for ($i = 0; $i < $ints; ++$i) {
         $random .= pack('N', $cstring[$i]);
     }
     $c = new Math_BigInteger(substr($random, 0, $bytes), 256);
     $one = new Math_BigInteger(1);
     $result_base = $c->divide($q->subtract($one));
     return $result_base[1]->add($one);
 }
예제 #3
0
 /**
  * Loads a public or private key
  *
  * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
  *
  * @access public
  * @param String $key
  * @param Integer $type optional
  */
 function loadKey($key, $type = CRYPT_RSA_PRIVATE_FORMAT_PKCS1)
 {
     $components = $this->_parseKey($key, $type);
     if ($components === false) {
         return false;
     }
     $this->modulus = $components['modulus'];
     $this->k = strlen($this->modulus->toBytes());
     $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
     if (isset($components['primes'])) {
         $this->primes = $components['primes'];
         $this->exponents = $components['exponents'];
         $this->coefficients = $components['coefficients'];
         $this->publicExponent = $components['publicExponent'];
     } else {
         $this->primes = array();
         $this->exponents = array();
         $this->coefficients = array();
         $this->publicExponent = false;
     }
     return true;
 }
예제 #4
0
파일: biginteger.php 프로젝트: thu0ng91/jmc
 /**
  * Logical Exclusive-Or
  *
  * @param Math_BigInteger $x
  * @access public
  * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
  * @return Math_BigInteger
  */
 function bitwise_xor($x)
 {
     switch (MATH_BIGINTEGER_MODE) {
         case MATH_BIGINTEGER_MODE_GMP:
             $temp = new Math_BigInteger();
             $temp->value = gmp_xor($this->value, $x->value);
             return $temp;
         case MATH_BIGINTEGER_MODE_BCMATH:
             return new Math_BigInteger($this->toBytes() ^ $x->toBytes(), 256);
     }
     $result = new Math_BigInteger();
     $x_length = count($x->value);
     for ($i = 0; $i < $x_length; $i++) {
         $result->value[] = $this->value[$i] ^ $x->value[$i];
     }
     return $result->_normalize();
 }
예제 #5
0
 /**
  * Default Constructor.
  *
  * Connects to an SSHv1 server
  *
  * @param String $host
  * @param optional Integer $port
  * @param optional Integer $timeout
  * @param optional Integer $cipher
  * @return Net_SSH1
  * @access public
  */
 function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
 {
     if (!class_exists('Math_BigInteger')) {
         include_once EASYWIDIR . '/third_party/phpseclib/Math/BigInteger.php';
     }
     // Include Crypt_Random
     // the class_exists() will only be called if the crypt_random_string function hasn't been defined and
     // will trigger a call to __autoload() if you're wanting to auto-load classes
     // call function_exists() a second time to stop the include_once from being called outside
     // of the auto loader
     if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) {
         include_once EASYWIDIR . '/third_party/phpseclib/Crypt/Random.php';
     }
     $this->protocol_flags = array(1 => 'NET_SSH1_MSG_DISCONNECT', 2 => 'NET_SSH1_SMSG_PUBLIC_KEY', 3 => 'NET_SSH1_CMSG_SESSION_KEY', 4 => 'NET_SSH1_CMSG_USER', 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD', 10 => 'NET_SSH1_CMSG_REQUEST_PTY', 12 => 'NET_SSH1_CMSG_EXEC_SHELL', 13 => 'NET_SSH1_CMSG_EXEC_CMD', 14 => 'NET_SSH1_SMSG_SUCCESS', 15 => 'NET_SSH1_SMSG_FAILURE', 16 => 'NET_SSH1_CMSG_STDIN_DATA', 17 => 'NET_SSH1_SMSG_STDOUT_DATA', 18 => 'NET_SSH1_SMSG_STDERR_DATA', 19 => 'NET_SSH1_CMSG_EOF', 20 => 'NET_SSH1_SMSG_EXITSTATUS', 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION');
     $this->_define_array($this->protocol_flags);
     $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
         return;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (defined('NET_SSH1_LOGGING')) {
         $this->_append_log('<-', $this->server_identification);
         $this->_append_log('->', $this->identifier . "\r\n");
     }
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers');
         return;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers");
         return;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY');
         return;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = crypt_random_string(32);
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY');
         return;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             if (!class_exists('Crypt_DES')) {
                 include_once EASYWIDIR . '/third_party/phpseclib/Crypt/DES.php';
             }
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             if (!class_exists('Crypt_TripleDES')) {
                 include_once EASYWIDIR . '/third_party/phpseclib/Crypt/TripleDES.php';
             }
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    if (!class_exists('Crypt_RC4')) {
             //        include_once('Crypt/RC4.php');
             //    }
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS');
         return;
     }
     $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
 }
예제 #6
0
파일: SSH1.php 프로젝트: heliopsis/eZCopy
 /**
  * Default Constructor.
  *
  * Connects to an SSHv1 server
  *
  * @param String $host
  * @param optional Integer $port
  * @param optional Integer $timeout
  * @param optional Integer $cipher
  * @return Net_SSH1
  * @access public
  */
 function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
 {
     $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"), E_USER_NOTICE);
         return;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers', E_USER_NOTICE);
         return;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers", E_USER_NOTICE);
         return;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY', E_USER_NOTICE);
         return;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     list(, $supported_ciphers_mask) = unpack('N', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     list(, $supported_authentications_mask) = unpack('N', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = '';
     for ($i = 0; $i < 32; $i++) {
         $session_key .= chr(crypt_random(0, 255));
     }
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY', E_USER_NOTICE);
         return;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);
         return;
     }
     $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
 }
예제 #7
0
파일: RSA.php 프로젝트: jneivil/api
 /**
  * Returns the public key's fingerprint
  *
  * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
  * no public key currently loaded, false is returned.
  * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
  *
  * @access public
  * @param String $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
  * for invalid values.
  */
 public function getPublicKeyFingerprint($algorithm = 'md5')
 {
     if (empty($this->modulus) || empty($this->publicExponent)) {
         return false;
     }
     $modulus = $this->modulus->toBytes(true);
     $publicExponent = $this->publicExponent->toBytes(true);
     $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
     switch ($algorithm) {
         case 'sha256':
             $hash = new Crypt_Hash('sha256');
             $base = base64_encode($hash->hash($RSAPublicKey));
             return substr($base, 0, strlen($base) - 1);
         case 'md5':
             return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1);
         default:
             return false;
     }
 }
예제 #8
0
 protected static function get_server_random()
 {
     $current_time = new Math_BigInteger(microtime(true) * 10000, '10');
     return bin2hex($current_time->toBytes()) . bin2hex(openssl_random_pseudo_bytes(TrustAuth::SERVER_RANDOM_LENGTH));
 }
예제 #9
0
파일: RSA.php 프로젝트: sawh/ostepu-system
 /**
  * Loads a public or private key
  *
  * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
  *
  * @access public
  * @param String $key
  * @param Integer $type optional
  */
 function loadKey($key, $type = false)
 {
     if (is_object($key) && strtolower(get_class($key)) == 'crypt_rsa') {
         $this->privateKeyFormat = $key->privateKeyFormat;
         $this->publicKeyFormat = $key->publicKeyFormat;
         $this->k = $key->k;
         $this->hLen = $key->hLen;
         $this->sLen = $key->sLen;
         $this->mgfHLen = $key->mgfHLen;
         $this->encryptionMode = $key->encryptionMode;
         $this->signatureMode = $key->signatureMode;
         $this->password = $key->password;
         $this->configFile = $key->configFile;
         $this->comment = $key->comment;
         if (is_object($key->hash)) {
             $this->hash = new Crypt_Hash($key->hash->getHash());
         }
         if (is_object($key->mgfHash)) {
             $this->mgfHash = new Crypt_Hash($key->mgfHash->getHash());
         }
         if (is_object($key->modulus)) {
             $this->modulus = $key->modulus->copy();
         }
         if (is_object($key->exponent)) {
             $this->exponent = $key->exponent->copy();
         }
         if (is_object($key->publicExponent)) {
             $this->publicExponent = $key->publicExponent->copy();
         }
         $this->primes = array();
         $this->exponents = array();
         $this->coefficients = array();
         foreach ($this->primes as $prime) {
             $this->primes[] = $prime->copy();
         }
         foreach ($this->exponents as $exponent) {
             $this->exponents[] = $exponent->copy();
         }
         foreach ($this->coefficients as $coefficient) {
             $this->coefficients[] = $coefficient->copy();
         }
         return true;
     }
     if ($type === false) {
         $types = array(CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PRIVATE_FORMAT_PKCS1, CRYPT_RSA_PRIVATE_FORMAT_XML, CRYPT_RSA_PRIVATE_FORMAT_PUTTY, CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
         foreach ($types as $type) {
             $components = $this->_parseKey($key, $type);
             if ($components !== false) {
                 break;
             }
         }
     } else {
         $components = $this->_parseKey($key, $type);
     }
     if ($components === false) {
         return false;
     }
     if (isset($components['comment']) && $components['comment'] !== false) {
         $this->comment = $components['comment'];
     }
     $this->modulus = $components['modulus'];
     $this->k = strlen($this->modulus->toBytes());
     $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
     if (isset($components['primes'])) {
         $this->primes = $components['primes'];
         $this->exponents = $components['exponents'];
         $this->coefficients = $components['coefficients'];
         $this->publicExponent = $components['publicExponent'];
     } else {
         $this->primes = array();
         $this->exponents = array();
         $this->coefficients = array();
         $this->publicExponent = false;
     }
     switch ($type) {
         case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
         case CRYPT_RSA_PUBLIC_FORMAT_RAW:
             $this->setPublicKey();
             break;
         case CRYPT_RSA_PRIVATE_FORMAT_PKCS1:
             switch (true) {
                 case strpos($key, '-BEGIN PUBLIC KEY-') !== false:
                 case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false:
                     $this->setPublicKey();
             }
     }
     return true;
 }
예제 #10
0
 /**
  * @param \Math_BigInteger $big_int
  * @return Base64urlUInt
  */
 public static function fromBigInt(\Math_BigInteger $big_int)
 {
     $b64 = new Base64UrlRepresentation();
     $input = $big_int->toBytes();
     return new Base64urlUInt($b64->encode($input));
 }
예제 #11
0
/*$str[0] = chr(145);
$str[1] = chr(70);
$str[2] = chr(59);*/
//echo $str; die();
$dec = 7.0 + 125.0 * 256 + 114.0 * 256 * 256 + 103.0 * 256 * 256 * 256 + 156.0 * 256 * 256 * 256 * 256 + 145.0 * 256 * 256 * 256 * 256 * 256 + 70.0 * 256 * 256 * 256 * 256 * 256 * 256 + 59.0 * 256 * 256 * 256 * 256 * 256 * 256 * 256;
$bi = new Math_BigInteger($str_invert, 256);
//echo $bi->toString(); die();
//echo $dec; die();
$bi1 = new Math_BigInteger(2);
$bi2 = new Math_BigInteger(1);
//$res = $bi1->divide($bi2);
//print_r($res);
//die();
$num = "4271261397543976199";
$bi = new Math_BigInteger($num, 10);
$res = $bi->toBytes();
//echo $res;die();
function check_error(&$obj)
{
    if ($obj->isError()) {
        $error = $obj->getLastError();
        switch ($error->getCode()) {
            case CRYPT_RSA_ERROR_WRONG_TAIL:
                // nothing to do
                break;
            default:
                // echo error message and exit
                die('error: ' . $error->getMessage());
        }
    }
}
 /**
  * Transforms large integer into binary representation.
  *
  * Example of transformation:
  *    $num = 0x9078563412;
  *    $str = "\x12\x34\x56\x78\x90";
  *
  * @param gmp resource $num
  * @return string
  * @access public
  */
 function int2bin($num)
 {
     $bi = new Math_BigInteger($num, 10);
     return _byte_strrev($bi->toBytes());
 }
예제 #13
0
 /**
  * Loads a public or private key
  *
  * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed)
  *
  * @access public
  * @param String $key
  * @param Integer $type optional
  */
 function loadKey($key, $type = false)
 {
     if ($type === false) {
         $types = array(CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PRIVATE_FORMAT_PKCS1, CRYPT_RSA_PRIVATE_FORMAT_XML, CRYPT_RSA_PRIVATE_FORMAT_PUTTY, CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
         foreach ($types as $type) {
             try {
                 $components = $this->_parseKey($key, $type);
                 break;
             } catch (FormatNotSupportedException $e) {
             }
         }
         if (!isset($components)) {
             throw new FormatNotSupportedException('Unable to find matching format');
         }
     } else {
         $components = $this->_parseKey($key, $type);
     }
     if (isset($components['comment']) && $components['comment'] !== false) {
         $this->comment = $components['comment'];
     }
     $this->modulus = $components['modulus'];
     $this->k = strlen($this->modulus->toBytes());
     $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
     if (isset($components['primes'])) {
         $this->primes = $components['primes'];
         $this->exponents = $components['exponents'];
         $this->coefficients = $components['coefficients'];
         $this->publicExponent = $components['publicExponent'];
     } else {
         $this->primes = array();
         $this->exponents = array();
         $this->coefficients = array();
         $this->publicExponent = false;
     }
     return true;
 }
예제 #14
0
 /**
  * Default Constructor.
  *
  * Connects to an SSHv1 server
  *
  * @param String $host
  * @param optional Integer $port
  * @param optional Integer $timeout
  * @param optional Integer $cipher
  * @return Net_SSH1
  * @access public
  */
 function __construct($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
 {
     $this->protocol_flags = array(1 => 'NET_SSH1_MSG_DISCONNECT', 2 => 'NET_SSH1_SMSG_PUBLIC_KEY', 3 => 'NET_SSH1_CMSG_SESSION_KEY', 4 => 'NET_SSH1_CMSG_USER', 9 => 'NET_SSH1_CMSG_AUTH_PASSWORD', 10 => 'NET_SSH1_CMSG_REQUEST_PTY', 12 => 'NET_SSH1_CMSG_EXEC_SHELL', 13 => 'NET_SSH1_CMSG_EXEC_CMD', 14 => 'NET_SSH1_SMSG_SUCCESS', 15 => 'NET_SSH1_SMSG_FAILURE', 16 => 'NET_SSH1_CMSG_STDIN_DATA', 17 => 'NET_SSH1_SMSG_STDOUT_DATA', 18 => 'NET_SSH1_SMSG_STDERR_DATA', 19 => 'NET_SSH1_CMSG_EOF', 20 => 'NET_SSH1_SMSG_EXITSTATUS', 33 => 'NET_SSH1_CMSG_EXIT_CONFIRMATION');
     $this->_define_array($this->protocol_flags);
     $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"), E_USER_NOTICE);
         return;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (defined('NET_SSH1_LOGGING')) {
         $this->protocol_flags_log[] = '<-';
         $this->protocol_flags_log[] = '->';
         if (NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX) {
             $this->message_log[] = $this->server_identification;
             $this->message_log[] = $this->identifier . "\r\n";
         }
     }
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers', E_USER_NOTICE);
         return;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers", E_USER_NOTICE);
         return;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY', E_USER_NOTICE);
         return;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = '';
     for ($i = 0; $i < 32; $i++) {
         $session_key .= chr(crypt_random(0, 255));
     }
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$cipher]) ? $cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY', E_USER_NOTICE);
         return;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS', E_USER_NOTICE);
         return;
     }
     $this->bitmap = NET_SSH1_MASK_CONSTRUCTOR;
 }
예제 #15
0
 /**
  * @param string $sEncryptedData
  *
  * @return string
  */
 private function clientRsaDecryptHelper($sEncryptedData)
 {
     $aMatch = array();
     if (\preg_match('/^rsa:([a-z0-9]{32}):/', $sEncryptedData, $aMatch) && !empty($aMatch[1]) && $this->Config()->Get('security', 'use_rsa_encryption', false)) {
         $oLogger = $this->Logger();
         $oLogger->Write('Trying to decode encrypted data', \MailSo\Log\Enumerations\Type::INFO, 'RSA');
         $sPrivateKey = $this->Cacher()->Get(\RainLoop\KeyPathHelper::RsaCacherKey($aMatch[1]), true);
         if (!empty($sPrivateKey)) {
             $sData = \trim(\substr($sEncryptedData, 37));
             if (!\class_exists('Crypt_RSA')) {
                 \set_include_path(\get_include_path() . PATH_SEPARATOR . APP_VERSION_ROOT_PATH . 'app/libraries/phpseclib');
                 \defined('CRYPT_RSA_MODE') || \define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
                 include_once 'Crypt/RSA.php';
             }
             \RainLoop\Service::$__HIDE_ERROR_NOTICES = true;
             $oRsa = new \Crypt_RSA();
             $oRsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
             $oRsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
             $oRsa->setPrivateKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);
             $oRsa->loadKey($sPrivateKey, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
             $oMsg = new \Math_BigInteger($sData, 16);
             $sData = $oRsa->decrypt($oMsg->toBytes());
             if (\preg_match('/^[a-z0-9]{32}:(.+):[a-z0-9]{32}$/', $sData, $aMatch) && isset($aMatch[1])) {
                 $sEncryptedData = $aMatch[1];
             } else {
                 $oLogger->Write('Invalid decrypted data', \MailSo\Log\Enumerations\Type::WARNING, 'RSA');
             }
             \RainLoop\Service::$__HIDE_ERROR_NOTICES = false;
         } else {
             $oLogger->Write('Private key is not found', \MailSo\Log\Enumerations\Type::WARNING, 'RSA');
         }
     }
     return $sEncryptedData;
 }
예제 #16
0
 /**
  * Logical Exclusive-Or
  *
  * @param Math_BigInteger $x
  * @access public
  * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
  * @return Math_BigInteger
  */
 function bitwise_xor($x)
 {
     switch (MATH_BIGINTEGER_MODE) {
         case MATH_BIGINTEGER_MODE_GMP:
             $temp = new Math_BigInteger();
             $temp->value = gmp_xor($this->value, $x->value);
             return $this->_normalize($temp);
         case MATH_BIGINTEGER_MODE_BCMATH:
             $left = $this->toBytes();
             $right = $x->toBytes();
             $length = max(strlen($left), strlen($right));
             $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
             $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
             return $this->_normalize(new Math_BigInteger($left ^ $right, 256));
     }
     $length = max(count($this->value), count($x->value));
     $result = $this->copy();
     $result->value = array_pad($result->value, $length, 0);
     $x->value = array_pad($x->value, $length, 0);
     for ($i = 0; $i < $length; ++$i) {
         $result->value[$i] ^= $x->value[$i];
     }
     return $this->_normalize($result);
 }
예제 #17
0
 /**
  * Connect to an SSHv1 server
  *
  * @return Boolean
  * @access private
  */
 function _connect()
 {
     $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout);
     if (!$this->fsock) {
         user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error {$errno}. {$errstr}"));
         return false;
     }
     $this->server_identification = $init_line = fgets($this->fsock, 255);
     if (defined('NET_SSH1_LOGGING')) {
         $this->_append_log('<-', $this->server_identification);
         $this->_append_log('->', $this->identifier . "\r\n");
     }
     if (!preg_match('#SSH-([0-9\\.]+)-(.+)#', $init_line, $parts)) {
         user_error('Can only connect to SSH servers');
         return false;
     }
     if ($parts[1][0] != 1) {
         user_error("Cannot connect to SSH {$parts['1']} servers");
         return false;
     }
     fputs($this->fsock, $this->identifier . "\r\n");
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) {
         user_error('Expected SSH_SMSG_PUBLIC_KEY');
         return false;
     }
     $anti_spoofing_cookie = $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 8);
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_exponent = $server_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $server_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->server_key_public_modulus = $server_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_exponent = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_exponent = $host_key_public_exponent;
     $temp = unpack('nlen', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 2));
     $host_key_public_modulus = new Math_BigInteger($this->_string_shift($response[NET_SSH1_RESPONSE_DATA], ceil($temp['len'] / 8)), 256);
     $this->host_key_public_modulus = $host_key_public_modulus;
     $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4);
     // get a list of the supported ciphers
     extract(unpack('Nsupported_ciphers_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_ciphers as $mask => $name) {
         if (($supported_ciphers_mask & 1 << $mask) == 0) {
             unset($this->supported_ciphers[$mask]);
         }
     }
     // get a list of the supported authentications
     extract(unpack('Nsupported_authentications_mask', $this->_string_shift($response[NET_SSH1_RESPONSE_DATA], 4)));
     foreach ($this->supported_authentications as $mask => $name) {
         if (($supported_authentications_mask & 1 << $mask) == 0) {
             unset($this->supported_authentications[$mask]);
         }
     }
     $session_id = pack('H*', md5($host_key_public_modulus->toBytes() . $server_key_public_modulus->toBytes() . $anti_spoofing_cookie));
     $session_key = crypt_random_string(32);
     $double_encrypted_session_key = $session_key ^ str_pad($session_id, 32, chr(0));
     if ($server_key_public_modulus->compare($host_key_public_modulus) < 0) {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
     } else {
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($host_key_public_exponent, $host_key_public_modulus));
         $double_encrypted_session_key = $this->_rsa_crypt($double_encrypted_session_key, array($server_key_public_exponent, $server_key_public_modulus));
     }
     $cipher = isset($this->supported_ciphers[$this->cipher]) ? $this->cipher : NET_SSH1_CIPHER_3DES;
     $data = pack('C2a*na*N', NET_SSH1_CMSG_SESSION_KEY, $cipher, $anti_spoofing_cookie, 8 * strlen($double_encrypted_session_key), $double_encrypted_session_key, 0);
     if (!$this->_send_binary_packet($data)) {
         user_error('Error sending SSH_CMSG_SESSION_KEY');
         return false;
     }
     switch ($cipher) {
         //case NET_SSH1_CIPHER_NONE:
         //    $this->crypto = new Crypt_Null();
         //    break;
         case NET_SSH1_CIPHER_DES:
             if (!class_exists('Crypt_DES')) {
                 include_once 'Crypt/DES.php';
             }
             $this->crypto = new Crypt_DES();
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 8));
             break;
         case NET_SSH1_CIPHER_3DES:
             if (!class_exists('Crypt_TripleDES')) {
                 include_once 'Crypt/TripleDES.php';
             }
             $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
             $this->crypto->disablePadding();
             $this->crypto->enableContinuousBuffer();
             $this->crypto->setKey(substr($session_key, 0, 24));
             break;
             //case NET_SSH1_CIPHER_RC4:
             //    if (!class_exists('Crypt_RC4')) {
             //        include_once 'Crypt/RC4.php';
             //    }
             //    $this->crypto = new Crypt_RC4();
             //    $this->crypto->enableContinuousBuffer();
             //    $this->crypto->setKey(substr($session_key, 0,  16));
             //    break;
     }
     $response = $this->_get_binary_packet();
     if ($response[NET_SSH1_RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) {
         user_error('Expected SSH_SMSG_SUCCESS');
         return false;
     }
     $this->bitmap = NET_SSH1_MASK_CONNECTED;
     return true;
 }
예제 #18
0
파일: ASN1.php 프로젝트: Kevin-ZK/vaneDisk
 /**
  * ASN.1 Encode (Helper function)
  *
  * @param String $source
  * @param String $mapping
  * @param Integer $idx
  * @return String
  * @access private
  */
 function _encode_der($source, $mapping, $idx = null, $special = array())
 {
     if (is_object($source) && strtolower(get_class($source)) == 'file_asn1_element') {
         return $source->element;
     }
     // do not encode (implicitly optional) fields with value set to default
     if (isset($mapping['default']) && $source === $mapping['default']) {
         return '';
     }
     if (isset($idx)) {
         if (isset($special[$idx])) {
             $source = call_user_func($special[$idx], $source);
         }
         $this->location[] = $idx;
     }
     $tag = $mapping['type'];
     switch ($tag) {
         case FILE_ASN1_TYPE_SET:
             // Children order is not important, thus process in sequence.
         // Children order is not important, thus process in sequence.
         case FILE_ASN1_TYPE_SEQUENCE:
             $tag |= 0x20;
             // set the constructed bit
             $value = '';
             // ignore the min and max
             if (isset($mapping['min']) && isset($mapping['max'])) {
                 $child = $mapping['children'];
                 foreach ($source as $content) {
                     $temp = $this->_encode_der($content, $child, null, $special);
                     if ($temp === false) {
                         return false;
                     }
                     $value .= $temp;
                 }
                 break;
             }
             foreach ($mapping['children'] as $key => $child) {
                 if (!isset($source[$key])) {
                     if (!isset($child['optional'])) {
                         return false;
                     }
                     continue;
                 }
                 $temp = $this->_encode_der($source[$key], $child, $key, $special);
                 if ($temp === false) {
                     return false;
                 }
                 // An empty child encoding means it has been optimized out.
                 // Else we should have at least one tag byte.
                 if ($temp === '') {
                     continue;
                 }
                 // if isset($child['constant']) is true then isset($child['optional']) should be true as well
                 if (isset($child['constant'])) {
                     /*
                       From X.680-0207.pdf#page=58 (30.6):
                     
                       "The tagging construction specifies explicit tagging if any of the following holds:
                        ...
                        c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or
                        AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
                        an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
                     */
                     if (isset($child['explicit']) || $child['type'] == FILE_ASN1_TYPE_CHOICE) {
                         $subtag = chr(FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6 | 0x20 | $child['constant']);
                         $temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
                     } else {
                         $subtag = chr(FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6 | ord($temp[0]) & 0x20 | $child['constant']);
                         $temp = $subtag . substr($temp, 1);
                     }
                 }
                 $value .= $temp;
             }
             break;
         case FILE_ASN1_TYPE_CHOICE:
             $temp = false;
             foreach ($mapping['children'] as $key => $child) {
                 if (!isset($source[$key])) {
                     continue;
                 }
                 $temp = $this->_encode_der($source[$key], $child, $key, $special);
                 if ($temp === false) {
                     return false;
                 }
                 // An empty child encoding means it has been optimized out.
                 // Else we should have at least one tag byte.
                 if ($temp === '') {
                     continue;
                 }
                 $tag = ord($temp[0]);
                 // if isset($child['constant']) is true then isset($child['optional']) should be true as well
                 if (isset($child['constant'])) {
                     if (isset($child['explicit']) || $child['type'] == FILE_ASN1_TYPE_CHOICE) {
                         $subtag = chr(FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6 | 0x20 | $child['constant']);
                         $temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
                     } else {
                         $subtag = chr(FILE_ASN1_CLASS_CONTEXT_SPECIFIC << 6 | ord($temp[0]) & 0x20 | $child['constant']);
                         $temp = $subtag . substr($temp, 1);
                     }
                 }
             }
             if (isset($idx)) {
                 array_pop($this->location);
             }
             if ($temp && isset($mapping['cast'])) {
                 $temp[0] = chr($mapping['class'] << 6 | $tag & 0x20 | $mapping['cast']);
             }
             return $temp;
         case FILE_ASN1_TYPE_INTEGER:
         case FILE_ASN1_TYPE_ENUMERATED:
             if (!isset($mapping['mapping'])) {
                 if (is_numeric($source)) {
                     $source = new Math_BigInteger($source);
                 }
                 $value = $source->toBytes(true);
             } else {
                 $value = array_search($source, $mapping['mapping']);
                 if ($value === false) {
                     return false;
                 }
                 $value = new Math_BigInteger($value);
                 $value = $value->toBytes(true);
             }
             if (!strlen($value)) {
                 $value = chr(0);
             }
             break;
         case FILE_ASN1_TYPE_UTC_TIME:
         case FILE_ASN1_TYPE_GENERALIZED_TIME:
             $format = $mapping['type'] == FILE_ASN1_TYPE_UTC_TIME ? 'y' : 'Y';
             $format .= 'mdHis';
             $value = @gmdate($format, strtotime($source)) . 'Z';
             break;
         case FILE_ASN1_TYPE_BIT_STRING:
             if (isset($mapping['mapping'])) {
                 $bits = array_fill(0, count($mapping['mapping']), 0);
                 $size = 0;
                 for ($i = 0; $i < count($mapping['mapping']); $i++) {
                     if (in_array($mapping['mapping'][$i], $source)) {
                         $bits[$i] = 1;
                         $size = $i;
                     }
                 }
                 if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
                     $size = $mapping['min'] - 1;
                 }
                 $offset = 8 - ($size + 1 & 7);
                 $offset = $offset !== 8 ? $offset : 0;
                 $value = chr($offset);
                 for ($i = $size + 1; $i < count($mapping['mapping']); $i++) {
                     unset($bits[$i]);
                 }
                 $bits = implode('', array_pad($bits, $size + $offset + 1, 0));
                 $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' ')));
                 foreach ($bytes as $byte) {
                     $value .= chr(bindec($byte));
                 }
                 break;
             }
         case FILE_ASN1_TYPE_OCTET_STRING:
             /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
                                the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
             
                                -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
             $value = base64_decode($source);
             break;
         case FILE_ASN1_TYPE_OBJECT_IDENTIFIER:
             $oid = preg_match('#(?:\\d+\\.)+#', $source) ? $source : array_search($source, $this->oids);
             if ($oid === false) {
                 user_error('Invalid OID');
                 return false;
             }
             $value = '';
             $parts = explode('.', $oid);
             $value = chr(40 * $parts[0] + $parts[1]);
             for ($i = 2; $i < count($parts); $i++) {
                 $temp = '';
                 if (!$parts[$i]) {
                     $temp = "";
                 } else {
                     while ($parts[$i]) {
                         $temp = chr(0x80 | $parts[$i] & 0x7f) . $temp;
                         $parts[$i] >>= 7;
                     }
                     $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7f);
                 }
                 $value .= $temp;
             }
             break;
         case FILE_ASN1_TYPE_ANY:
             $loc = $this->location;
             if (isset($idx)) {
                 array_pop($this->location);
             }
             switch (true) {
                 case !isset($source):
                     return $this->_encode_der(null, array('type' => FILE_ASN1_TYPE_NULL) + $mapping, null, $special);
                 case is_int($source):
                 case is_object($source) && strtolower(get_class($source)) == 'math_biginteger':
                     return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping, null, $special);
                 case is_float($source):
                     return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping, null, $special);
                 case is_bool($source):
                     return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping, null, $special);
                 case is_array($source) && count($source) == 1:
                     $typename = implode('', array_keys($source));
                     $outtype = array_search($typename, $this->ANYmap, true);
                     if ($outtype !== false) {
                         return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special);
                     }
             }
             $filters = $this->filters;
             foreach ($loc as $part) {
                 if (!isset($filters[$part])) {
                     $filters = false;
                     break;
                 }
                 $filters = $filters[$part];
             }
             if ($filters === false) {
                 user_error('No filters defined for ' . implode('/', $loc));
                 return false;
             }
             return $this->_encode_der($source, $filters + $mapping, null, $special);
         case FILE_ASN1_TYPE_NULL:
             $value = '';
             break;
         case FILE_ASN1_TYPE_NUMERIC_STRING:
         case FILE_ASN1_TYPE_TELETEX_STRING:
         case FILE_ASN1_TYPE_PRINTABLE_STRING:
         case FILE_ASN1_TYPE_UNIVERSAL_STRING:
         case FILE_ASN1_TYPE_UTF8_STRING:
         case FILE_ASN1_TYPE_BMP_STRING:
         case FILE_ASN1_TYPE_IA5_STRING:
         case FILE_ASN1_TYPE_VISIBLE_STRING:
         case FILE_ASN1_TYPE_VIDEOTEX_STRING:
         case FILE_ASN1_TYPE_GRAPHIC_STRING:
         case FILE_ASN1_TYPE_GENERAL_STRING:
             $value = $source;
             break;
         case FILE_ASN1_TYPE_BOOLEAN:
             $value = $source ? "ÿ" : "";
             break;
         default:
             user_error('Mapping provides no type definition for ' . implode('/', $this->location));
             return false;
     }
     if (isset($idx)) {
         array_pop($this->location);
     }
     if (isset($mapping['cast'])) {
         if (isset($mapping['explicit']) || $mapping['type'] == FILE_ASN1_TYPE_CHOICE) {
             $value = chr($tag) . $this->_encodeLength(strlen($value)) . $value;
             $tag = $mapping['class'] << 6 | 0x20 | $mapping['cast'];
         } else {
             $tag = $mapping['class'] << 6 | ord($temp[0]) & 0x20 | $mapping['cast'];
         }
     }
     return chr($tag) . $this->_encodeLength(strlen($value)) . $value;
 }