あなたは任意の制約を与えないので、ランダムな文字列を生成し、その文字列とルート文字列のハッシュを追加することができます。
- ベースストリング(S_I):
FooBar
- ランダムベース64列(R_iを):例えば
(b28DGWIjI5/NeQrw5RBI9KXZ
)
Hash[s_i || r_i]
:= Hash[FooBarb28DGWIjI5/NeQrw5RBI9KXZ
] = 3KGuDze1
- 結果=
[s_i || Hash]
(x_i):[b28DGWIjI5/NeQrw5RBI9KXZ || 3KGuDze1
] = b28DGWIjI5/NeQrw5RBI9KXZ3KGuDze1
ハッシュが固定長であるため、それはFooBarのから来ているかどうかを確認するために端をそれを引っ張ることができる:
- ベースストリング(S_I):
FooBar
- ランダムな文字列:
b28DGWIjI5/NeQrw5RBI9KXZ3KGuDze1
= [b28DGWIjI5/NeQrw5RBI9KXZ || 3KGuDze1
]
- アサート
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);
}
}
私は検証部分を取得しませんでした。私が見る限りでは、 'x_i'と' s_i'を与えれば、 'x_i'が他のルート文字列から来ていないことを確認する方法がありません。 –
ランダムな文字列で、ルートからのものであるかどうかを確認することは不可能です。どちらかのパターンがあるので、同じルートから来たものか、文字列がランダムであるかを評価することができます。 – maraca
@maraca私は違うことを請う!私の答えを参照してください:一見乱数、ルート文字列から来ることを確認します。 –