Pseudo-Random Number Generators

In the following example, we will explore the PRNGs available in ChaoticEncryption.jl. The API documentation for ChaoticEncryption.jl is available here.

Let us start by adding in the julia packages we will be needing -

# install TestImages for this tutorial
# julia> using Pkg
# julia> Pkg.add("TestImages")
# install ChaoticEncryption.jl if you haven't already!
# julia> Pkg.add("ChaoticEncryption")

julia> using TestImages, ChaoticEncryption

PRNGs in ChaoticEncryption.jl

Currently, ChaoticEncryption.jl includes 2 PRNGs, which are-

  1. Logistic Map
  2. Lorenz System of Differential Equations

We will be adding more of them soon! If you stumble upon an interesting PRNG, feel free to create an issue or a pull request for the same!

Logistic Map

As per the documentation, logistic_key generates a vectors of pseudo-random numbers using the Logistic Map.

The function uses the following equation to generate pseudo-random numbers -

\[x_{n+1} = r * x_{n} * (1 - x_{n})\]

The function takes in the following arguments -

  • x_init::Float64: Initial value of x. x ϵ (0, 1).
  • r::Float64: A constant value. Values > 4 usually results in pseudo-random numbers.
  • num_keys::Int64: Number of keys to be generated.
  • scaling_factor::Float64=10.0^16: Factor to be multiplied to the generated value of pseudo-random number. Ideally, the factor should be > upper_bound.
  • upper_bound::Float64=256.0: Upper bound of keys (not included). Use 256 for encrypting images as the RGB values of a pixel varies from 0 to 255.

And returns the following Vector -

  • keys::Vector{Int64}:: Generated pseudo-random keys.

Using logistic_key

After going through the documentation, let us use the function logistic_key with the following aarguments -

  • x_init = 0.01
  • r = 3.97
  • num_keys = 20
julia> keys = logistic_key(0.01, 3.97, 20)
20-element Vector{Int64}:
   0
  44
   7
  26
  14
 224
  16
 250
 162
 211
 200
 217
  97
 132
 134
 100
 135
 232
 122
 102

This returns a 1 dimensional Vector of pseudo-random Int64 elements ranging from 0 - 255 (as the RGB values of an image range from 0 - 255)!

Generating pseudo-random keys for an image

Now we can try to generate a pseudo-random key for each pixel in a given image. Let us load an image using the TestImages package for this!

julia> img = testimage("cameraman");

julia> height, width = size(img)
(512, 512)

The image can be viewed using ImageView.jl -

julia> using ImageView

julia> imshow(img)

image

Generating a key for each pixel in the image

julia> keys = logistic_key(0.01, 3.67, height * width)
262144-element Vector{Int64}:
   0
  68
 135
  20
  13
 140
 197
 182
 248
 229
   ⋮
 168
 182
  77
  83
  74
 176
  27
 251
 206

We can now use these keys to encrypt the image! Encryption and decryption will be covered in another example :)

Lorenz System of Differential Equations

As per the documentation, lorenz_key generates 3 vectors of pseudo-random numbers using Lorenz system of differential equations.

The function uses the following system of differential equations to generate pseudo-random numbers -

\[\frac{dx}{dt} = α * (y - x)\]

\[\frac{dy}{dt} = x * (ρ - z) - y\]

\[\frac{dz}{dt} = x * y - β * z\]

The function takes in the following arguments -

  • x_init::Float64: Initial value of x.
  • y_init::Float64: Initial value of y.
  • z_init::Float64: Initial value of z.
  • num_keys::Int64: Number of keys (in a single list) to be generated.
  • α::Float64: Constant associated with Lorenz system of differential equations.
  • ρ::Float64: Constant associated with Lorenz system of differential equations.
  • β::Float64: Constant associated with Lorenz system of differential equations.
  • scaling_factor::Float64=10.0^16: Factor to be multiplied to the generated value of pseudo-random number. Ideally, the factor should be > upper_bound.
  • upper_bound::Float64=256.0: Upper bound of keys (not included). Use 256 for encrypting images as the RGB values of a pixel varies from 0 to 255.

And returns the following Vectors

  • x::Vector{Int64}: Generated pseudo-random keys corresponding to x values.
  • y::Vector{Int64}: Generated pseudo-random keys corresponding to y values.
  • z::Vector{Int64}: Generated pseudo-random keys corresponding to z values.

Using lorenz_key

After going through the documentation, let us use the function lorenz_key with the following aarguments -

  • x_init = 0.01
  • y_init = 0.02
  • z_init = 0.03
  • num_keys = 20

You can play with other arguments as well!

julia> keys = lorenz_key(0.01, 0.02, 0.03, 20)
([0, 0, 256, 24, 129, 42, 54, 134, 43, 179, 85, 19, 24, 44, 71, 210, 238, 152, 22, 27], [0, 0, 240, 55, 25, 163, 89, 243, 123, 5, 197, 64, 227, 54, 188, 226, 154, 134, 64, 69], [0, 0, 80, 227, 178, 204, 89, 33, 144, 139, 105, 208, 108, 155, 61, 254, 57, 102, 149, 47])

Generating pseudo-random keys for an image

Now we can try to generate a pseudo-random key for each pixel in a given image. Let us load an image using the TestImages package for this!

julia> img = testimage("cameraman");

julia> height, width = size(img)
(512, 512)

Generating a key for each pixel in the image

julia> x, y, z = lorenz_key(0.01, 0.02, 0.03, height * width)
([0, 0, 256, 24, 129, 42, 54, 134, 43, 179  …  46, 94, 18, 206, 68, 98, 72, 10, 248, 136], [0, 0, 240, 55, 25, 163, 89, 243, 123, 5  …  4, 112, 116, 100, 108, 92, 236, 80, 152, 144], [0, 0, 80, 227, 178, 204, 89, 33, 144, 139  …  128, 48, 176, 128, 176, 72, 168, 32, 208, 112])

lorenz_key returns a Tuple with each element being an Vector{Int64}. Thus, it returns a variable of the type Tuple{Vector{Int64}, Vector{Int64}, Vector{Int64}}.

julia> x
262144-element Vector{Int64}:
   0
   0
 256
  24
 129
  42
  54
 134
  43
 179
   ⋮
  94
  18
 206
  68
  98
  72
  10
 248
 136

A notebook version of this tutorial is available here. Don't forget to star ChaoticEncryption.jl :)

The complete API documentation is available here.