diff options
-rw-r--r-- | boot.php | 2 | ||||
-rw-r--r-- | images/friendika-16.png | bin | 770 -> 756 bytes | |||
-rw-r--r-- | include/crypto.php (renamed from include/certfns.php) | 54 | ||||
-rw-r--r-- | include/diaspora.php | 67 | ||||
-rw-r--r-- | include/network.php | 14 | ||||
-rw-r--r-- | include/salmon.php | 31 | ||||
-rw-r--r-- | include/text.php | 6 | ||||
-rw-r--r-- | mod/receive.php | 2 | ||||
-rw-r--r-- | mod/salmon.php | 44 | ||||
-rw-r--r-- | mod/xrd.php | 14 |
10 files changed, 106 insertions, 128 deletions
@@ -7,7 +7,7 @@ require_once('include/text.php'); require_once("include/pgettext.php"); -define ( 'FRIENDIKA_VERSION', '2.2.1066' ); +define ( 'FRIENDIKA_VERSION', '2.2.1067' ); define ( 'DFRN_PROTOCOL_VERSION', '2.21' ); define ( 'DB_UPDATE_VERSION', 1079 ); diff --git a/images/friendika-16.png b/images/friendika-16.png Binary files differindex 3793508fb..745b7ac6c 100644 --- a/images/friendika-16.png +++ b/images/friendika-16.png diff --git a/include/certfns.php b/include/crypto.php index aa84cfeb6..1ab9e7b25 100644 --- a/include/certfns.php +++ b/include/crypto.php @@ -1,6 +1,56 @@ <?php require_once('library/ASNValue.class.php'); +require_once('library/asn1.php'); + + +function rsa_sign($data,$key) { + + $sig = ''; + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + openssl_sign($data,$sig,$key,'sha256'); + } + else { + if(strlen($key) < 1024 || extension_loaded('gmp')) { + require_once('library/phpsec/Crypt/RSA.php'); + $rsa = new CRYPT_RSA(); + $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1; + $rsa->setHash('sha256'); + $rsa->loadKey($key); + $sig = $rsa->sign($data); + } + else { + logger('rsa_sign: insecure algorithm used. Please upgrade PHP to 5.3'); + openssl_private_encrypt(hex2bin('3031300d060960864801650304020105000420') . hash('sha256',$data,true), $sig, $key); + } + } + return $sig; +} + +function rsa_verify($data,$sig,$key) { + + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + $verify = openssl_verify($data,$sig,$key,'sha256'); + } + else { + if(strlen($key) <= 300 || extension_loaded('gmp')) { + require_once('library/phpsec/Crypt/RSA.php'); + $rsa = new CRYPT_RSA(); + $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1; + $rsa->setHash('sha256'); + $rsa->loadKey($key); + $verify = $rsa->verify($data,$sig); + } + else { + // fallback sha256 verify for PHP < 5.3 and large key lengths + $rawsig = ''; + openssl_public_decrypt($sig,$rawsig,$key); + $verify = (($rawsig && substr($rawsig,-32) === hash('sha256',$data,true)) ? true : false); + } + } + return $verify; +} + function DerToPem($Der, $Private=false) { @@ -128,3 +178,7 @@ function metorsa($m,$e) { return $key; } +function salmon_key($pubkey) { + pemtome($pubkey,$m,$e); + return 'RSA' . '.' . base64url_encode($m,true) . '.' . base64url_encode($e,true) ; +} diff --git a/include/diaspora.php b/include/diaspora.php index 6862074c6..e39617aa3 100644 --- a/include/diaspora.php +++ b/include/diaspora.php @@ -1,6 +1,6 @@ <?php -require_once('include/certfns.php'); +require_once('include/crypto.php'); function receive_return($val) { @@ -69,7 +69,7 @@ function diaspora_msg_build($msg,$user,$contact,$prvkey,$pubkey) { $inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv); $b64_data = base64_encode($inner_encrypted); -echo "inner: $b64_data"; + $b64url_data = base64url_encode($b64_data); $b64url_stripped = str_replace(array("\n","\r"," ","\t"),array('','','',''),$b64url_data); @@ -83,9 +83,7 @@ echo "inner: $b64_data"; $signable_data = $data . '.' . base64url_encode($type) . "\n" . '.' . base64url_encode($encoding) . "\n" . '.' . base64url_encode($alg) . "\n"; - $signature = ''; - $result = openssl_sign($signable_data,$signature,$prvkey,'SHA256'); - + $signature = rsa_sign($signable_data,$prvkey); $sig = base64url_encode($signature); $decrypted_header = <<< EOT @@ -100,12 +98,8 @@ $decrypted_header = <<< EOT EOT; $decrypted_header = pkcs5_pad($decrypted_header,16); -logger("decrypted_header: $decrypted_header"); - $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv); -logger( "encrypted_ciphertext: " . base64_encode($ciphertext)); - logger("encrypt_outer_key: $b_outer_aes_key"); - logger("ecnrypt_outer_iv: $b_outer_iv"); + $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 = ''; @@ -135,44 +129,28 @@ EOT; function diaspora_decode($importer,$xml) { - $basedom = parse_xml_string($xml); - if($basedom) - logger('parsed dom'); + $basedom = parse_xml_string($xml); $atom = $basedom->children(NAMESPACE_ATOM1); - logger('atom: ' . count($atom)); $encrypted_header = json_decode(base64_decode($atom->encrypted_header)); - - print_r($encrypted_header); $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key); $ciphertext = base64_decode($encrypted_header->ciphertext); - logger('encrypted_aes: ' . print_r($encrypted_aes_key_bundle,true)); - logger('ciphertext: ' . print_r($ciphertext,true)); - $outer_key_bundle = ''; openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']); - logger('outer_bundle: ' . print_r($outer_key_bundle,true)); - $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); - logger("outer_iv: $outer_iv"); - logger("outer_key: $outer_key"); - logger("ciphertext: " . base64_encode($ciphertext)); - $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv); $decrypted = pkcs5_unpad($decrypted); - logger('decrypted: ' . print_r($decrypted,true)); - /** * $decrypted now contains something like * @@ -190,18 +168,11 @@ function diaspora_decode($importer,$xml) { $inner_iv = base64_decode($idom->iv); $inner_aes_key = base64_decode($idom->aes_key); -logger('idom: ' . print_r($idom,true)); $author_link = str_replace('acct:','',$idom->author->uri); - logger('inner_iv: ' . $inner_iv); - $dom = $basedom->children(NAMESPACE_SALMON_ME); - if($dom) - logger('have dom'); - - logger('dom: ' . count($dom)); // figure out where in the DOM tree our data is hiding if($dom->provenance->data) @@ -220,8 +191,6 @@ logger('idom: ' . print_r($idom,true)); // 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); - logger('signature: ' . bin2hex($signature)); - // unpack the data // strip whitespace so our data element will return to one big base64 blob @@ -240,7 +209,6 @@ logger('idom: ' . print_r($idom,true)); $signed_data = $data . (($data[-1] != "\n") ? "\n" : '') . '.' . base64url_encode($type) . "\n" . '.' . base64url_encode($encoding) . "\n" . '.' . base64url_encode($alg) . "\n"; - logger('signed data: ' . $signed_data); // decode the data $data = base64url_decode($data); @@ -254,13 +222,9 @@ logger('idom: ' . print_r($idom,true)); $inner_decrypted = pkcs5_unpad($inner_decrypted); - logger('inner_decrypted: ' . $inner_decrypted); - - - if(! $author_link) { logger('mod-diaspora: Could not retrieve author URI.'); - receive_return(400); + http_status_exit(400); } // Once we have the author URI, go to the web and try to find their public key @@ -272,26 +236,15 @@ logger('idom: ' . print_r($idom,true)); $key = get_diaspora_key($author_link); if(! $key) { - logger('mod-salmon: Could not retrieve author key.'); - receive_return(400); + logger('mod-diaspora: Could not retrieve author key.'); + http_status_exit(400); } - $verify = false; - - if (version_compare(PHP_VERSION, '5.3.0', '>=')) { - $verify = openssl_verify($signed_data,$signature,$key,'sha256'); - } - else { - // fallback sha256 verify for PHP < 5.3 - $rawsig = ''; - $hash = hash('sha256',$signed_data,true); - openssl_public_decrypt($signature,$rawsig,$key); - $verify = (($rawsig && substr($rawsig,-32) === $hash) ? true : false); - } + $verify = rsa_verify($signed_data,$signature,$key); if(! $verify) { logger('mod-diaspora: Message did not verify. Discarding.'); - receive_return(400); + http_status_exit(400); } logger('mod-diaspora: Message verified.'); diff --git a/include/network.php b/include/network.php index 48e830e84..ddfc34977 100644 --- a/include/network.php +++ b/include/network.php @@ -181,6 +181,20 @@ function xml_status($st, $message = '') { }} +if(! function_exists('http_status_exit')) { +function http_status_exit($val) { + + if($val >= 400) + $err = 'Error'; + if($val >= 200 && $val < 300) + $err = 'OK'; + + logger('http_status_exit ' . $val); + header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err); + killme(); + +}} + // convert an XML document to a normalised, case-corrected array // used by webfinger diff --git a/include/salmon.php b/include/salmon.php index 3ccae2756..4043b4f1d 100644 --- a/include/salmon.php +++ b/include/salmon.php @@ -1,21 +1,7 @@ <?php -require_once('library/asn1.php'); +require_once('include/crypto.php'); -function salmon_key($pubkey) { - $lines = explode("\n",$pubkey); - unset($lines[0]); - unset($lines[count($lines)]); - $x = base64_decode(implode('',$lines)); - - $r = ASN_BASE::parseASNString($x); - - $m = $r[0]->asnData[1]->asnData[0]->asnData[0]->asnData; - $e = $r[0]->asnData[1]->asnData[0]->asnData[1]->asnData; - - - return 'RSA' . '.' . $m . '.' . $e ; -} function get_salmon_key($uri,$keyhash) { @@ -112,24 +98,15 @@ EOT; $algorithm = 'RSA-SHA256'; $keyhash = base64url_encode(hash('sha256',salmon_key($owner['spubkey'])),true); - // Setup RSA stuff to PKCS#1 sign the data - - require_once('library/phpsec/Crypt/RSA.php'); - - $rsa = new CRYPT_RSA(); - $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1; - $rsa->setHash('sha256'); - $rsa->loadKey($owner['sprvkey']); - // precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods $precomputed = '.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng=='; - $signature = base64url_encode($rsa->sign(str_replace('=','',$data . $precomputed),true)); + $signature = base64url_encode(rsa_sign(str_replace('=','',$data . $precomputed),true),$owner['sprvkey']); - $signature2 = base64url_encode($rsa->sign($data . $precomputed)); + $signature2 = base64url_encode(rsa_sign($data . $precomputed),$owner['sprvkey']); - $signature3 = base64url_encode($rsa->sign($data)); + $signature3 = base64url_encode(rsa_sign($data),$owner['sprvkey']); $salmon_tpl = get_markup_template('magicsig.tpl'); diff --git a/include/text.php b/include/text.php index adc94b458..7b43cd340 100644 --- a/include/text.php +++ b/include/text.php @@ -671,7 +671,7 @@ function smilies($s) { $a = get_app(); return str_replace( - array( '<3', '</3', '<\\3', ':-)', ':)', ';-)', ':-(', ':(', ':-P', ':P', ':-"', ':-x', ':-X', ':-D', '8-|', '8-O'), + array( '<3', '</3', '<\\3', ':-)', ':)', ';-)', ':-(', ':(', ':-P', ':P', ':-"', ':-x', ':-X', ':-D', '8-|', '8-O', '~friendika' ), array( '<img src="' . $a->get_baseurl() . '/images/smiley-heart.gif" alt="<3" />', '<img src="' . $a->get_baseurl() . '/images/smiley-brokenheart.gif" alt="</3" />', @@ -688,7 +688,9 @@ function smilies($s) { '<img src="' . $a->get_baseurl() . '/images/smiley-kiss.gif" alt=":-X" />', '<img src="' . $a->get_baseurl() . '/images/smiley-laughing.gif" alt=":-D" />', '<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-|" />', - '<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" />' + '<img src="' . $a->get_baseurl() . '/images/smiley-surprised.gif" alt="8-O" />', + '<a href="http://project.friendika.com">~friendika <img src="' . $a->get_baseurl() . '/images/friendika-16.png" alt="~friendika" /></a>', + ), $s); }} diff --git a/mod/receive.php b/mod/receive.php index 851437124..e2c110202 100644 --- a/mod/receive.php +++ b/mod/receive.php @@ -6,7 +6,7 @@ require_once('include/salmon.php'); -require_once('include/certfns.php'); +require_once('include/crypto.php'); require_once('include/diaspora.php'); diff --git a/mod/salmon.php b/mod/salmon.php index 514653be3..0264e820d 100644 --- a/mod/salmon.php +++ b/mod/salmon.php @@ -5,6 +5,7 @@ // complicated process to try and sort out. require_once('include/salmon.php'); +require_once('include/crypto.php'); require_once('library/simplepie/simplepie.inc'); function salmon_return($val) { @@ -33,7 +34,7 @@ function salmon_post(&$a) { dbesc($nick) ); if(! count($r)) - salmon_return(500); + http_status_exit(500); $importer = $r[0]; @@ -52,7 +53,7 @@ function salmon_post(&$a) { if(! $base) { logger('mod-salmon: unable to locate salmon data in xml '); - salmon_return(400); + http_status_exit(400); } // Stash the signature away for now. We have to find their key or it won't be good for anything. @@ -117,7 +118,7 @@ function salmon_post(&$a) { if(! $author_link) { logger('mod-salmon: Could not retrieve author URI.'); - salmon_return(400); + http_status_exit(400); } // Once we have the author URI, go to the web and try to find their public key @@ -129,54 +130,35 @@ function salmon_post(&$a) { if(! $key) { logger('mod-salmon: Could not retrieve author key.'); - salmon_return(400); + http_status_exit(400); } - // Setup RSA stuff to verify the signature - - require_once('library/phpsec/Crypt/RSA.php'); - - $rsa = new CRYPT_RSA(); - $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1; - $rsa->setHash('sha256'); - $rsa->loadKey($prvkey); - - $sig = $rsa->sign($data); - - require_once('library/phpsec/Crypt/RSA.php'); - $key_info = explode('.',$key); $m = base64url_decode($key_info[1]); $e = base64url_decode($key_info[2]); - logger('mod-salmon: key details: ' . print_r($key_info,true)); - - $rsa = new CRYPT_RSA(); - $rsa->signatureMode = CRYPT_RSA_SIGNATURE_PKCS1; - $rsa->setHash('sha256'); + logger('mod-salmon: key details: ' . print_r($key_info,true), LOGGER_DEBUG); - $rsa->modulus = new Math_BigInteger($m, 256); - $rsa->k = strlen($rsa->modulus->toBytes()); - $rsa->exponent = new Math_BigInteger($e, 256); + $pubkey = metopem($m,$e); // We should have everything we need now. Let's see if it verifies. - $verify = $rsa->verify($compliant_format,$signature); + $verify = rsa_verify($compliant_format,$signature,$pubkey); if(! $verify) { logger('mod-salmon: message did not verify using protocol. Trying padding hack.'); - $verify = $rsa->verify($signed_data,$signature); + $verify = rsa_verify($signed_data,$signature,$pubkey); } if(! $verify) { logger('mod-salmon: message did not verify using padding. Trying old statusnet hack.'); - $verify = $rsa->verify($stnet_signed_data,$signature); + $verify = rsa_verify($stnet_signed_data,$signature,$pubkey); } if(! $verify) { logger('mod-salmon: Message did not verify. Discarding.'); - salmon_return(400); + http_status_exit(400); } logger('mod-salmon: Message verified.'); @@ -203,7 +185,7 @@ function salmon_post(&$a) { if((count($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == CONTACT_IS_FOLLOWER) || ($r[0]['blocked']))) { logger('mod-salmon: Ignoring this author.'); - salmon_return(202); + http_status_exit(202); // NOTREACHED } @@ -225,7 +207,7 @@ function salmon_post(&$a) { consume_feed($feedxml,$importer,$contact_rec,$hub); - salmon_return(200); + http_status_exit(200); } diff --git a/mod/xrd.php b/mod/xrd.php index 9021222b7..fcec74336 100644 --- a/mod/xrd.php +++ b/mod/xrd.php @@ -1,9 +1,8 @@ <?php -require_once('salmon.php'); -require_once('certfns.php'); +require_once('include/crypto.php'); -function xrd_content(&$a) { +function xrd_init(&$a) { $uri = urldecode(notags(trim($_GET['uri']))); @@ -23,14 +22,12 @@ function xrd_content(&$a) { if(! count($r)) killme(); - $salmon_key = str_replace('=','',salmon_key($r[0]['spubkey'])); + $salmon_key = salmon_key($r[0]['spubkey']); header('Access-Control-Allow-Origin: *'); header("Content-type: text/xml"); - $dspr_enabled = get_config('system','diaspora_enabled'); - - if($dspr_enabled) { + if(get_config('system','diaspora_enabled')) { $tpl = file_get_contents('view/xrd_diaspora.tpl'); $dspr = replace_macros($tpl,array( '$baseurl' => $a->get_baseurl(), @@ -41,7 +38,6 @@ function xrd_content(&$a) { else $dspr = ''; - $tpl = file_get_contents('view/xrd_person.tpl'); $o = replace_macros($tpl, array( @@ -60,7 +56,7 @@ function xrd_content(&$a) { $arr = array('user' => $r[0], 'xml' => $o); call_hooks('personal_xrd', $arr); - echo $o; + echo $arr['xml']; killme(); } |