function SendEncryptedResponse($message) { $aes = new AES(AES_MODE_CBC); $aes->setKeyLength(256); $aes->setKey(Base64UrlDecode($_SESSION['key'])); $aes->setIV(Base64UrlDecode($_SESSION['iv'])); $aes->enablePadding(); // This is PKCS echo Base64UrlEncode($aes->encrypt($message)); exit; }
/** * 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 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 RSA_PRIVATE_FORMAT_PKCS1: case 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('AES')) { require_once 'Crypt/AES.php'; } $symkey = substr($symkey, 0, 16); $crypto = new AES(); break; case 'DES-EDE3-CFB': if (!class_exists('TripleDES')) { require_once 'Crypt/TripleDES.php'; } $crypto = new TripleDES(DES_MODE_CFB); break; case 'DES-EDE3-CBC': if (!class_exists('TripleDES')) { require_once 'Crypt/TripleDES.php'; } $crypto = new TripleDES(); break; case 'DES-CBC': if (!class_exists('DES')) { require_once 'Crypt/DES.php'; } $crypto = new 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)) != RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); if ($tag == 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)) != RSA_ASN1_SEQUENCE) { return false; } if ($this->_decodeLength($key) != strlen($key)) { return false; } $tag = ord($this->_string_shift($key)); } if ($tag != 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 BigInteger($temp, -256); $this->_string_shift($key); // skip over RSA_ASN1_INTEGER $length = $this->_decodeLength($key); $components[$type == RSA_PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new BigInteger($this->_string_shift($key, $length), -256); return $components; } if (ord($this->_string_shift($key)) != RSA_ASN1_INTEGER) { return false; } $length = $this->_decodeLength($key); $components['modulus'] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['publicExponent'] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['privateExponent'] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['primes'] = array(1 => new BigInteger($this->_string_shift($key, $length), -256)); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['primes'][] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'] = array(1 => new BigInteger($this->_string_shift($key, $length), -256)); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'][] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['coefficients'] = array(2 => new BigInteger($this->_string_shift($key, $length), -256)); if (!empty($key)) { if (ord($this->_string_shift($key)) != RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); while (!empty($key)) { if (ord($this->_string_shift($key)) != RSA_ASN1_SEQUENCE) { return false; } $this->_decodeLength($key); $key = substr($key, 1); $length = $this->_decodeLength($key); $components['primes'][] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['exponents'][] = new BigInteger($this->_string_shift($key, $length), -256); $this->_string_shift($key); $length = $this->_decodeLength($key); $components['coefficients'][] = new BigInteger($this->_string_shift($key, $length), -256); } } return $components; case 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 BigInteger($this->_string_shift($key, $length), -256); extract(unpack('Nlength', $this->_string_shift($key, 4))); $modulus = new BigInteger($this->_string_shift($key, $length), -256); if ($cleanup && strlen($key)) { extract(unpack('Nlength', $this->_string_shift($key, 4))); return array('modulus' => new BigInteger($this->_string_shift($key, $length), -256), 'publicExponent' => $modulus); } else { return 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 RSA_PRIVATE_FORMAT_XML: case 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 $this->components; // from PuTTY's SSHPUBK.C // from PuTTY's SSHPUBK.C case 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 BigInteger($this->_string_shift($public, $length), -256); extract(unpack('Nlength', $this->_string_shift($public, 4))); $components['modulus'] = new 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('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 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))); $components['privateExponent'] = new BigInteger($this->_string_shift($private, $length), -256); extract(unpack('Nlength', $this->_string_shift($private, 4))); $components['primes'] = array(1 => new BigInteger($this->_string_shift($private, $length), -256)); extract(unpack('Nlength', $this->_string_shift($private, 4))); $components['primes'][] = new 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))); $components['coefficients'] = array(2 => new BigInteger($this->_string_shift($private, $length), -256)); return $components; } }
<?php // // Copyright (c) 2011 Scott Clayton // // This file is part of the C# to PHP Encryption Library. // // The C# to PHP Encryption Library is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The C# to PHP Encryption Library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with the C# to PHP Encryption Library. If not, see <http://www.gnu.org/licenses/>. // use Simbacode\Xcrypto\Crypt\AES; $aes = new AES(); $aes->setKey('abcdefghijklmnopabcdefghijklmnop'); $aes->setIV('abcdefghijklmnop'); $aes->setKeyLength(256); echo base64_encode("abcdefghijklmnopabcdefghijklmnop") . "<BR>"; echo base64_encode("abcdefghijklmnop") . "<BR>"; $plaintext = 'llamas are super cool!'; echo base64_encode($aes->encrypt($plaintext)) . "<BR>"; echo $aes->decrypt($aes->encrypt($plaintext));
/** * Encrypts the message to be sent using AES. * Make sure you have not output any other text before or after calling this. * * @param String $message The message to be transported online */ function SendEncryptedResponse($message) { $aes = new AES(AES_MODE_CBC); $aes->setKeyLength(256); $aes->setKey($this->Base64UrlDecode($this->key)); $aes->setIV($this->Base64UrlDecode($this->iv)); $aes->enablePadding(); // This is PKCS echo $this->Base64UrlEncode($aes->encrypt($message)); exit; }