
Java Puzzle: Square Root - crazybob
http://corner.squareup.com/2013/03/puzzle-square-root.html
======
cromwellian
Consider that SecureRandom is really a facade around multiple providers that
can plug in varying implementations. :)

~~~
raylu
SquareRoot.n is static, so it runs before any code in your main().

~~~
cromwellian
Java Service Providers (SPI) trigger before main() is run. You can create a
SecureRandom() provider, add it to the classpath with SPI, removing other
providers.

------
uvdiv
Force a race condition on the variable `root'.

    
    
        if (n.divide(root).equals(root)) {
    

Try to set it to 2^20001 on the first funcall and 0 on the second.

~~~
mtpettyp
BigInteger is immutable so this won't work

~~~
uvdiv
You're right! Good catch.

------
powera
I'm not sure this is interesting. Unless I'm missing something, the question
is "find what way of breaking the compartmentalization of the JVM we haven't
forbidden in these English-language rules".

~~~
craigching
Yes, I believe you and cromwellian have hit upon the main point. Or, to be
more succinct, "do you know about Java spi."

------
IvyMike
I'm surprised nobody's given the obvious algorithm yet: while(i <
BigInt(2).pow(10000)) ++i;

Before anyone complains, this algorithm is correct and does not break any of
the rules as far as I can tell. :)

I think the timing attack is probably what he's really looking for.

Edit: as mattvanhorn pointed out, answer() is void, but that's ok... changed
to a "constant time" algorithm. :)

~~~
lancefisher
The BigInteger is really big.

An i7 does about 109 gigaFLOPS, or 109 operations per nanosecond. [1]

Suppose we can do 1 guess per operation. There are 2^10,000 possible roots.
[2]

2^10,000 / 109 nanoseconds is 5.804×10^2991 years. [3]

The stars will burn out before you brute force it.

[1] <http://en.wikipedia.org/wiki/FLOPS>

[2] <http://bit.ly/ZIWkkt> (parens in the original link)

[3]
[http://www.wolframalpha.com/input/?i=2%5E10%2C000+%2F+109+na...](http://www.wolframalpha.com/input/?i=2%5E10%2C000+%2F+109+nanoseconds+in+years)

~~~
IvyMike
I must dryly point out that this does not invalidate the correctness of the
algorithm.

------
somethingnew
Someone should just modify the StackSort algorithm that was posted yesterday
(made up by xkcd) to search for Square Root functions instead and run them.

<http://gkoberger.github.com/stacksort/>

~~~
sumzup
That won't work. The point here is that you don't have the number available.

------
itsdrewmiller
Not really a Java guy, but could you subclass BigInteger in such a way that
when .divide is called and accesses root's representation of the data, that
property access reflectively examines the calling expression to find out n's
representation of the data, then just square roots that and sets it as its own
representation before allowing the expression to evaluate? Or something along
those lines, anyway?

------
asabil
Maybe read /proc/self/maps and /proc/self/mem and try to locate the BigInteger
value in the JVM heap?

------
tantalor
I'd start by trying to create an evil subclass of BigInteger, as it is not a
final class.

~~~
raylu
I've tried this but failed to create something that was evil enough to pass on
.equals but benign enough that it didn't choke on .divide

------
wheaties
I hate to break it to you but "n" is not final. Hence, you can reassign any
BigInteger to it. Why not just set n = 9 and the root = 3...

Immutability is your friend. Use it or lose it.

~~~
craigching
But n is also private, so you can't reassign it without using setAccessible or
changing the security manager, both forbidden by the rules.

------
TallboyOne
Can someone explain what this is asking? I don't know java

~~~
Semaphor
There is a really big number you don't know. You should get the square root
for it.

~~~
TallboyOne
So why are people talking about vulnerabilities and 'timing attacks' then? and
how are you supposed to get the square root of a number you dont know..

~~~
craigching
You don't need to use timing attacks or other vulnerabilities. Others have
pointed out how to do it, use SPI and provide your own implementation. The
xkcd post is probably the best hint ;)

------
Eduard
1: Pause debugging session. 2: Look into SquareRoot.n

------
mingpan
Are they asking for a timing attack, then?

------
huherto
I think you can create a new instance of SecureRandom() that provides the same
value that we are looking for.

------
doctorpangloss
Hint: Many pseudo-random number generators take the square of a seed value to
advance to the next sequence.

------
mcgin
Presumably something from the java.lang.instrument package will allow you to
solve this

------
web007
Subclass BigInteger, and override equals() on your subclass to "return true;"?

~~~
raylu
equals() isn't being called on your class; it's being called on the result of
n.divide()

~~~
web007
I don't know Java, clearly, as I don't even know what to name a file that's
going to do the override. Also, as mentioned elsewhere, SecureRandom seems the
easier target as it's a pluggable interface for entropy providers.

That said, can't you override the equals() for your subtype? I'm talking about
the implementation of BigInteger::equals(MyBigInt x), not
MyBigInt::equals(BigInteger x). Or does that need to be done on BigInteger-
proper, versus its subclass?

~~~
raylu
You can override the .equals() for your subtype but look at the check:

    
    
        if (n.divide(root).equals(root)) {
    

It never calls root.equals(). It calls .equals() on the result of the
.divide(), which is a standard java.math.BigInteger.

------
jlebar
Use reflection to read n. Reflection lets you bypass |private|.

~~~
GhotiFish
that should throw an exception with the security manager on. I think. I might
of read the docs wrong.

~~~
jlebar
Ahh, I see.

------
wisesascha
is using the ASM library not a legitimate way or would that violate the rules
in some way?

~~~
mtpettyp
I read "Solve the problem in a single separate .java file which compiles and
runs with JDK 6 or 7." to mean that the entire solution has to be in one Java
file.

------
uribs
The only possibilities seem to be a timing attack, exploiting a bug or taking
advantage of an implementation that puts the dividend value in the exception
when dividing by zero.

I'm not sure anyone will bother writing the timing attack since he apparently
gives out no prize.

~~~
ISL
Unless there's something in Java that allows you to manipulate private copies
of private variables without access to the stored values.

I'm familiar with Java, but not so familiar that I can state with authority
that such a thing is impossible.

------
martinced
Is this just like String that are actually mutable on most JVM implementations
out there where the underlying char[] can be accessed using reflection?

