逆向工程一个基于随机字符串的Java中Math.random()的数字。

huangapple go评论74阅读模式
英文:

Reverse engineer a number for Math.random() in Java, based on a random string

问题

因此,我在处理一个小问题时有一个问题。

通过任意长度的Java程序生成的随机字符串,例如jdefreq

字符串中的每个字符都是使用以下方式生成的,

final String[] dict = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
            "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ",", ".", "?" };

final int dictIndex = (int)Math.floor(Math.random() * dict.length);

我有一种复制Math.random()的方法,但我需要得到确切的第一个数字,该数字在序列中起始使用。

我目前尝试的方法是获取第一个字符,然后循环使用Math.random(),直到获得一个可以产生与该第一个字符相同索引的数字,但这还不够,因为我只能产生一个类似的数字,而不是完全相同的数字。

所以我来到这里,各位程序员!

是否有人知道我该如何做才能实现这一点?

非常期待听取大家对这个问题的建议和他们的观点


谢谢,祝你有美好的一天!

英文:

So I have a question on a little problem I am working on.

Given a random string generated by a java program of any length e.g. jdefreq.

Each character within the string is generated using,

final String[] dict = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
		"s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ",", ".", "?" };

final int dictIndex = (int)Math.floor(Math.random() * dict.length);

I have a way to replicate Math.random() but I need the exact first number, that is used starting off within the sequence.

The way I have been trying to go about it, right now is take the first character, and loop with Math.random() until I get a number that can reproduce the same index of that first character, but that's not good enough since I only produce a similar number, but not the exact same one.

So I have came here fellow programmers !

Does anybody have any idea how / what I can do to be able to pull this off ?

Really excited to hear people's advice / their POV on the problem !


Thanks and have an awesome day !

答案1

得分: 2

为了深入阐述我的评论:只有 248 种不同的序列可以由 Math.random 生成。这还是相当多的,但并不多到你不能在可思量的时间内尝试所有这些序列。设置如下:

for (long seed = 0; seed < (1L << 48); seed++) {
    Random r = new Random(seed);
    if (generateString(r).equals(desiredString)) return seed;
}

其中 generateString(r) 的生成方式相同,只是使用 r.nextDouble() 替代了 Math.random()

另一种方法是将相关设置编码为满足模理论(SMT),然后将求解器应用于它。由于 Java 的伪随机数生成器是线性同余生成器,不使用除法,所以这部分并不太难。一开始,人们可能会想象我们必须为 Random.nextDouble() 实现浮点算术,但我们可以直接根据 nextDouble() 生成的 53 位整数来推理范围。总的来说,虽然这很繁琐,但相对而言相当直接,因为复杂的算法逻辑被封装在求解器中。

英文:

To expand on my comment: there are only 2<sup>48</sup> distinct sequences that Math.random can produce. That's quite a lot, but not so many that you can't try all of them in a thinkable amount of time. The setup looks like

for (long seed = 0; seed &lt; (1L &lt;&lt; 48); seed++) {
    Random r = new Random(seed);
    if (generateString(r).equals(desiredString)) return seed;
}

where generateString(r) generates strings the same way except using r.nextDouble() instead of Math.random().

Another approach would be to code the relevant setup as a satisfiability modulo theory and then throw a solver at it. Since Java's pseudorandom number generator is a linear congruential generator that doesn't use division, that part isn't too hard. Naively one might imagine that we have to implement floating-point arithmetic for Random.nextDouble(), but we can reason directly about ranges with respect to the 53-bit integer that nextDouble() generates. All in all, this is tedious but relatively straightforward because the complicated algorithm logic is encapsulated in the solver.

huangapple
  • 本文由 发表于 2020年9月19日 20:19:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63968722.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定