public static function Crypto($text, $cipher, $key, $isEncrypt) { switch ($cipher) { case 'DES': $crypt = new Crypt_DES(CRYPT_DES_MODE_CBC); $crypt->setKey($key); $crypt->setIV($key); if ($isEncrypt) { return strtoupper(bin2hex($crypt->encrypt($text))); } else { return $crypt->decrypt(CryptoUtil::hex2bin($text)); } break; case 'AES-256': $crypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_ECB); $crypt->setKey($key); if ($isEncrypt) { return strtoupper(bin2hex($crypt->encrypt($text))); } else { return $crypt->decrypt(CryptoUtil::hex2bin($text)); } break; default: break; } return "ERROR"; }
public static function idtagDesEncode($key, $text) { $crypt_des = new Crypt_DES(); $crypt_des->setKey($key); $crypt_des->setIV($key); $encrypted = $crypt_des->encrypt($text); return base64_encode($encrypted); }
/** * Sets the initialization vector. (optional) * * SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explicitly set, it'll be assumed * to be all zero's. * * @see Crypt_Base::setIV() * @access public * @param String $iv */ function setIV($iv) { parent::setIV($iv); if ($this->mode_3cbc) { $this->des[0]->setIV($iv); $this->des[1]->setIV($iv); $this->des[2]->setIV($iv); } }
/** * 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: (.+),(.+)#', $key, $matches)) { $iv = pack('H*', trim($matches[2])); $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 = preg_replace('#.+(\\r|\\n|\\r\\n)\\1|[\\r\\n]|-.+-#s', '', $key); $ciphertext = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false; if ($ciphertext === false) { $ciphertext = $key; } switch ($matches[1]) { case 'DES-EDE3-CBC': if (!class_exists('Crypt_TripleDES')) { require_once 'Crypt/TripleDES.php'; } $crypto = new Crypt_TripleDES(); break; case 'DES-CBC': if (!class_exists('Crypt_DES')) { require_once 'Crypt/DES.php'; } $crypto = new Crypt_DES(); break; default: return false; } $crypto->setKey($symkey); $crypto->setIV($iv); $decoded = $crypto->decrypt($ciphertext); } else { $decoded = preg_replace('#-.+-|[\\r\\n]#', '', $key); $decoded = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $decoded) ? base64_decode($decoded) : false; } if ($decoded !== false) { $key = $decoded; } $components = array(); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); if ($tag == CRYPT_RSA_ASN1_SEQUENCE) { /* intended for keys for which OpenSSL's asn1parse returns the following: 0:d=0 hl=4 l= 290 cons: SEQUENCE 4:d=1 hl=2 l= 13 cons: SEQUENCE 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 17:d=2 hl=2 l= 0 prim: NULL 19:d=1 hl=4 l= 271 prim: BIT STRING */ $this->_string_shift($key, $this->_decodeLength($key)); $this->_string_shift($key); // skip over the BIT STRING tag $this->_decodeLength($key); // skip over the BIT STRING length // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of // unused bits in teh 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 (section 8.6.2.2) $this->_string_shift($key); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); } if ($tag != CRYPT_RSA_ASN1_INTEGER) { return false; } $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; } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) { return false; } $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)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); while (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $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; } $cleanup = substr($key, 0, 11) == "ssh-rsa"; extract(unpack('Nlength', $this->_string_shift($key, 4))); $publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256); extract(unpack('Nlength', $this->_string_shift($key, 4))); $modulus = new Math_BigInteger($this->_string_shift($key, $length), -256); if ($cleanup && strlen($key)) { extract(unpack('Nlength', $this->_string_shift($key, 4))); return array('modulus' => new Math_BigInteger($this->_string_shift($key, $length), -256), 'publicExponent' => $modulus); } else { return array('modulus' => $modulus, 'publicExponent' => $publicExponent); } } }
/** * 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) { if ($type != CRYPT_RSA_PUBLIC_FORMAT_RAW && !is_string($key)) { return false; } 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 isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; 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: (.+),(.+)#', $key, $matches)) { $iv = pack('H*', trim($matches[2])); $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key $symkey .= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); $ciphertext = preg_replace('#.+(\\r|\\n|\\r\\n)\\1|[\\r\\n]|-.+-| #s', '', $key); $ciphertext = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false; if ($ciphertext === false) { $ciphertext = $key; } switch ($matches[1]) { case 'AES-128-CBC': if (!class_exists('Crypt_AES')) { require_once 'Crypt/AES.php'; } $symkey = substr($symkey, 0, 16); $crypto = new Crypt_AES(); break; case 'DES-EDE3-CFB': if (!class_exists('Crypt_TripleDES')) { require_once 'Crypt/TripleDES.php'; } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); break; case 'DES-EDE3-CBC': if (!class_exists('Crypt_TripleDES')) { require_once 'Crypt/TripleDES.php'; } $crypto = new Crypt_TripleDES(); break; case 'DES-CBC': if (!class_exists('Crypt_DES')) { require_once 'Crypt/DES.php'; } $crypto = new Crypt_DES(); break; default: return false; } $crypto->setKey($symkey); $crypto->setIV($iv); $decoded = $crypto->decrypt($ciphertext); } else { $decoded = preg_replace('#-.+-|[\\r\\n]| #', '', $key); $decoded = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $decoded) ? base64_decode($decoded) : false; } if ($decoded !== false) { $key = $decoded; } $components = array(); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); /* intended for keys for which OpenSSL's asn1parse returns the following: 0:d=0 hl=4 l= 631 cons: SEQUENCE 4:d=1 hl=2 l= 1 prim: INTEGER :00 7:d=1 hl=2 l= 13 cons: SEQUENCE 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 20:d=2 hl=2 l= 0 prim: NULL 22:d=1 hl=4 l= 609 prim: OCTET STRING */ if ($tag == CRYPT_RSA_ASN1_INTEGER && substr($key, 0, 3) == "0") { $this->_string_shift($key, 3); $tag = CRYPT_RSA_ASN1_SEQUENCE; } if ($tag == CRYPT_RSA_ASN1_SEQUENCE) { /* intended for keys for which OpenSSL's asn1parse returns the following: 0:d=0 hl=4 l= 290 cons: SEQUENCE 4:d=1 hl=2 l= 13 cons: SEQUENCE 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 17:d=2 hl=2 l= 0 prim: NULL 19:d=1 hl=4 l= 271 prim: BIT STRING */ $this->_string_shift($key, $this->_decodeLength($key)); $tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag $this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length // "The initial octet shall encode, as an unsigned binary integer wtih 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 (section 8.6.2.2) if ($tag == CRYPT_RSA_ASN1_BITSTRING) { $this->_string_shift($key); } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); } if ($tag != CRYPT_RSA_ASN1_INTEGER) { return false; } $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; } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) { return false; } $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)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); while (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $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; } $cleanup = substr($key, 0, 11) == "ssh-rsa"; if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256); if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $modulus = new Math_BigInteger($this->_string_shift($key, $length), -256); if ($cleanup && strlen($key)) { if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256); return strlen($key) ? false : array('modulus' => $realModulus, 'publicExponent' => $modulus); } else { return strlen($key) ? false : array('modulus' => $modulus, 'publicExponent' => $publicExponent); } // http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue // http://en.wikipedia.org/wiki/XML_Signature // http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue // http://en.wikipedia.org/wiki/XML_Signature case CRYPT_RSA_PRIVATE_FORMAT_XML: case CRYPT_RSA_PUBLIC_FORMAT_XML: $this->components = array(); $xml = xml_parser_create('UTF-8'); xml_set_object($xml, $this); xml_set_element_handler($xml, '_start_element_handler', '_stop_element_handler'); xml_set_character_data_handler($xml, '_data_handler'); if (!xml_parse($xml, $key)) { return false; } return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false; // from PuTTY's SSHPUBK.C // from PuTTY's SSHPUBK.C case CRYPT_RSA_PRIVATE_FORMAT_PUTTY: $components = array(); $key = preg_split('#\\r\\n|\\r|\\n#', $key); $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); if ($type != 'ssh-rsa') { return false; } $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); $publicLength = trim(preg_replace('#Public-Lines: (\\d+)#', '$1', $key[3])); $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); $public = substr($public, 11); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['publicExponent'] = new Math_BigInteger($this->_string_shift($public, $length), -256); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['modulus'] = new Math_BigInteger($this->_string_shift($public, $length), -256); $privateLength = trim(preg_replace('#Private-Lines: (\\d+)#', '$1', $key[$publicLength + 4])); $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); switch ($encryption) { case 'aes256-cbc': if (!class_exists('Crypt_AES')) { require_once 'Crypt/AES.php'; } $symkey = ''; $sequence = 0; while (strlen($symkey) < 32) { $temp = pack('Na*', $sequence++, $this->password); $symkey .= pack('H*', sha1($temp)); } $symkey = substr($symkey, 0, 32); $crypto = new Crypt_AES(); } if ($encryption != 'none') { $crypto->setKey($symkey); $crypto->disablePadding(); $private = $crypto->decrypt($private); if ($private === false) { return false; } } extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['privateExponent'] = new Math_BigInteger($this->_string_shift($private, $length), -256); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($private, $length), -256)); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['primes'][] = new Math_BigInteger($this->_string_shift($private, $length), -256); $temp = $components['primes'][1]->subtract($this->one); $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp)); $temp = $components['primes'][2]->subtract($this->one); $components['exponents'][] = $components['publicExponent']->modInverse($temp); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($private, $length), -256)); return $components; } }
function _parseKey($key, $type) { if ($type != CRYPT_RSA_PUBLIC_FORMAT_RAW && !is_string($key)) { return false; } 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 isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; case CRYPT_RSA_PRIVATE_FORMAT_PKCS1: case CRYPT_RSA_PUBLIC_FORMAT_PKCS1: if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { $iv = pack('H*', trim($matches[2])); $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8))); $ciphertext = preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-| #s', '', $key); $ciphertext = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false; if ($ciphertext === false) { $ciphertext = $key; } switch ($matches[1]) { case 'AES-256-CBC': $crypto = new Crypt_AES(); break; case 'AES-128-CBC': $symkey = substr($symkey, 0, 16); $crypto = new Crypt_AES(); break; case 'DES-EDE3-CFB': if (!class_exists('Crypt_TripleDES')) { require_once('Crypt/TripleDES.php'); } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); break; case 'DES-EDE3-CBC': if (!class_exists('Crypt_TripleDES')) { require_once('Crypt/TripleDES.php'); } $symkey = substr($symkey, 0, 24); $crypto = new Crypt_TripleDES(); break; case 'DES-CBC': if (!class_exists('Crypt_DES')) { require_once('Crypt/DES.php'); } $crypto = new Crypt_DES(); break; default: return false; } $crypto->setKey($symkey); $crypto->setIV($iv); $decoded = $crypto->decrypt($ciphertext); } else { $decoded = preg_replace('#-.+-|[\r\n]| #', '', $key); $decoded = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $decoded) ? base64_decode($decoded) : false; } if ($decoded !== false) { $key = $decoded; } $components = array(); if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); if ($tag == CRYPT_RSA_ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") { $this->_string_shift($key, 3); $tag = CRYPT_RSA_ASN1_SEQUENCE; } if ($tag == CRYPT_RSA_ASN1_SEQUENCE) { $this->_string_shift($key, $this->_decodeLength($key)); $tag = ord($this->_string_shift($key)); $this->_decodeLength($key); if ($tag == CRYPT_RSA_ASN1_BITSTRING) { $this->_string_shift($key); } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); } if ($tag != CRYPT_RSA_ASN1_INTEGER) { return false; } $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); $length = $this->_decodeLength($key); $components[$type == CRYPT_RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new Math_BigInteger($this->_string_shift($key, $length), 256); return $components; } if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_INTEGER) { return false; } $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)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); while (!empty($key)) { if (ord($this->_string_shift($key)) != CRYPT_RSA_ASN1_SEQUENCE) { return false; } $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: $parts = explode(' ', $key, 3); $key = isset($parts[1]) ? base64_decode($parts[1]) : false; if ($key === false) { return false; } $comment = isset($parts[2]) ? $parts[2] : false; $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa"; if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $publicExponent = new Math_BigInteger($this->_string_shift($key, $length), -256); if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $modulus = new Math_BigInteger($this->_string_shift($key, $length), -256); if ($cleanup && strlen($key)) { if (strlen($key) <= 4) { return false; } extract(unpack('Nlength', $this->_string_shift($key, 4))); $realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256); return strlen($key) ? false : array( 'modulus' => $realModulus, 'publicExponent' => $modulus, 'comment' => $comment ); } else { return strlen($key) ? false : array( 'modulus' => $modulus, 'publicExponent' => $publicExponent, 'comment' => $comment ); } case CRYPT_RSA_PRIVATE_FORMAT_XML: case CRYPT_RSA_PUBLIC_FORMAT_XML: $this->components = array(); $xml = xml_parser_create('UTF-8'); xml_set_object($xml, $this); xml_set_element_handler($xml, '_start_element_handler', '_stop_element_handler'); xml_set_character_data_handler($xml, '_data_handler'); if (!xml_parse($xml, '<xml>' . $key . '</xml>')) { return false; } return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false; case CRYPT_RSA_PRIVATE_FORMAT_PUTTY: $components = array(); $key = preg_split('#\r\n|\r|\n#', $key); $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); if ($type != 'ssh-rsa') { return false; } $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); $comment = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); $public = substr($public, 11); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['publicExponent'] = new Math_BigInteger($this->_string_shift($public, $length), -256); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['modulus'] = new Math_BigInteger($this->_string_shift($public, $length), -256); $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4])); $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); switch ($encryption) { case 'aes256-cbc': if (!class_exists('Crypt_AES')) { require_once('Crypt/AES.php'); } $symkey = ''; $sequence = 0; while (strlen($symkey) < 32) { $temp = pack('Na*', $sequence++, $this->password); $symkey.= pack('H*', sha1($temp)); } $symkey = substr($symkey, 0, 32); $crypto = new Crypt_AES(); } if ($encryption != 'none') { $crypto->setKey($symkey); $crypto->disablePadding(); $private = $crypto->decrypt($private); if ($private === false) { return false; } } extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['privateExponent'] = new Math_BigInteger($this->_string_shift($private, $length), -256); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['primes'] = array(1 => new Math_BigInteger($this->_string_shift($private, $length), -256)); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['primes'][] = new Math_BigInteger($this->_string_shift($private, $length), -256); $temp = $components['primes'][1]->subtract($this->one); $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp)); $temp = $components['primes'][2]->subtract($this->one); $components['exponents'][] = $components['publicExponent']->modInverse($temp); extract(unpack('Nlength', $this->_string_shift($private, 4))); if (strlen($private) < $length) { return false; } $components['coefficients'] = array(2 => new Math_BigInteger($this->_string_shift($private, $length), -256)); return $components; } }
/** * 對稱加密 */ public static function encrypt($text, $key = KEY) { $crypt_des = new Crypt_DES(); $crypt_des->setKey($key); $crypt_des->setIV($key); return base64_encode($crypt_des->encrypt($text)); }