Exemplo n.º 1
0
function aes_unencapsulate($data, $prvkey)
{
    openssl_private_decrypt(base64url_decode($data['key']), $k, $prvkey);
    openssl_private_decrypt(base64url_decode($data['iv']), $i, $prvkey);
    return AES256CBC_decrypt(base64url_decode($data['data']), $k, $i);
}
Exemplo n.º 2
0
/**
 *
 * diaspora_decode($importer,$xml,$format)
 *   array $importer -> from user table
 *   string $xml -> urldecoded Diaspora salmon
 *   string $format 'legacy', 'salmon', or 'json' 
 *
 * Returns array
 * 'message' -> decoded Diaspora XML message
 * 'author' -> author diaspora handle
 * 'key' -> author public key (converted to pkcs#8)
 *
 * Author and key are used elsewhere to save a lookup for verifying replies and likes
 */
function diaspora_decode($importer, $xml, $format)
{
    $public = false;
    if ($format === 'json') {
        $json = json_decode($xml, true);
        if ($json['aes_key']) {
            $key_bundle = '';
            $result = openssl_private_decrypt(base64_decode($json['aes_key']), $key_bundle, $importer['channel_prvkey']);
            if (!$result) {
                logger('decrypting key_bundle for ' . $importer['channel_address'] . ' failed: ' . $json['aes_key'], LOGGER_NORMAL, LOG_ERR);
                http_status_exit(400);
            }
            $jkey = json_decode($key_bundle, true);
            $xml = AES256CBC_decrypt(base64_decode($json['encrypted_magic_envelope']), base64_decode($jkey['key']), base64_decode($jkey['iv']));
            if (!$xml) {
                logger('decrypting magic_envelope for ' . $importer['channel_address'] . ' failed: ' . $json['aes_key'], LOGGER_NORMAL, LOG_ERR);
                http_status_exit(400);
            }
        }
    }
    $basedom = parse_xml_string($xml);
    if ($format !== 'legacy') {
        $children = $basedom->children('http://salmon-protocol.org/ns/magic-env');
        $public = true;
        $author_link = str_replace('acct:', '', base64url_decode($children->key_id));
        /**
        			SimpleXMLElement Object
        			(
        			    [encoding] => base64url
        			    [alg] => RSA-SHA256
        			    [data] => ((base64url-encoded payload message))
        			    [sig] => ((the RSA-SHA256 signature of the above data))
        			    [key_id] => ((base64url-encoded Alice's diaspora ID))
        			)
        		**/
    } else {
        $children = $basedom->children('https://joindiaspora.com/protocol');
        if ($children->header) {
            $public = true;
            $author_link = str_replace('acct:', '', $children->header->author_id);
        } else {
            $encrypted_header = json_decode(base64_decode($children->encrypted_header));
            $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
            $ciphertext = base64_decode($encrypted_header->ciphertext);
            $outer_key_bundle = '';
            openssl_private_decrypt($encrypted_aes_key_bundle, $outer_key_bundle, $importer['channel_prvkey']);
            $j_outer_key_bundle = json_decode($outer_key_bundle);
            $outer_iv = base64_decode($j_outer_key_bundle->iv);
            $outer_key = base64_decode($j_outer_key_bundle->key);
            $decrypted = AES256CBC_decrypt($ciphertext, $outer_key, $outer_iv);
            /**
             * $decrypted now contains something like
             *
             *  <decrypted_header>
             *	 <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
             *	 <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
             ***** OBSOLETE
             *	 <author>
             *	   <name>Ryan Hughes</name>
             *	   <uri>acct:galaxor@diaspora.pirateship.org</uri>
             *	 </author>
             ***** CURRENT/LEGACY
             *	 <author_id>galaxor@diaspora.pirateship.org</author_id>
             ***** END DIFFS
             *  </decrypted_header>
             */
            logger('decrypted: ' . $decrypted, LOGGER_DATA);
            $idom = parse_xml_string($decrypted, false);
            $inner_iv = base64_decode($idom->iv);
            $inner_aes_key = base64_decode($idom->aes_key);
            $author_link = str_replace('acct:', '', $idom->author_id);
        }
    }
    $dom = $basedom->children(NAMESPACE_SALMON_ME);
    // figure out where in the DOM tree our data is hiding
    if ($dom->provenance->data) {
        $base = $dom->provenance;
    } elseif ($dom->env->data) {
        $base = $dom->env;
    } elseif ($dom->data) {
        $base = $dom;
    }
    if (!$base) {
        logger('mod-diaspora: unable to locate salmon data in xml ', LOGGER_NORMAL, LOG_ERR);
        http_status_exit(400);
    }
    // Stash the signature away for now. We have to find their key or it won't be good for anything.
    $signature = base64url_decode($base->sig);
    // unpack the  data
    // strip whitespace so our data element will return to one big base64 blob
    $data = str_replace(array(" ", "\t", "\r", "\n"), array("", "", "", ""), $base->data);
    // stash away some other stuff for later
    $type = $base->data[0]->attributes()->type[0];
    $keyhash = $base->sig[0]->attributes()->keyhash[0];
    $encoding = $base->encoding;
    $alg = $base->alg;
    $signed_data = $data . '.' . base64url_encode($type, false) . '.' . base64url_encode($encoding, false) . '.' . base64url_encode($alg, false);
    // decode the data
    $data = base64url_decode($data);
    if ($format === 'legacy' && !$public) {
        // Decode the encrypted blob
        $final_msg = AES256CBC_decrypt(base64_decode($data), $inner_aes_key, $inner_iv);
    } else {
        $final_msg = $data;
    }
    if (!$author_link) {
        logger('mod-diaspora: Could not retrieve author URI.');
        http_status_exit(400);
    }
    // Once we have the author URI, go to the web and try to find their public key
    // (first this will look it up locally if it is in the fcontact cache)
    // This will also convert diaspora public key from pkcs#1 to pkcs#8
    logger('mod-diaspora: Fetching key for ' . $author_link);
    $key = get_diaspora_key($author_link);
    if (!$key) {
        logger('mod-diaspora: Could not retrieve author key.', LOGGER_NORMAL, LOG_WARNING);
        http_status_exit(400);
    }
    $verify = rsa_verify($signed_data, $signature, $key);
    if (!$verify) {
        logger('mod-diaspora: Message did not verify. Discarding.', LOGGER_NORMAL, LOG_ERR);
        http_status_exit(400);
    }
    logger('mod-diaspora: Message verified.');
    return array('message' => $final_msg, 'author' => $author_link, 'key' => $key);
}