summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortailor <cygnus@janrain.com>2005-12-28 21:52:09 +0000
committertailor <cygnus@janrain.com>2005-12-28 21:52:09 +0000
commit3319724398a82a37f785d6b8ba1783a630a08cb2 (patch)
tree342c9343fa09ed6e04f6e39b14319037e0e5ebf5
parent3594ce31eab937a9745c93e45ec341b3e7bc27d0 (diff)
downloadphp-openid-3319724398a82a37f785d6b8ba1783a630a08cb2.zip
php-openid-3319724398a82a37f785d6b8ba1783a630a08cb2.tar.gz
php-openid-3319724398a82a37f785d6b8ba1783a630a08cb2.tar.bz2
[project @ Ported CryptUtils functions and added some tests for CryptUtils.]
-rw-r--r--Net/OpenID/CryptUtil.php130
-rw-r--r--Tests/Net/OpenID/CryptUtil.php81
2 files changed, 211 insertions, 0 deletions
diff --git a/Net/OpenID/CryptUtil.php b/Net/OpenID/CryptUtil.php
index f26ca72..9214cd9 100644
--- a/Net/OpenID/CryptUtil.php
+++ b/Net/OpenID/CryptUtil.php
@@ -8,6 +8,10 @@ if (!defined('Net_OpenID_RAND_SOURCE')) {
define('Net_OpenID_RAND_SOURCE', '/dev/urandom');
}
+require('HMACSHA1.php');
+
+$Net_OpenID_CryptUtil_duplicate_cache = array();
+
/**
* Cryptographic utility functions
*/
@@ -45,6 +49,132 @@ class Net_OpenID_CryptUtil {
}
return $bytes;
}
+
+ /**
+ * Computes the SHA1 hash.
+ *
+ * @param string $str The input string.
+ * @static
+ * @return string The resulting SHA1 hash.
+ */
+ function sha1($str) {
+ return sha1($str, true);
+ }
+
+ /**
+ * Computes an HMAC-SHA1 digest.
+ */
+ function hmacSha1($key, $text) {
+ return Net_OpenID_HMACSHA1($key, $text);
+ }
+
+ function fromBase64($str) {
+ return base64_decode($str);
+ }
+
+ function toBase64($str) {
+ return base64_encode($str);
+ }
+
+ function longToBinary($long) {
+ return pack("L", $long);
+ }
+
+ function binaryToLong($str) {
+ return unpack($str, "L");
+ }
+
+ function base64ToLong($str) {
+ return Net_OpenID_CryptUtil::binaryToLong(Net_OpenID_CryptUtil::fromBase64($str));
+ }
+
+ function longToBase64($long) {
+ return Net_OpenID_CryptUtil::toBase64(Net_OpenID_CryptUtil::longToBinary($long));
+ }
+
+ function strxor($x, $y) {
+ if (strlen($x) != strlen($y)) {
+ return null;
+ }
+
+ $str = "";
+ for ($i = 0; $i < strlen($x); $i++) {
+ $str .= chr(ord($x[$i]) ^ ord($y[$i]));
+ }
+
+ return $str;
+ }
+
+ function reversed($list) {
+ if (is_string($list)) {
+ return strrev($list);
+ } else if (is_array($list)) {
+ return array_reverse($list);
+ } else {
+ return null;
+ }
+ }
+
+ function randrange($start, $stop = null, $step = 1) {
+
+ global $Net_OpenID_CryptUtil_duplicate_cache;
+
+ if ($stop == null) {
+ $stop = $start;
+ $start = 0;
+ }
+
+ $r = ($stop - $start);
+
+ if (array_key_exists($r, $Net_OpenID_CryptUtil_duplicate_cache)) {
+ list($duplicate, $nbytes) = $Net_OpenID_CryptUtil_duplicate_cache[$r];
+ } else {
+ $rbytes = Net_OpenID_CryptUtil::longToBinary($r);
+ if ($rbytes[0] == '\x00') {
+ $nbytes = strlen($rbytes) - 1;
+ } else {
+ $nbytes = strlen($rbytes);
+ }
+
+ $mxrand = (pow(256, $nbytes));
+
+ // If we get a number less than this, then it is in the
+ // duplicated range.
+ $duplicate = $mxrand % $r;
+
+ if (count($Net_OpenID_CryptUtil_duplicate_cache) > 10) {
+ $Net_OpenID_CryptUtil_duplicate_cache = array();
+ }
+
+ $Net_OpenID_CryptUtil_duplicate_cache[$r] = array($duplicate, $nbytes);
+ }
+
+ while (1) {
+ $bytes = '\x00' + Net_OpenID_CryptUtil::getBytes($nbytes);
+ $n = Net_OpenID_CryptUtil::binaryToLong($bytes);
+ // Keep looping if this value is in the low duplicated range
+ if ($n >= $duplicate) {
+ break;
+ }
+ }
+ return $start + ($n % $r) * $step;
+ }
+
+ /**
+ * Produce a string of length random bytes, chosen from chrs.
+ */
+ function randomString($length, $chrs = null) {
+ if ($chrs == null) {
+ return getBytes($length);
+ } else {
+ $n = strlen($chrs);
+ $str = "";
+ for ($i = 0; $i < $length; $i++) {
+ $str .= $chrs[Net_OpenID_CryptUtil::randrange($n)];
+ }
+ return $str;
+ }
+ }
}
?> \ No newline at end of file
diff --git a/Tests/Net/OpenID/CryptUtil.php b/Tests/Net/OpenID/CryptUtil.php
index ee1cfe5..af4bd69 100644
--- a/Tests/Net/OpenID/CryptUtil.php
+++ b/Tests/Net/OpenID/CryptUtil.php
@@ -23,6 +23,87 @@ class Tests_Net_OpenID_CryptUtil extends PHPUnit_TestCase {
$this->assertFalse($data == $last);
}
}
+
+ function test_cryptrand() {
+ return;
+ // It's possible, but HIGHLY unlikely that a correct
+ // implementation will fail by returning the same number twice
+
+ $s = Net_OpenID_CryptUtil::getBytes(32);
+ $t = Net_OpenID_CryptUtil::getBytes(32);
+ $this->assertEquals(strlen($s), 32);
+ $this->assertEquals(strlen($t), 32);
+ $this->assertFalse($s == $t);
+
+ $a = Net_OpenID_CryptUtil::randrange(pow(2, 128));
+ $b = Net_OpenID_CryptUtil::randrange(pow(2, 128));
+ // assert(is_long($a));
+ // assert(is_long($b));
+ // assert($b != $a);
+
+ // Make sure that we can generate random numbers that are
+ // larger than platform int size
+ // Net_OpenID_CryptUtil::randrange(INT_MAX + 1);
+ }
+
+ function test_strxor() {
+ $NUL = "\x00";
+
+ $cases = array(
+ array($NUL, $NUL, $NUL),
+ array("\x01", $NUL, "\x01"),
+ array("a", "a", $NUL),
+ array("a", $NUL, "a"),
+ array("abc", str_repeat($NUL, 3), "abc"),
+ array(str_repeat("x", 10), str_repeat($NUL, 10), str_repeat("x", 10)),
+ array("\x01", "\x02", "\x03"),
+ array("\xf0", "\x0f", "\xff"),
+ array("\xff", "\x0f", "\xf0"),
+ );
+
+ while (list($index, $values) = each($cases)) {
+ list($aa, $bb, $expected) = $values;
+ $actual = Net_OpenID_CryptUtil::strxor($aa, $bb);
+ $this->assertEquals($actual, $expected);
+ }
+
+ $exc_cases = array(
+ array('', 'a'),
+ array('foo', 'ba'),
+ array(str_repeat($NUL, 3), str_repeat($NUL, 4)),
+ array(implode('', array_map('chr', range(0, 255))),
+ implode('', array_map('chr', range(0, 127))))
+ );
+
+ while(list($index, $values) = each($exc_cases)) {
+ list($aa, $bb) = $values;
+ $unexpected = Net_OpenID_CryptUtil::strxor($aa, $bb);
+ $this->assertNull($unexpected);
+ }
+ }
+
+ function test_reversed() {
+ $cases = array(
+ array('', ''),
+ array('a', 'a'),
+ array('ab', 'ba'),
+ array('abc', 'cba'),
+ array('abcdefg', 'gfedcba'),
+ array(array(), array()),
+ array(array(1), array(1)),
+ array(array(1,2), array(2,1)),
+ array(array(1,2,3), array(3,2,1)),
+ array(range(0, 999), array_reverse(range(0, 999)))
+ );
+
+ while (list($index, $values) = each($cases)) {
+ list($case, $expected) = $values;
+ $actual = Net_OpenID_CryptUtil::reversed($case);
+ $this->assertEquals($actual, $expected);
+ $twice = Net_OpenID_CryptUtil::reversed($actual);
+ $this->assertEquals($twice, $case);
+ }
+ }
}
?> \ No newline at end of file