views:

109

answers:

2

(N.B.: Yes, this is a ridiculous question, and I will be entirely unsurprised if the answer to this question is "no". That said:)

I've written an XSLT stylesheet which deliberately performs a lengthy, unparallelizable computation on an XML fragment. It's intended as a component of a proof-of-work system to be used in a web browser as a sort of CAPTCHA that doesn't require any input from the user -- the result of the computation gets submitted as a hidden form element when the user POSTs data to the server. The form contents are only accepted if the computed value is correct. (The computation is structured in such a way that the server can cheaply provide the user with input parameters to a function, and the server knows the result without having to do a lot of work, but the user's machine has to spend cycles to determine the result.)

The transformation works just fine, but unfortunately hangs the browser while the computation is going on. Since my goal is to have this computation running while the user continues to use the browser, this is unacceptably annoying behaviour. Is there a way to background the transformation and leave the browser usable while it runs? One thought I had was to load the source XML fragment from an iframe, but I haven't been able to get the transform to work at all using this approach. I figured I'd ask here to see if anyone has any brilliant ideas before beating my head against this much further -- if I'm trying to do something that's fundamentally impossible given the way browsers work, it would be nice to know.

I know I could do this in Javascript, but it would be nice not to have to. Any ideas?

EDIT: Guys, I know about recaptcha.net and other alternatives. This is an experiment. My goal is to find out whether a theoretical idea can be reduced to practice in a way that isn't too onerous for the user. I'm not looking for alternative implementations, I'm looking for a way to do a cryptographically strong CAPTCHA that doesn't involve Javascript. (If I wanted to use Javascript, I'd use one of the Javascript hashcash implementations.) The only other browser-based Turing-complete language out there is XSLT. Please consider the question in the spirit in which it was asked.

+2  A: 

You won't be able to perform a XSLT transformation after the page is loaded and use its result in a form in the same page without Javascript. I don't know why your IFrame solution doesn't work, but even if it did, you would still need Javascript to import the result into the page's form.

My advice would be to use a small and fast Javascript-based system and fallback to reCAPTCHA if Javascript is disabled. You don't need to make the Proof-of-work CPU-intensive, any custom solution will throw off the very large majority (if not all) of spambots out there.

For example, your page could contain something like

<input type="hidden" name="a" value="123" />
<input type="hidden" name="b" value="456" />
<input type="hidden" name="c" />

and set the value of c to (a+b) in Javascript. Bot-makers would need to adapt their bots specifically to your site in order to solve that extremely simple CAPTCHA. And if they do (which they won't) then add a new field which will define what kind of operation to perform on a and b to get c. And if they adapt again, change the name of the fields. In all likelyhood, they won't adapt unless your site happens to be in Alexa's top 10.

Josh Davis
+1 for applying common sense.
Tomalak
+1  A: 

I use xslt in an iframe, and it works just fine - there's probably some unrelated issue you're running into.

If you wish the machine to submit a particular value without user interaction and without javascript, consider using using meta refresh:

  1. Include a small, hidden iframe on the webpage which points to an url getting your xml file which includes a stylesheet processing directive to your xslt computation engine
  2. Engineer the xslt file such that the output generates a redirect to a URL with the computation token encoded in the url; i.e. compute the url:

    <meta http-equiv="refresh" content="0;url=http://xyz.abc/captcha?......">

Where the ellided section contains your token. That should, in principle, work.

On the other hand, I seriously doubt that xslt is very useful for something like this. Browsers may abort the computation if it takes long; even in an iframe you may get blocking behavior, on single core systems even non-blocking behaviour may effectively be blocking, differences in XSLT engines are such that you'd be hard-pressed to find a transformation that every engine executes fast enough but none blaze through almost instantly.

I don't think javascript would be very good for this, and XSLT is probably even less appropriate. If you really want such computation, silverlight may be a better bet - at least there you can write code that executes everywhere reasonably quickly but that no future engine could ever trivialize (it's close enough to native speed that you should be able to write code that is fairly close to optimal for a cpu - certainly you can come within a factor 10, which probably can't be said for javascript/XSLT).

Eamon Nerbonne
I hadn't thought about the refresh idea, thanks! That actually gives me some more flexibility in terms of computing a nonce. I appreciate the iframe data point, too -- it's good to know that it's just me doing something wrong. <:) Back to the salt mines.
Meredith L. Patterson
It's neat that actually, finally, it-just-took-9-years, all major browsers support in-browser xslt: FF3.5, IE8, Chrome 3, Safari 4, Opera 9: everything finally supports it, making it a feasible choice even on a public site.
Eamon Nerbonne