diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceImpl.java b/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceImpl.java index 40056b37..8c64eb39 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceImpl.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceImpl.java @@ -50,9 +50,6 @@ public class SearchServiceImpl implements SearchService { @Autowired private SearchServiceUtilities util; - // TODO Should be changed to SecureRandom? - private final Random random = new Random(System.currentTimeMillis()); - @Override public SearchResult search(SearchCriteria criteria, List musicFolders, IndexType indexType) { @@ -108,7 +105,7 @@ public class SearchServiceImpl implements SearchService { List result = new ArrayList<>(); while (!docs.isEmpty() && result.size() < count) { - int randomPos = random.nextInt(docs.size()); + int randomPos = util.nextInt.apply(docs.size()); Document document = searcher.doc(docs.get(randomPos)); id2ListCallBack.accept(result, util.getId.apply(document)); docs.remove(randomPos); diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceUtilities.java b/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceUtilities.java index 7ee6b445..2f22ccd2 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceUtilities.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/search/SearchServiceUtilities.java @@ -31,13 +31,21 @@ import org.airsonic.player.service.MediaFileService; import org.apache.commons.collections4.CollectionUtils; import org.apache.lucene.document.Document; import org.checkerframework.checker.nullness.qual.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.Security; +import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Random; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.stream.Collectors; import static org.springframework.util.ObjectUtils.isEmpty; @@ -71,6 +79,41 @@ public class SearchServiceUtilities { @Autowired private MediaFileService mediaFileService; + private static final Logger LOG = LoggerFactory.getLogger(SearchServiceUtilities.class); + + private Random random; + + private static Random createSecureRandom(String algorithm) { + SecureRandom secureRandom = null; + try { + LOG.debug("{} is used to create a random list of songs.", algorithm); + secureRandom = SecureRandom.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + LOG.error("Usually unreachable.", e); + } + return secureRandom; + } + + { + List algorithms = Arrays.asList(Security.getProviders()).stream() + .flatMap(p -> p.getServices().stream().filter(s -> "SecureRandom".equals(s.getType()))) + .map(s -> s.getAlgorithm()).collect(Collectors.toList()); + + for (String algorithmName : new String[]{"NativePRNG", "SHA1PRNG"}) { + if (algorithms.contains(algorithmName)) { + random = createSecureRandom(algorithmName); + } + } + + if (isEmpty(random)) { + random = new Random(System.currentTimeMillis()); + LOG.debug("NativePRNG and SHA1PRNG cannot be used on this platform."); + } + + } + + public Function nextInt = (range) -> random.nextInt(range); + public final Function round = (i) -> { // return // NumericUtils.floatToSortableInt(i);