0

So I'm trying to make a function that will have a random name generated on page load, but I'm having problems calling the method later. This is what I got so far:

 var methodName = Math.floor(Math.random()*1000001);   
 window[methodName] = function(){
     alert("It works!");
 }
 window.onload = function start() {
     methodName();
 }

But I'm having problems calling it, since methodName(); would actually be a random number. So how could I call the methodName() function?

Gus
  • 15,397
  • 7
  • 25
  • 28
  • How about using the same notation you used to assign the function? –  May 03 '13 at 00:42
  • If you're trying to make a function that can't be found by code loaded later in the page for security reasons, you should know that properties are of `window` are enumerable by default, and JavaScript's PRNG is not crypto-strong. – Mike Samuel May 03 '13 at 00:43
  • @MikeSamuel that's exactly what I'm trying to do. Could you link me to something explaining how to do something like that, please? Got this question solved with the brackets, though. – Gus May 03 '13 at 00:45
  • @Gus: It is completely impossible to enforce security like that. You need to rethink your approach. – SLaks May 03 '13 at 00:46
  • @SLaks, what I'm tring to do actually is make an "unguessable" function name. In this case, though, you could use `window[methodName]()` to get the function name. Should I open another question for it? I'm doing some research already, might find something useful. – Gus May 03 '13 at 00:54
  • @Gus, please see my edit at the bottom of my answer. "unguessable" isn't good enough when something is enumerable, and property names in ES5 are all enumerable even when you tell the interpreter otherwise. – Mike Samuel May 03 '13 at 01:08

2 Answers2

3

You can reference the property the same way that you set it:

window[methodName]();
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
2

If you're trying to make a function that can't be found by code loaded later in the page for security reasons, you should know that properties are of window are enumerable by default, and JavaScript's PRNG is not crypto-strong.


@MikeSamuel that's exactly what I'm trying to do.

If you had a crypto-strong source of randomness then you can use a lock&key approach to make a function that can only be called by someone who knows the secret.

For example,

(function () {
  // Multiple calls to a secure source of randomness could get you more entropy than 64B.
  var key = Math.random() + '/' + Math.random() + '/' + Math.random();

  var sensitiveFunction = function () { alert("Don't leak me"); }

  var slice = [].slice;

  function lock(f) {
    var g = f;
    f = null;  // arguments is widgy and leaky in non-strict mode.
    return function (unlocker, var_args) {
      if (key !== unlocker) { throw new Error(); }
      return g.call(this, slice.apply(arguments, 1));
    };
  }

  myGlobal = lock(sensitiveFunction);
})();

which uses the secret to wrap a function in one whose toString() does not return sensitive code, and which will only be callable by code that can read var key.

Is Math.random() cryptographically secure? discusses some alternatives to Math.random for strong nonces in JavaScript but I don't have personal experience with any of them.

This isn't practically useful unless you can get key out of this closure to code that needs it, so you need to have a secure communication channel to that code. You probably also want to have any script that defines this go through <script> elements and delete their text content from the DOM so that the body of the sensitive function can't be read that way.

I believe some frameworks like waterken use the URL fragment to seed web applications with secrets and then use techniques like this within the page to keep them from prying code.


Note that making properties with unpredictable names un-enumerable does not protect them.

In EcmaScript 5, getOwnPropertyNames does not respect enumerability. The only standardized way to get truly un-enumerable properties is with weak maps and a closely held object token and that will have to wait for EcmaScript 6 to be in an actual spec though browser vendors are implementing a lot of ES6 speculatively.

Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • First of all, thanks for taking your time to write this! Now I have a question, though, would you be able to call the function if you have the source code? For instance, with userscripts? – Gus May 03 '13 at 01:00
  • @Gus, the source code is half of a function. The rest is its environment, which is why `lock` works. Even if you have the source code for `lock`, you don't know the exact value of its free-variables, such as `var key` and the parameter `f`. Old versions of Firefox violated that by allowing `eval` to be called with a second argument that was an environment, but that is widely regarded as a mistake so future extensions which break the inviolability of function scopes are unlikely. If `lock` were reentrant and non strict, then it could leak details via `arguments`, so there is some trickiness. – Mike Samuel May 03 '13 at 01:06