Java 如何从没有长度约束的字符串生成多个具有长度约束的随机字符串?
在基于java的分布式系统中,我需要从根字符串s_I创建多个随机(尽可能多的)字符串{x_I}。同时,我还需要验证字符串{x_I}是否是从s_I生成的,而不是其他根字符串。每个x_i是固定长度,s_i的长度是可变的Java 如何从没有长度约束的字符串生成多个具有长度约束的随机字符串?,java,algorithm,encryption,hash,distributed-system,Java,Algorithm,Encryption,Hash,Distributed System,在基于java的分布式系统中,我需要从根字符串s_I创建多个随机(尽可能多的)字符串{x_I}。同时,我还需要验证字符串{x_I}是否是从s_I生成的,而不是其他根字符串。每个x_i是固定长度,s_i的长度是可变的 我怎样才能做到这一点?期待你的帮助 您不提供任何约束,因此一个选项是生成一个随机字符串,然后附加该字符串和根字符串的哈希 例如: 基本字符串(s_i):FooBar 随机基64字符串(r_i):(b28DGWIjI5/NeQrw5RBI9KXZ) Hash[s|i | r|i]:=H
我怎样才能做到这一点?期待你的帮助 您不提供任何约束,因此一个选项是生成一个随机字符串,然后附加该字符串和根字符串的哈希 例如:
FooBar
b28DGWIjI5/NeQrw5RBI9KXZ
)Hash[s|i | r|i]
:=Hash[FooBarb28DGWIjI5/NeQrw5RBI9KXZ
]
=3KGuDze1
[s|i|Hash]
(x|i):[b28DGWIjI5/NeQrw5RBI9KXZ | 3KGuDze1
]=b28DGWIjI5/NeQrw5RBI9KXZ3KGuDze1
FooBar
b28DGWIjI5/NeQrw5RBI9KXZ3KGuDze1
=[b28DGWIjI5/NeQrw5RBI9KXZ | 3KGuDze1
]Hash[FoorBarb28DGWIjI5/NeQrw5RBI9KXZ]
=3KGuDze1
public class RandomStringGenerator {
private final int randomLength;
private final int hashLength;
private final MessageDigest hasher;
public RandomStringGenerator(int randomLength, int hashLength, MessageDigest hasher) {
this.randomLength = randomLength;
this.hashLength = hashLength;
this.hasher = hasher;
}
public String generate(String base) {
// the multiplier accounts for the base-64 conversion
byte[] rand = new byte[randomLength * 3 / 4];
ThreadLocalRandom.current().nextBytes(rand);
Base64.Encoder base64 = Base64.getEncoder();
byte[] front = base64.encode(rand);
hasher.update(base.getBytes(StandardCharsets.UTF_8));
hasher.update(front);
CharSequence hash = base64.encodeToString(hasher.digest()).subSequence(0, hashLength);
return new String(front, StandardCharsets.UTF_8) + hash;
}
public boolean validate(String base, String random) {
int totalLength = randomLength + hashLength;
if (random.length() != totalLength)
return false;
String front = random.substring(0, randomLength);
String hash = random.substring(randomLength);
hasher.update(base.getBytes(StandardCharsets.UTF_8));
hasher.update(front.getBytes(StandardCharsets.UTF_8));
String calculatedHash = Base64.getEncoder().encodeToString(hasher.digest());
return calculatedHash.startsWith(hash);
}
public static void main(String[] args) throws NoSuchAlgorithmException {
MessageDigest hasher = MessageDigest.getInstance("Sha-256");
RandomStringGenerator gen = new RandomStringGenerator(24, 8, hasher);
String generated = gen.generate("FooBar");
System.out.println(generated);
boolean isValid = gen.validate("FooBar", generated);
System.out.println("isValid: " + isValid);
}
}
我没有得到验证部分。据我所知,给定
x_I
和s_I
无法确保x_I
不是来自其他根字符串。随机字符串和可验证的if is from root对我来说似乎是不可能的。要么存在某种模式,因此您可以计算它是否来自同一根,要么字符串是随机的。@maraca我不同意!请参阅我的答案:一个看似随机的数字,可验证来自根字符串。@MichaelDeardeuff我认为您只是将根和随机字符串连接起来(使用唯一分隔符可能是最好的方法)。否则可能会发生冲突,不仅仅是因为散列。例如,(A,BCD),(AB,CD),(ABC,D)在串联后都给出相同的字符串。在我看来,将根和随机字符串连接起来并不是真正的随机,即使在哈希或加密之后也是如此。@maraca首先,是的,这仍然可以通过将根长度包含到哈希中来改进。其次,好的散列函数与随机函数是无法区分的。