【问题标题】:From a string without length constraint, How to generate multiple random strings with length constraint?从没有长度限制的字符串,如何生成多个有长度限制的随机字符串?
【发布时间】:2017-11-12 06:13:01
【问题描述】:

在基于 java 的分布式系统中,我需要从根字符串 s_i 创建多个随机(尽可能多)字符串 {x_i}。同时,我还需要验证字符串 {x_i} 是否是从 s_i 生成的,而不是其他根字符串。每个 x_i 的长度是固定的,而 s_i 的长度是可变的。

我怎样才能做到这一点?期待您的帮助。

【问题讨论】:

  • 我没有得到验证部分。据我所知,鉴于x_i 和s_i,无法确保x_i 不是来自其他根字符串。
  • 随机字符串和可验证是否来自根对我来说似乎是不可能的。要么有一些模式,所以你可以评估它是否来自同一个根,或者字符串是随机的。
  • @maraca 我不敢苟同!看我的答案:一个看似随机的数字,可验证来自根字符串。
  • @MichaelDeardeuff 我认为您只是将根和随机字符串连接起来(这可能是使用唯一分隔符可以获得的最佳效果)。否则可能会发生冲突,不仅仅是因为哈希。例如。 (A, BCD), (AB, CD), (ABC, D) 在连接后都给出相同的字符串。在我看来,连接根和随机字符串并不是真正随机的,即使在散列或加密之后也是如此。
  • @maraca 首先,是的,这仍然可以通过将根长度包含到哈希中来改进。其次,一个好的散列函数与随机是没有区别的。

标签: java algorithm encryption hash distributed-system


【解决方案1】:

您没有给出任何约束,因此一种选择是生成一个随机字符串,然后附加该字符串和根字符串的哈希值。

例如:

  1. 基本字符串(s_i):FooBar
  2. 随机 base 64 字符串 (r_i): (b28DGWIjI5/NeQrw5RBI9KXZ)
  3. Hash[s_i || r_i]: = Hash[FooBarb28DGWIjI5/NeQrw5RBI9KXZ] = 3KGuDze1
  4. 结果 = [s_i || Hash] (x_i): [b28DGWIjI5/NeQrw5RBI9KXZ || 3KGuDze1] = b28DGWIjI5/NeQrw5RBI9KXZ3KGuDze1

由于哈希是固定长度的,你可以把它拉到最后来验证它是否来自FooBar:

  1. 基本字符串 (s_i):FooBar
  2. 随机字符串:b28DGWIjI5/NeQrw5RBI9KXZ3KGuDze1 = [b28DGWIjI5/NeQrw5RBI9KXZ || 3KGuDze1]
  3. 断言Hash[FoorBarb28DGWIjI5/NeQrw5RBI9KXZ] === 3KGuDze1

注意:在上面的示例中,我使用 base64 编码的 Sha256 的前 8 位作为哈希函数。

这是系统的初稿。如果是我的系统(大型分布式系统),我会删除所有的字符串转换。

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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    相关资源
    最近更新 更多