org.cryptomator.cryptolib.common.ReseedingSecureRandom Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cryptolib Show documentation
Show all versions of cryptolib Show documentation
This library contains all cryptographic functions that are used by Cryptomator.
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE.txt.
*
* Contributors:
* Sebastian Stenzel - initial API and implementation
*******************************************************************************/
package org.cryptomator.cryptolib.common;
import java.security.Provider;
import java.security.SecureRandom;
import java.security.SecureRandomSpi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Wraps a fast CSPRNG, which gets reseeded automatically after a certain amount of bytes has been generated.
*
*
* Java 8 Example:
*
*
* try {
* // NIST SP 800-90A Rev 1 (http://dx.doi.org/10.6028/NIST.SP.800-90Ar1) suggests 440 seed bits for up to 2^48 bytes between reseeds for SHA1/SHA2 PRNGs:
* return new ReseedingSecureRandom(SecureRandom.getInstanceStrong(), SecureRandom.getInstance("SHA1PRNG"), 1 << 30, 55);
* } catch (NoSuchAlgorithmException e) {
* throw new IllegalStateException("Used RNGs must exist in every Java platform.", e);
* }
*
*/
class ReseedingSecureRandom extends SecureRandom {
private static final Logger LOG = LoggerFactory.getLogger(ReseedingSecureRandom.class);
private static final Provider PROVIDER = new ReseedingSecureRandomProvider();
/**
* @param seeder RNG for high-quality random numbers. E.g. SecureRandom.getInstanceStrong()
in Java 8 environments.
* @param csprng A fast csprng implementation, such as SHA1PRNG
, that will be wrapped by this instance.
* @param reseedAfter How many bytes can be read from the csprng
, before a new seed will be generated.
* @param seedLength Number of bytes generated by seeder
in order to seed csprng
.
*/
public ReseedingSecureRandom(SecureRandom seeder, SecureRandom csprng, long reseedAfter, int seedLength) {
super(new ReseedingSecureRandomSpi(seeder, csprng, reseedAfter, seedLength), PROVIDER);
}
private static class ReseedingSecureRandomProvider extends Provider {
protected ReseedingSecureRandomProvider() {
super("ReseedingSecureRandomProvider", 1.0, "Provides ReseedingSecureRandom");
}
}
private static class ReseedingSecureRandomSpi extends SecureRandomSpi {
private final SecureRandom seeder, csprng;
private final long reseedAfter;
private final int seedLength;
private long counter;
public ReseedingSecureRandomSpi(SecureRandom seeder, SecureRandom csprng, long reseedAfter, int seedLength) {
this.seeder = seeder;
this.csprng = csprng;
this.reseedAfter = reseedAfter;
this.seedLength = seedLength;
this.counter = reseedAfter; // trigger reseed during first "engineNextBytes(...)"
}
@Override
protected void engineSetSeed(byte[] seed) {
csprng.setSeed(seed);
}
@Override
protected void engineNextBytes(byte[] bytes) {
if (counter + bytes.length > reseedAfter) {
reseed();
}
counter += bytes.length;
csprng.nextBytes(bytes);
}
@Override
protected byte[] engineGenerateSeed(int numBytes) {
try {
LOG.info("Seeding CSPRNG with {} bytes...", numBytes);
return seeder.generateSeed(numBytes);
} finally {
LOG.info("Seeded CSPRNG.");
}
}
private void reseed() {
engineSetSeed(engineGenerateSeed(seedLength));
counter = 0;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy