 # Can you extract the seed from randomly generated perlin noise?

Can you get the seed from a randomly generated perlin noise graph?

please check the reference, noise can be initialised with a value that you choose.

https://p5js.org/reference/#/p5/noise

Thanks. That wasn’t my question.

Can you extract a seed from a perlin noise graph you did not initialize a seed for?

Thanks.

In theory, this might be possible. Perlin noise is based on a continuous/smooth interpolation of values between randomly generated vectors at discreet intervals, and in p5.js that field of vectors is generated using a Linear congruential generator. LCGs are not cryptographically secure (which is to say that it is not necessarily difficult to reverse engineer the seed, or key from a sequence of output values). Here is a blog post about finding a LCG seed that produces a specific output. I read over the source code for the noise function and it looks like this should be feasible assuming you can explicitly set the noiseDetail and get the output from `noise(0, 0, 0)`:

``````// p5.js LCG constants
// m is basically chosen to be large (as it is the max period)
// and for its relationships to a and c
const m = 4294967296;
// a - 1 should be divisible by m's prime factors
const a = 1664525;
// c and m should be co-prime
const c = 1013904223;

// p5.js perlin constants
const PERLIN_YWRAP = 16;
const PERLIN_ZWRAP = 256;

function setup() {
createCanvas(400, 400);
noLoop();

noiseSeed(2701);
noiseDetail(1);
print(`Actual noise(0, 0, 0): \${noise(0, 0, 0)}`);

let lcgInt0 = (a * 2701 + c) % m;
print(`Expected lcg0: \${lcgInt0}`);
let lcgVal0 = lcgInt0 / m;

let n1 = lcgVal0; // perlin[of & PERLIN_SIZE];
/*
// copy and pasted from noise.js
// All of these terms go to 0 and so they have no impact on the output of noise(0,0,0)
n1 += 0; // rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1);
let n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
n2 += 0; // rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2);
n1 += 0; // ryf * (n2 - n1);

of += PERLIN_ZWRAP;
n2 = perlin[of & PERLIN_SIZE];
n2 += 0; // rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2);
n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE];
n3 += 0; // rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3);
n2 += 0; // ryf * (n3 - n2);

n1 += 0; // scaled_cosine(zf) * (n2 - n1); */

print(`noise(0, 0, 0) predicted: \${n1 * 0.5}`);
print(`lcg0 predicted from noise output: \${noise(0, 0, 0) * 2 * m}`);
}

function draw() {}
``````

Now, if you wanted to find the seed based on the output for some arbitrary set of non-integer points that would be much harder.

3 Likes

Wow! Thank you for doing all of this.