diff --git a/src/conversion.jl b/src/conversion.jl index 2dfdb4f..4c51843 100644 --- a/src/conversion.jl +++ b/src/conversion.jl @@ -3,14 +3,27 @@ using Interpolations using Distributions """ - convert_message_to_samples(message::String) + convert_message_to_samples( + message::String; + add_noise::Bool = false, + std::Float64 = 1.0, + ) + +# Arguments +- `message::String` : filepath to the wav file to convert to samples +- `sampling_rate` : sampling rate of the resulting file +- `add_noise::Bool` : if true, add Gaussian noise of standard deviation `std` and none otherwise +- `std::Float64` : standard deviation of Gaussian noise if `add_noise` is `true` + +# Returns +- `func_message_unencrypted` : waveform that is a function of time +- `num_samples` : number of samples +- `sampling_rate` : sampling rate Convert a message (.wav file) which is identified as the string of the file path and convert it into samples. If `add_noise` is true, then noise is added to the samples. The noise is generated from a Gaussian distribution with mean 0 and standard deviation `std``. - -Return a waveform that is a function of time, number of samples, and the sampling rate. """ function convert_message_to_samples( message::String; @@ -43,7 +56,12 @@ function convert_message_to_samples( end """ - convert_samples_to_message(samples, sampling_rate, num_of_samples, name_of_file) + convert_samples_to_message( + samples, + sampling_rate, + num_of_samples::Int64, + name_of_file::String, + ) # Arguments - `samples` : function that produce the samples @@ -59,13 +77,19 @@ function convert_samples_to_message( num_of_samples::Int64, name_of_file::String, ) + # Evaluate the waveform for every element in time_arr and write the result as a wav file time_arr = [(1 / sampling_rate) * n for n = 1:num_of_samples] message = samples(time_arr) wavwrite(message, name_of_file, Fs = sampling_rate) end """ - binary_to_bmessage(s::String; time_length = 2.0, b_zero = 4.0, b_one = 4.4) + binary_to_bmessage( + s::String; + time_length::Float64 = 2.0, + b_zero::Float64 = 4.0, + b_one::Float64 = 4.4, + ) # Arguments - `s::String` : binary string of 0's and 1's @@ -73,9 +97,9 @@ end - `b_zero::Float64 = 4.0` : value of the function when the binary digit is zero - `b_one::Float64 = 4.4` : value of the function when the binary digit is one -Return a function that map the time ``t`` to `floor(t/time_length)`th letter -in the string. The binary digits in the string is counted starting with 0. If `t < 0` or -`t >= time_length * length(binary_arr)`, then it is `b_zero`. +Return a function that map the time ``t`` to `floor(t/time_length)`th position of the binary +string. The binary digits in the string is counted starting with 0. If `t < 0` or +`t >= time_length * length(binary_arr)`, then the function evaluate to `b_zero`. """ function binary_to_bmessage( s::String; @@ -90,11 +114,11 @@ function binary_to_bmessage( end end - # Parse string and put them into an array + # Parse string and put them into an array as Float64 binary_arr = [parse.(Float64, string(c)) for c in s] # Iterate through binary_arr and replace them with b_zero if the digit is 0 and b_one - # otherise + # othewise for (idx, num) in enumerate(binary_arr) if num == 0 binary_arr[idx] = b_zero diff --git a/src/encryption.jl b/src/encryption.jl index fa55105..46d2f63 100644 --- a/src/encryption.jl +++ b/src/encryption.jl @@ -59,7 +59,8 @@ end - `abstol::Float64 = 1e-11` : absolute tolerance for the ODE solver - `reltol::Float64 = 1e-11` : relative tolerance for the ODE solver -Encrpyt the message using the Lorenz system (see lorenz_transmitter!). +Encrpyt the message using a paramterized version of the Lorenz system +(see lorenz_transmitter! and lorenz_transmitter_binary!). """ function create_secret_message( u0::Vector{Float64}, @@ -72,9 +73,12 @@ function create_secret_message( reltol::Float64 = 1e-11, ) if !binary + # Solve chaotic system prob = ODEProblem(lorenz_transmitter!, u0, tspan, p) sol_transmitter = solve(prob, AutoTsit5(Rodas4P()), abstol = abstol, reltol = reltol) + + # Make a function that return the x-component of the solution function secret_message1(t) hidden(t) = scale * message_unencrypted(t) secret_at_time_t = sol_transmitter(t, idxs = 1) + hidden(t) @@ -82,11 +86,15 @@ function create_secret_message( end return secret_message1 else - (σ, _, r) = p - p1 = (σ, message_unencrypted, r) + (σ, _, r) = p # ignore the second parameter + p1 = (σ, message_unencrypted, r) # substitute second paramter for the message + + # Solve chaotic system prob = ODEProblem(lorenz_transmitter_binary!, u0, tspan, p1) sol_transmitter = solve(prob, AutoTsit5(Rodas4P()), abstol = abstol, reltol = reltol) + + # Make a function that return the x-component of the solution function secret_message2(t) secret_at_time_t = sol_transmitter(t, idxs = 1) return secret_at_time_t @@ -133,7 +141,7 @@ end - `abstol::Float64 = 1e-11` : absolute tolerance for the ODE solver - `reltol::Float64 = 1e-11` : relative tolerance for the ODE solver -Decrypt the message using the Lorenz system (lorenz_receiver!). +Decrypt the message using a paramterized version of the Lorenz system (lorenz_receiver!). """ function decrypt_secret_message( u0::Vector{Float64}, @@ -144,10 +152,14 @@ function decrypt_secret_message( scale::Float64 = 1e5, abstol::Float64 = 1e-11, reltol::Float64 = 1e-11, -) +) + # Solve chaotic system lorenz_receiver_with_message! = lorenz_receiver!(secret_message) prob_R = ODEProblem(lorenz_receiver_with_message!, u0, tspan, p) sol_receiver = solve(prob_R, AutoTsit5(Rodas4P()), abstol = abstol, reltol = reltol) + + # Make a function that return the error and scale it if the message is not binary and + # square it if the message is binary if !binary function decrypted_message1(t) return (secret_message(t) - sol_receiver(t, idxs = 1)) * scale