summaryrefslogtreecommitdiffstats
path: root/Net
diff options
context:
space:
mode:
authortailor <cygnus@janrain.com>2006-01-07 00:40:52 +0000
committertailor <cygnus@janrain.com>2006-01-07 00:40:52 +0000
commita8f19ae921440b566388e58183b9f6f6097d29a9 (patch)
tree2ada118714f0c54c0ea866d04592fabe441a48d7 /Net
parent3a3850a8e96494c07ab9f60875db683384e246a6 (diff)
downloadphp-openid-a8f19ae921440b566388e58183b9f6f6097d29a9.zip
php-openid-a8f19ae921440b566388e58183b9f6f6097d29a9.tar.gz
php-openid-a8f19ae921440b566388e58183b9f6f6097d29a9.tar.bz2
[project @ Fixed longToBinary and randomString to use platform-based integers]
Diffstat (limited to 'Net')
-rw-r--r--Net/OpenID/CryptUtil.php121
1 files changed, 116 insertions, 5 deletions
diff --git a/Net/OpenID/CryptUtil.php b/Net/OpenID/CryptUtil.php
index 4364cda..ce8573a 100644
--- a/Net/OpenID/CryptUtil.php
+++ b/Net/OpenID/CryptUtil.php
@@ -138,7 +138,9 @@ class Net_OpenID_CryptUtil {
/**
* Given a long integer, returns the number converted to a binary
- * string.
+ * string. This function accepts long integer values of arbitrary
+ * magnitude and uses the local large-number math library when
+ * available.
*
* @param integer $long The long number (can be a normal PHP
* integer or a number created by one of the available long number
@@ -152,7 +154,7 @@ class Net_OpenID_CryptUtil {
$cmp = $lib->cmp($long, 0);
if ($cmp < 0) {
- print "numToBytes takes only positive integers.";
+ print "longToBytes takes only positive integers.";
return null;
}
@@ -180,6 +182,27 @@ class Net_OpenID_CryptUtil {
}
/**
+ * Given a long integer, returns the number converted to a binary
+ * string. This function accepts "long" numbers within the PHP
+ * integer range (usually 32 bits).
+ *
+ * @param integer $long The long number (can be a normal PHP
+ * integer or a number created by one of the available long number
+ * libraries)
+ * @return string $binary The binary version of $long
+ */
+ function longToBinary_platform($long)
+ {
+
+ if ($long < 0) {
+ print "longToBytes_platform takes only positive integers.";
+ return null;
+ }
+
+ return pack('N', $long);
+ }
+
+ /**
* Given a binary string, returns the binary string converted to a
* long number.
*
@@ -203,7 +226,8 @@ class Net_OpenID_CryptUtil {
$n = $lib->init(0);
if ($bytes && ($bytes[0] > 127)) {
- print "bytesToNum works only for positive integers.";
+ trigger_error("bytesToNum works only for positive integers.",
+ E_USER_WARNING);
return null;
}
@@ -216,6 +240,25 @@ class Net_OpenID_CryptUtil {
}
/**
+ * Given a binary string, returns the binary string converted to a
+ * long number.
+ *
+ * @param string $binary The binary version of a long number,
+ * probably as a result of calling longToBinary
+ * @return integer $long The long number equivalent of the binary
+ * string $str
+ */
+ function binaryToLong_platform($str)
+ {
+ if ($str === null) {
+ return null;
+ }
+
+ $data = unpack('N', $str);
+ return $data[1];
+ }
+
+ /**
* Converts a base64-encoded string to a long number.
*
* @param string $str A base64-encoded string
@@ -280,7 +323,10 @@ class Net_OpenID_CryptUtil {
}
/**
- * Returns a random number in the specified range.
+ * Returns a random number in the specified range. This function
+ * accepts $start, $stop, and $step values of arbitrary magnitude
+ * and will utilize the local large-number math library when
+ * available.
*
* @param integer $start The start of the range, or the minimum
* random number to return
@@ -345,6 +391,71 @@ class Net_OpenID_CryptUtil {
}
/**
+ * Returns a random number in the specified range. This function
+ * accepts $start, $stop, and $step values within the platform
+ * integer range.
+ *
+ * @param integer $start The start of the range, or the minimum
+ * random number to return
+ * @param integer $stop The end of the range, or the maximum
+ * random number to return
+ * @param integer $step The step size, such that $result - ($step
+ * * N) = $start for some N
+ * @return integer $result The resulting randomly-generated number
+ */
+ function randrange_platform($start, $stop = null, $step = 1)
+ {
+
+ static $Net_OpenID_CryptUtil_duplicate_cache = array();
+
+ if ($stop == null) {
+ $stop = $start;
+ $start = 0;
+ }
+
+ $r = ($stop - $start) / $step;
+
+ // DO NOT MODIFY THIS VALUE.
+ $rbytes = Net_OpenID_CryptUtil::longToBinary_platform($r);
+
+ if (array_key_exists($rbytes, $Net_OpenID_CryptUtil_duplicate_cache)) {
+ list($duplicate, $nbytes) =
+ $Net_OpenID_CryptUtil_duplicate_cache[$rbytes];
+ } else {
+ 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[$rbytes] =
+ array($duplicate, $nbytes);
+ }
+
+ while (1) {
+ $bytes = "\x00" . Net_OpenID_CryptUtil::getBytes($nbytes);
+ $n = Net_OpenID_CryptUtil::binaryToLong_platform($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. If
* $chrs is null, the resulting string may contain any characters.
*
@@ -363,7 +474,7 @@ class Net_OpenID_CryptUtil {
$n = strlen($chrs);
$str = "";
for ($i = 0; $i < $length; $i++) {
- $str .= $chrs[Net_OpenID_CryptUtil::randrange($n)];
+ $str .= $chrs[Net_OpenID_CryptUtil::randrange_platform($n)];
}
return $str;
}