java种子数据在哪层_关于Java:有没有办法从一系列数字中生成种子?

例如,如果Java产生伪随机序列:9 3,2,5,6。用23作为种子,我该怎么做呢?即从序列9 3 2 5 6中取出23。

或者如何为某个序列分配种子?

如果有一个数据库,很容易做到-只需为序列分配一个随机键

INSERT INTO SEQUENCE_TABLE VALUES (RANDOM_KEY, SEQUENCE)

但是,如果不允许我使用数据库,有没有一个公式可以做这样的事情?

据我所知,不可能从输出中确定种子,除非事先有一个每个可能的种子/序列对的查找表。你的用例是什么?可能有比试图逆转Java的PRNG更优雅的解决方案。

我只需要为一系列唯一的数字分配一个键,但是这个键也必须是短的。密钥只是表示序列的一种简短方式,比如Java中的种子来表示伪随机数序列。

我只是想用Java的种子和随机函数来再生我独特的数字序列。如果有更简单的方法,希望你能提出建议并感谢你。

我不确定你到底想达到什么目的。你能详细阐述一下你的问题吗?您将收到哪些输入,您需要生成什么?

您将:(1)根据RNG算法的需求生成一个种子。(2)将该种子与一个序列(或数字的子序列,包括起始位置)一起保存在数据库中;(3)根据需要通过使用相同的值重新播种来复制流。如果您试图反向工程RNG输出,请参阅下面的答案。

随机数生成器的要点是这是不可能的。SecureRandom在密码学上特别强大,但一般来说,如果您正在编写一个随机数生成器,而这是可能的或很容易的,那么您就错了。

也就是说,Java内置的随机类很可能是不可能的。(不过,SecureRandom是另一回事。)但它需要惊人的数学运算量。

更具体一点:如果存在一个多项式时间算法来做你想做的事情,对于某个特定的伪随机数生成器,那么根据定义,它将无法通过链接的维基百科文章中描述的"下一位测试",因为你可以预测将要生成的下一个元素。

事实上,java.util.random并不重要,请看我的文章。

是的,逆向设计一个设计不好的伪随机数发生器的数字流是绝对容易的,例如Java编程语言中的线性同余PRNG实现(EDOCX1,1)。

事实上,只有来自特定生成器的两个值,以及这些值出现的顺序信息,就可以预测整个流。

Random random = new Random();

long v1 = random.nextInt();

long v2 = random.nextInt();

for (int i = 0; i < 65536; i++) {

long seed = v1 * 65536 + i;

if (((seed * multiplier + addend) & mask) >>> 16) == v2) {

System.out.println("Seed found:" + seed);

break;

}

}

这正是为什么使用密码安全的随机数生成器非常关键的原因,这些生成器已经被社区广泛审查,用于需要安全性的实现。

这里有更多关于逆向工程的信息,包括java.util.Random。…

PS,这不应该被用作体系结构特性。我只是把这个贴在这里让大家知道。

当然可以恢复java.util.random使用的种子。这篇文章描述了Random线性同余公式背后的数学原理,这里有一个函数可以从nextint()返回的最后两个整数中发现当前种子。

public static long getCurrentSeed(int i1, int i2) {

final long multiplier = 0x5DEECE66DL;

final long inv_mult = 0xDFE05BCB1365L;

final long increment = 0xBL;

final long mask = ((1L << 48) - 1);

long suffix = 0L;

long lastSeed;

long currSeed;

int lastInt;

for (long i=0; i < (1<<16); i++) {

suffix = i;

currSeed = ((long)i2 << 16) | suffix;

lastSeed = ((currSeed - increment) * inv_mult) & mask;

lastInt = (int)(lastSeed >>> 16);

if (lastInt == i1) {

/* We've found the current seed, need to roll back 2 seeds */

currSeed = lastSeed;

lastSeed = ((currSeed - increment) * inv_mult) & mask;

return  lastSeed ^ multiplier;

}

}

/* Error, current seed not found */

System.err.println("current seed not found");

return 0;

}

此函数返回一个值,该值可与rand.setseed()一起使用,生成以i1和i2开头的伪随机数字序列。

您想取任意的数字序列,然后确定一个短的(固定长度?)允许您重新生成该数字序列而不存储原始序列的键?不幸的是,你想要的在技术上是不可能的。这就是为什么:

这是压缩的一种特殊情况。您有一个很长的数据序列,您希望能够从一个较小的信息片段中重新创建无损的数据序列。如果您请求的是可能的,那么我可以将整个堆栈溢出压缩为一个整数(因为整个网站可以序列化为一个数字序列,尽管这个序列非常长!)

不幸的是,数学不是这样的。任何给定的序列都有一个特定的熵度量——该序列的平均复杂性。为了无损地重现这个序列,您必须能够编码至少足够的信息来表示它的熵。

对于某些序列,可能实际上有一个种子能够生成一个长的、特定的序列,但这仅仅是因为有一个硬编码的数学函数,它接受该种子并生成一个特定的数字序列。但是,要获取任意值序列并生成这样的种子,您需要一个种子,以及一个能够从该种子生成该序列的函数。为了对这两样东西进行编码,你会发现你得到的数据比预期的要多得多!

这是完全错误的。CSPRNGS和PRNGS之间存在差异,而CSPRNGS的设计正是为了避免这种困境。一旦已知RNG的初始种子(按照RNG周期的顺序,或者对于设计不好的算法来说,小于等于RNG周期的顺序),序列中的所有数字都是确定已知的。en.wikipedia.org/wiki/random_number_generator_攻击

@嗯,我想你可能还没有读完整的原始问题。作者不是在问他是否能从一个序列中产生数字,如果他知道密钥,他是在问是否有一种方法(不列举每一个可能的选项)来识别一个数字密钥可以无损地产生任何随机的数字序列。

如果您可以使用String作为种子,则可以使用:

String seed ="9 3 2 5 6";

然后你的发电机看起来像:

String[] numbers = seed.split("");

如果你真的想在Java中逆向设计"随机数"生成器,那将是非常困难的(我想)。

如果可以的话,最好换一种方式来做:从种子开始,产生序列,然后从那里开始计算。

我也想过这样做,但是,如果序列太长,这将是一个问题。谢谢你的建议

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值