function aes_encapsulate($data, $pubkey) { $key = random_string(32, RANDOM_STRING_TEXT); $iv = random_string(16, RANDOM_STRING_TEXT); $result['data'] = base64url_encode(AES256CBC_encrypt($data, $key, $iv), true); openssl_public_encrypt($key, $k, $pubkey); $result['key'] = base64url_encode($k, true); openssl_public_encrypt($iv, $i, $pubkey); $result['iv'] = base64url_encode($i, true); return $result; }
function diaspora_msg_build($msg, $channel, $contact, $prvkey, $pubkey, $public = false) { $a = get_app(); if ($public) { return diaspora_pubmsg_build($msg, $channel, $contact, $prvkey, $pubkey); } logger('diaspora_msg_build: ' . $msg, LOGGER_DATA, LOG_DEBUG); // without a public key nothing will work if (!$pubkey) { logger('diaspora_msg_build: pubkey missing: contact id: ' . $contact['abook_id'], LOG_ERR); return ''; } $inner_aes_key = random_string(32); $b_inner_aes_key = base64_encode($inner_aes_key); $inner_iv = random_string(16); $b_inner_iv = base64_encode($inner_iv); $outer_aes_key = random_string(32); $b_outer_aes_key = base64_encode($outer_aes_key); $outer_iv = random_string(16); $b_outer_iv = base64_encode($outer_iv); $handle = $channel['channel_address'] . '@' . App::get_hostname(); $inner_encrypted = AES256CBC_encrypt($msg, $inner_aes_key, $inner_iv); // $padded_data = pkcs5_pad($msg,16); // $inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv); $b64_data = base64_encode($inner_encrypted); $b64url_data = base64url_encode($b64_data, false); $data = str_replace(array("\n", "\r", " ", "\t"), array('', '', '', ''), $b64url_data); $type = 'application/xml'; $encoding = 'base64url'; $alg = 'RSA-SHA256'; $signable_data = $data . '.' . base64url_encode($type, false) . '.' . base64url_encode($encoding, false) . '.' . base64url_encode($alg, false); logger('diaspora_msg_build: signable_data: ' . $signable_data, LOGGER_DATA, LOG_DEBUG); $signature = rsa_sign($signable_data, $prvkey); $sig = base64url_encode($signature, false); $decrypted_header = <<<EOT <decrypted_header> <iv>{$b_inner_iv}</iv> <aes_key>{$b_inner_aes_key}</aes_key> <author_id>{$handle}</author_id> </decrypted_header> EOT; $ciphertext = AES256CBC_encrypt($decrypted_header, $outer_aes_key, $outer_iv); // $decrypted_header = pkcs5_pad($decrypted_header,16); // $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv); $outer_json = json_encode(array('iv' => $b_outer_iv, 'key' => $b_outer_aes_key)); $encrypted_outer_key_bundle = ''; openssl_public_encrypt($outer_json, $encrypted_outer_key_bundle, $pubkey); $b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle); logger('outer_bundle: ' . $b64_encrypted_outer_key_bundle . ' key: ' . $pubkey, LOGGER_DATA, LOG_DEBUG); $encrypted_header_json_object = json_encode(array('aes_key' => base64_encode($encrypted_outer_key_bundle), 'ciphertext' => base64_encode($ciphertext))); $cipher_json = base64_encode($encrypted_header_json_object); $encrypted_header = '<encrypted_header>' . $cipher_json . '</encrypted_header>'; $magic_env = <<<EOT <?xml version='1.0' encoding='UTF-8'?> <diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" > {$encrypted_header} <me:env> \t<me:encoding>base64url</me:encoding> \t<me:alg>RSA-SHA256</me:alg> \t<me:data type="application/xml">{$data}</me:data> \t<me:sig>{$sig}</me:sig> </me:env> </diaspora> EOT; logger('diaspora_msg_build: magic_env: ' . $magic_env, LOGGER_DATA, LOG_DEBUG); return $magic_env; }