You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by jo...@apache.org on 2010/06/30 00:04:49 UTC

svn commit: r959124 - in /shindig/trunk/features: ./ src/main/javascript/features/ src/main/javascript/features/shindig.random/

Author: johnh
Date: Tue Jun 29 22:04:49 2010
New Revision: 959124

URL: http://svn.apache.org/viewvc?rev=959124&view=rev
Log:
shindig.random implementation, v1. A more-secure Math.random() in pure JS.


Added:
    shindig/trunk/features/src/main/javascript/features/shindig.random/feature.xml
    shindig/trunk/features/src/main/javascript/features/shindig.random/random.js
Modified:
    shindig/trunk/features/NOTICE
    shindig/trunk/features/src/main/javascript/features/features.txt
    shindig/trunk/features/src/main/javascript/features/shindig.random/sha1.js

Modified: shindig/trunk/features/NOTICE
URL: http://svn.apache.org/viewvc/shindig/trunk/features/NOTICE?rev=959124&r1=959123&r2=959124&view=diff
==============================================================================
--- shindig/trunk/features/NOTICE (original)
+++ shindig/trunk/features/NOTICE Tue Jun 29 22:04:49 2010
@@ -22,3 +22,4 @@ Geoff Stearns, Michael Williams, and Bob
 This product includes software (opensocial-resources) developed by
 The OpenSocial Foundation (http://opensocial-resources.googlecode.com/svn/spec/0.8/)
 
+This product contains software (sha1 JS impl) developed by Google Inc.

Modified: shindig/trunk/features/src/main/javascript/features/features.txt
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/features.txt?rev=959124&r1=959123&r2=959124&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/features.txt (original)
+++ shindig/trunk/features/src/main/javascript/features/features.txt Tue Jun 29 22:04:49 2010
@@ -62,6 +62,7 @@ features/settitle/feature.xml
 features/shindig.auth/feature.xml
 features/shindig.container/feature.xml
 features/shindig.container-1.0/feature.xml
+features/shindig.random/feature.xml
 features/shindig.xhrwrapper/feature.xml
 features/skins/feature.xml
 features/swfobject/feature.xml

Added: shindig/trunk/features/src/main/javascript/features/shindig.random/feature.xml
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.random/feature.xml?rev=959124&view=auto
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.random/feature.xml (added)
+++ shindig/trunk/features/src/main/javascript/features/shindig.random/feature.xml Tue Jun 29 22:04:49 2010
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations under the License.
+-->
+<feature>
+<!--
+A JavaScript "more-secure-random" implementation.
+-->
+  <name>shindig.random</name>
+  <dependency>globals</dependency>
+  <container>
+    <script src="sha1.js"/>
+    <script src="saferrandom.js"/>
+  </container>
+</feature>

Added: shindig/trunk/features/src/main/javascript/features/shindig.random/random.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.random/random.js?rev=959124&view=auto
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.random/random.js (added)
+++ shindig/trunk/features/src/main/javascript/features/shindig.random/random.js Tue Jun 29 22:04:49 2010
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+/*
+ * @fileoverview
+ * This code implements a safer random() method that is seeded from
+ * screen width/height and (presumably random/unguessable) mouse
+ * movement, in an effort to create a better seed for random().
+ *
+ * Its aim is to solve the problem of gadgets that are relying on
+ * secret RPC tokens to validate identity.
+ *
+ * Another possible solution is to use XHR to get a real random number
+ * from the server, though this is not feasible or may be too slow in
+ * some circumstances.
+ */
+shindig.random = (function() {
+  var oth = Math.random();
+  var hex = '0123456789ABCDEF';
+  var start = 1;
+  var m = ((screen.width * screen.width) + screen.height) * 1e6;
+
+  function sha1(str) {
+    var s = shindig.sha1();
+    s.update(str);
+    var arr = s.digest();
+    var hash = '';
+    for (var i = 0; i < arr.length; i++) {
+      hash += hex.charAt(Math.floor(arr[i] / 16)) + hex.charAt(arr[i] % 16);
+    }
+    return hash;
+  }
+
+  var orig_onmousemove = window.onmousemove || function() { return false };
+
+  window.onmousemove = function(e) {
+    if (window.event) {
+      e = event;
+    }
+
+    var ac = (e.screenX ^ e.clientX) << 16;
+    ac += (e.screenY ^ e.clientY);
+    ac *= new Date().getTime() % 1e6;
+    start = (start * ac) % m;
+    return orig_onmousemove.call(window, Array.prototype.slice.call(arguments));
+  };
+
+  var seed = sha1(
+      document.cookie + '|' + document.location + '|' + (new Date()).getTime() + '|' + oth);
+
+  return function() {
+    var rnd = start;
+    rnd += parseInt(seed.substr(0, 20), 16);
+    seed = sha1(seed);
+    return rnd / (m + Math.pow(16, 20));
+  }
+})();

Modified: shindig/trunk/features/src/main/javascript/features/shindig.random/sha1.js
URL: http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/shindig.random/sha1.js?rev=959124&r1=959123&r2=959124&view=diff
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/shindig.random/sha1.js (original)
+++ shindig/trunk/features/src/main/javascript/features/shindig.random/sha1.js Tue Jun 29 22:04:49 2010
@@ -1,28 +1,24 @@
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Copyright 2005 Google Inc. All Rights Reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS-IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+
+// File copied directly from Closure Library (http://code.google.com/p/closure-library)
+// Imported into Shindig w/ slight namespacing modifications and change from
+// prototype-style to closure (ironically) style JS objects.
 
 /**
  * @fileoverview SHA-1 cryptographic hash.
@@ -30,35 +26,32 @@
  * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
  *
  * Usage:
- *   var sha1 = new goog.crypt.sha1();
+ *   var sha1 = shindig.sha1();
  *   sha1.update(bytes);
  *   var hash = sha1.digest();
- *
  */
 
-goog.provide('goog.crypt.Sha1');
-
 /**
  * SHA-1 cryptographic hash constructor.
  *
  * The properties declared here are discussed in the above algorithm document.
  * @constructor
  */
-goog.crypt.Sha1 = function() {
+shindig.sha1 = (function() {
   /**
    * Holds the previous values of accumulated variables a-e in the compress_
    * function.
    * @type {Array.<number>}
    * @private
    */
-  this.chain_ = [];
+  var chain_ = [];
 
   /**
    * A buffer holding the partially computed hash result.
    * @type {Array.<number>}
    * @private
    */
-  this.buf_ = [];
+  var buf_ = [];
 
   /**
    * An array of 80 bytes, each a part of the message to be hashed.  Referred to
@@ -66,183 +59,184 @@ goog.crypt.Sha1 = function() {
    * @type {Array.<number>}
    * @private
    */
-  this.W_ = [];
+  var W_ = [];
 
   /**
    * Contains data needed to pad messages less than 64 bytes.
    * @type {Array.<number>}
    * @private
    */
-  this.pad_ = [];
+  var pad_ = [];
 
-  this.pad_[0] = 128;
+  pad_[0] = 128;
   for (var i = 1; i < 64; ++i) {
-    this.pad_[i] = 0;
+    pad_[i] = 0;
   }
 
-  this.reset();
-};
-
+  /**
+   * Resets the internal accumulator.
+   */
+  function reset() {
+    chain_[0] = 0x67452301;
+    chain_[1] = 0xefcdab89;
+    chain_[2] = 0x98badcfe;
+    chain_[3] = 0x10325476;
+    chain_[4] = 0xc3d2e1f0;
 
-/**
- * Resets the internal accumulator.
- */
-goog.crypt.Sha1.prototype.reset = function() {
-  this.chain_[0] = 0x67452301;
-  this.chain_[1] = 0xefcdab89;
-  this.chain_[2] = 0x98badcfe;
-  this.chain_[3] = 0x10325476;
-  this.chain_[4] = 0xc3d2e1f0;
-
-  this.inbuf_ = 0;
-  this.total_ = 0;
-};
+    inbuf_ = 0;
+    total_ = 0;
+  }
 
+  /**
+   * Internal helper performing 32 bit left rotate.
+   * @param {number} w 32-bit integer to rotate.
+   * @param {number} r Bits to rotate left by.
+   * @return {number} w rotated left by r bits.
+   * @private
+   */
+  function rotl_(w, r) {
+    return ((w << r) | (w >>> (32 - r))) & 0xffffffff;
+  }
 
-/**
- * Internal helper performing 32 bit left rotate.
- * @param {number} w 32-bit integer to rotate.
- * @param {number} r Bits to rotate left by.
- * @return {number} w rotated left by r bits.
- * @private
- */
-goog.crypt.Sha1.prototype.rotl_ = function(w, r) {
-  return ((w << r) | (w >>> (32 - r))) & 0xffffffff;
-};
+  /**
+   * Internal compress helper function.
+   * @param {Array} buf containing block to compress.
+   * @private
+   */
+  function compress_(buf) {
+    var W = W_;
 
+    // get 16 big endian words
+    for (var i = 0; i < 64; i += 4) {
+      var w = (buf[i] << 24) |
+              (buf[i + 1] << 16) |
+              (buf[i + 2] << 8) |
+              (buf[i + 3]);
+      W[i / 4] = w;
+    }
 
-/**
- * Internal compress helper function.
- * @param {Array} buf containing block to compress.
- * @private
- */
-goog.crypt.Sha1.prototype.compress_ = function(buf) {
-  var W = this.W_;
+    // expand to 80 words
+    for (var i = 16; i < 80; i++) {
+      W[i] = rotl_(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
+    }
 
-  // get 16 big endian words
-  for (var i = 0; i < 64; i += 4) {
-    var w = (buf[i] << 24) |
-            (buf[i + 1] << 16) |
-            (buf[i + 2] << 8) |
-            (buf[i + 3]);
-    W[i / 4] = w;
-  }
-
-  // expand to 80 words
-  for (var i = 16; i < 80; i++) {
-    W[i] = this.rotl_(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
-  }
-
-  var a = this.chain_[0];
-  var b = this.chain_[1];
-  var c = this.chain_[2];
-  var d = this.chain_[3];
-  var e = this.chain_[4];
-  var f, k;
-
-  for (var i = 0; i < 80; i++) {
-    if (i < 40) {
-      if (i < 20) {
-        f = d ^ (b & (c ^ d));
-        k = 0x5a827999;
-      } else {
-        f = b ^ c ^ d;
-        k = 0x6ed9eba1;
-      }
-    } else {
-      if (i < 60) {
-        f = (b & c) | (d & (b | c));
-        k = 0x8f1bbcdc;
+    var a = chain_[0];
+    var b = chain_[1];
+    var c = chain_[2];
+    var d = chain_[3];
+    var e = chain_[4];
+    var f, k;
+
+    for (var i = 0; i < 80; i++) {
+      if (i < 40) {
+        if (i < 20) {
+          f = d ^ (b & (c ^ d));
+          k = 0x5a827999;
+        } else {
+          f = b ^ c ^ d;
+          k = 0x6ed9eba1;
+        }
       } else {
-        f = b ^ c ^ d;
-        k = 0xca62c1d6;
+        if (i < 60) {
+          f = (b & c) | (d & (b | c));
+          k = 0x8f1bbcdc;
+        } else {
+          f = b ^ c ^ d;
+          k = 0xca62c1d6;
+        }
       }
-    }
-
-    var t = (this.rotl_(a, 5) + f + e + k + W[i]) & 0xffffffff;
-    e = d;
-    d = c;
-    c = this.rotl_(b, 30);
-    b = a;
-    a = t;
-  }
-
-  this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;
-  this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;
-  this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;
-  this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;
-  this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;
-};
 
+      var t = (rotl_(a, 5) + f + e + k + W[i]) & 0xffffffff;
+      e = d;
+      d = c;
+      c = rotl_(b, 30);
+      b = a;
+      a = t;
+    }
 
-/**
- * Adds a byte array to internal accumulator.
- * @param {Array.<number>} bytes to add to digest.
- * @param {number=} opt_length is # of bytes to compress.
- */
-goog.crypt.Sha1.prototype.update = function(bytes, opt_length) {
-  if (!opt_length) {
-    opt_length = bytes.length;
+    chain_[0] = (chain_[0] + a) & 0xffffffff;
+    chain_[1] = (chain_[1] + b) & 0xffffffff;
+    chain_[2] = (chain_[2] + c) & 0xffffffff;
+    chain_[3] = (chain_[3] + d) & 0xffffffff;
+    chain_[4] = (chain_[4] + e) & 0xffffffff;
   }
 
-  var n = 0;
-
-  // Optimize for 64 byte chunks at 64 byte boundaries.
-  if (this.inbuf_ == 0) {
-    while (n + 64 < opt_length) {
-      this.compress_(bytes.slice(n, n + 64));
-      n += 64;
-      this.total_ += 64;
+  /**
+   * Adds a byte array to internal accumulator.
+   * @param {Array.<number>} bytes to add to digest.
+   * @param {number=} opt_length is # of bytes to compress.
+   */
+  function update(bytes, opt_length) {
+    if (!opt_length) {
+      opt_length = bytes.length;
     }
-  }
-
-  while (n < opt_length) {
-    this.buf_[this.inbuf_++] = bytes[n++];
-    this.total_++;
 
-    if (this.inbuf_ == 64) {
-      this.inbuf_ = 0;
-      this.compress_(this.buf_);
+    var n = 0;
 
-      // Pick up 64 byte chunks.
+    // Optimize for 64 byte chunks at 64 byte boundaries.
+    if (inbuf_ == 0) {
       while (n + 64 < opt_length) {
-        this.compress_(bytes.slice(n, n + 64));
+        compress_(bytes.slice(n, n + 64));
         n += 64;
-        this.total_ += 64;
+        total_ += 64;
       }
     }
-  }
-};
-
 
-/**
- * @return {Array} byte[20] containing finalized hash.
- */
-goog.crypt.Sha1.prototype.digest = function() {
-  var digest = [];
-  var totalBits = this.total_ * 8;
-
-  // Add pad 0x80 0x00*.
-  if (this.inbuf_ < 56) {
-    this.update(this.pad_, 56 - this.inbuf_);
-  } else {
-    this.update(this.pad_, 64 - (this.inbuf_ - 56));
+    while (n < opt_length) {
+      buf_[inbuf_++] = bytes[n++];
+      total_++;
+
+      if (inbuf_ == 64) {
+        inbuf_ = 0;
+        compress_(buf_);
+
+        // Pick up 64 byte chunks.
+        while (n + 64 < opt_length) {
+          compress_(bytes.slice(n, n + 64));
+          n += 64;
+          total_ += 64;
+        }
+      }
+    }
   }
 
-  // Add # bits.
-  for (var i = 63; i >= 56; i--) {
-    this.buf_[i] = totalBits & 255;
-    totalBits >>>= 8;
-  }
+  /**
+   * @return {Array} byte[20] containing finalized hash.
+   */
+  function digest() {
+    var digest = [];
+    var totalBits = total_ * 8;
+
+    // Add pad 0x80 0x00*.
+    if (inbuf_ < 56) {
+      update(pad_, 56 - inbuf_);
+    } else {
+      update(pad_, 64 - (inbuf_ - 56));
+    }
+
+    // Add # bits.
+    for (var i = 63; i >= 56; i--) {
+      buf_[i] = totalBits & 255;
+      totalBits >>>= 8;
+    }
 
-  this.compress_(this.buf_);
+    compress_(buf_);
 
-  var n = 0;
-  for (var i = 0; i < 5; i++) {
-    for (var j = 24; j >= 0; j -= 8) {
-      digest[n++] = (this.chain_[i] >> j) & 255;
+    var n = 0;
+    for (var i = 0; i < 5; i++) {
+      for (var j = 24; j >= 0; j -= 8) {
+        digest[n++] = (chain_[i] >> j) & 255;
+      }
     }
+
+    return digest;
   }
 
-  return digest;
-};
+  reset();
+
+  return {
+    reset: reset,
+    update: update,
+    digest: digest
+  };
+});