Last active
September 2, 2025 19:11
-
-
Save kristoffer-paulsson/15d7123155e97ed9874fa129893ea291 to your computer and use it in GitHub Desktop.
JitterEntropy is a Java class that generates 128 bytes of fully unpredictable entropy using only nanosecond time jitter differences, with no external sources. It produces an array of random bytes via getEntropy(), designed to resist prediction, under the MIT license.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Copyright (c) 2025 by Kristoffer Paulsson <[email protected]>. | |
| * | |
| * This software is available under the terms of the MIT license. Parts are licensed | |
| * under different terms if stated. The legal terms are attached to the LICENSE file | |
| * and are made available on: | |
| * | |
| * https://opensource.org/licenses/MIT | |
| * | |
| * SPDX-License-Identifier: MIT | |
| * | |
| * Contributors: | |
| * Kristoffer Paulsson - initial implementation | |
| */ | |
| package com.example; | |
| /** | |
| * A class that generates unpredictable entropy bytes based on timing differences | |
| * in system operations, designed to provide a source of randomness resistant to | |
| * prediction. The entropy is derived from system timing jitter and processed | |
| * through a mixing function to produce a fixed-size output. | |
| * | |
| * @author Kristoffer Paulsson | |
| */ | |
| public class JitterEntropy { | |
| /** | |
| * Indicates whether the entropy source is designed to resist prediction. This | |
| * field is always set to {@code true}, indicating that the generated bytes are | |
| * intended to be unpredictable based on timing differences. | |
| */ | |
| public final boolean isPredictionResistant = true; | |
| /** | |
| * Generates entropy bytes using system timing jitter. The method measures | |
| * timing differences via {@link System#nanoTime()} and processes them through | |
| * a mixing function to produce a fixed-size array of entropy bytes. | |
| * | |
| * @return a {@link Blob} containing 128 bytes (1024 bits) of entropy | |
| */ | |
| public byte[] getEntropy() { | |
| int entropySize = getEntropySize(); | |
| long startTime = System.nanoTime(); | |
| long entropy = mix(startTime); | |
| byte[] result = new byte[entropySize]; // 1024 bits | |
| for (int i = 0; i < entropySize; i++) { | |
| entropy = (Long.rotateLeft(entropy, 8) ^ (System.nanoTime() - startTime)); | |
| entropy = mix(entropy); | |
| result[i] = (byte) entropy; | |
| } | |
| return result; | |
| } | |
| /** | |
| * Mixes the provided entropy value to enhance randomness. The method applies a | |
| * series of bitwise operations, including XOR, left shift, and right shift, | |
| * based on a variable number of loops determined by the input entropy. A | |
| * constant is also XORed to further scramble the output. | |
| * | |
| * @param entropy the long value to be mixed | |
| * @return the mixed entropy value | |
| */ | |
| private long mix(long entropy) { | |
| int loops = (int) entropy % 8; | |
| for (int j = 0; j < loops; j++) { | |
| entropy ^= ((entropy + j) << 13) ^ (-entropy >>> 17); | |
| } | |
| entropy ^= 0x3569356935693569L; | |
| return entropy; | |
| } | |
| /** | |
| * Returns the size of the entropy output in bytes. This implementation returns | |
| * 128, corresponding to a 1024-bit output. | |
| * | |
| * @return the size of the entropy output, in bytes (128) | |
| */ | |
| public int getEntropySize() { | |
| return 128; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment