module NumberStation
Ruby Number Station Author: David Kirwan gitub.com/davidkirwan Licence: GPL 3.0 NumberStation
is a collection of utilities to aid in the running of a number station
Copyright (C) 2018 David Kirwan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
Ruby Number Station Author: David Kirwan gitub.com/davidkirwan Licence: GPL 3.0 NumberStation
is a collection of utilities to aid in the running of a number station
Copyright (C) 2018 David Kirwan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
Ruby Number Station Author: David Kirwan gitub.com/davidkirwan Licence: GPL 3.0 NumberStation
is a collection of utilities to aid in the running of a number station
Copyright (C) 2018 David Kirwan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
Constants
- ALPHABET
- VERSION
Public Class Methods
call_espeak(input_file_path, output_file_path)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 97 def self.call_espeak(input_file_path, output_file_path) cmd = "espeak -ven+f3 -m -p 60 -s 180 -f #{input_file_path} --stdout | ffmpeg -i - -ar 44100 -ac 2 -ab 192k -f mp3 #{output_file_path}" unless NumberStation.command?('espeak') || NumberStation.command?('ffmpeg') NumberStation.log.error "number_station requires the espeak and ffmpeg utilities are installed in order to output an mp3 file." else `#{cmd}` end end
command?(name)
click to toggle source
# File lib/number_station.rb, line 35 def self.command?(name) `which #{name}` $?.success? end
data()
click to toggle source
# File lib/number_station.rb, line 52 def self.data() return @data end
decrypt_message(message, pad_path, pad_num)
click to toggle source
# File lib/number_station/decrypt_message.rb, line 26 def self.decrypt_message(message, pad_path, pad_num) NumberStation.log.debug "message length: #{message.size}" message_byte_array = message.scan(/.{1}/).each_slice(2).map { |f, l| (Integer(f,16) << 4) + Integer(l,16) } begin pad_data = JSON.parse(File.read(pad_path)) rescue Exception => e raise e end crypto_hex_str = pad_data["pads"][pad_num]["key"] if message.size > crypto_hex_str.size NumberStation.log.error "Error: The message length is greater than pad length. Unable to continue decryption." exit end NumberStation.log.debug "message length less than pad length: #{message.size <= crypto_hex_str.size}" crypto_byte_array = crypto_hex_str.scan(/.{1}/).each_slice(2).map { |f, l| (Integer(f,16) << 4) + Integer(l,16) } decrypted_byte_array = [] message_byte_array.each_with_index do |i, index| decrypted_byte_array << (i ^ crypto_byte_array[index]) end decrypted_string = decrypted_byte_array.pack('U*').force_encoding('utf-8') begin f_name = "#{pad_data["id"]}_#{pad_num}_#{Time.now.to_i}_decrypted.txt" NumberStation.log.info "Writing decrypted message to file #{f_name}" f = File.open(f_name, "w") f.write(decrypted_string) f.close rescue Exception => e raise e end return decrypted_string end
encrypt_message(message, pad_path, pad_num)
click to toggle source
# File lib/number_station/encrypt_message.rb, line 26 def self.encrypt_message(message, pad_path, pad_num) NumberStation.log.debug "message length: #{message.size}" message_byte_array = message.unpack('U*') begin pad_data = JSON.parse(File.read(pad_path)) rescue Exception => e raise e end crypto_hex_str = pad_data["pads"][pad_num]["key"] if message.size > crypto_hex_str.size NumberStation.log.error "Exception: message length is larger than pad length. Break the message into smaller parts." exit end NumberStation.log.debug "message length less than pad length" unless pad_data["pads"][pad_num]["consumed"] NumberStation.log.debug "Marking key as consumed" pad_data["pads"][pad_num]["epoch_date"] = Time.now.to_i pad_data["pads"][pad_num]["consumed"] = true f = File.open(pad_path, "w") f.write(pad_data.to_json) f.close else msg = "Warning pad #{pad_num} has been consumed on #{Time.at(pad_data["pads"][pad_num]["epoch_date"])}" NumberStation.log.error msg exit end crypto_byte_array = crypto_hex_str.scan(/.{1}/).each_slice(2).map { |f, l| (Integer(f,16) << 4) + Integer(l,16) } encrypted_byte_array = [] message_byte_array.each_with_index do |i, index| encrypted_byte_array << (i ^ crypto_byte_array[index]) end encrypted_byte_str = encrypted_byte_array.map { |n| '%02X' % (n & 0xFF) }.join.downcase begin f_name = "#{pad_data["id"]}_#{pad_num}_#{Time.now.to_i}.txt" NumberStation.log.info "Writing encrypted message to file #{f_name}" f = File.open(f_name, "w") f.write(encrypted_byte_str) f.close rescue Exception => e raise e end return encrypted_byte_str end
espeak_word_template(word)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 73 def self.espeak_word_template(word) return "<prosody pitch=\"#{randomsign() + rand(0..200).to_s}\">#{word}</prosody>" end
generate_sentence(message)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 83 def self.generate_sentence(message) sentence = "" message.split(" ").each {|i| sentence += espeak_word_template(i)} return "<speak version=\"1.0\" xmlns=\"\" xmlns:xsi=\"\" xsi:schemaLocation=\"\" xml:lang=\"\"><voice gender=\"female\">#{sentence}</voice></speak>" end
log()
click to toggle source
# File lib/number_station.rb, line 44 def self.log() return @log end
lookup_phonetic(c)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 64 def self.lookup_phonetic(c) begin return NumberStation::ALPHABET[c] + ' ' || ' ' rescue Exception => e return ' ' end end
make_otp(pad_path, length, num_pads)
click to toggle source
# File lib/number_station/make_onetime_pad.rb, line 26 def self.make_otp(pad_path, length, num_pads) path = pad_path || Dir.pwd len = length || 250 num = num_pads || 5 NumberStation.log.debug "make_otp" pads = {} id = rand(0..99999).to_s.rjust(5, "0") file_name = File.join(path, "one_time_pad_#{id}.json") NumberStation.log.debug "file_name: #{file_name}" 0.upto(num.to_i - 1) do |i| pads[i] = { "key"=>SecureRandom.hex(len.to_i), "epoch_date"=>nil, "consumed"=>false } end one_time_pads = { :id=> id, :pads=> pads } unless File.file?(file_name) f = File.open(file_name, "w") f.write(one_time_pads.to_json) f.close else raise Exception.new("Exception #{file_name} already exists") end end
randomsign()
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 78 def self.randomsign() return rand(0..1) == 0 ? "-" : "+" end
set_data(data)
click to toggle source
# File lib/number_station.rb, line 48 def self.set_data(data) @data = data end
set_log(log)
click to toggle source
# File lib/number_station.rb, line 40 def self.set_log(log) @log = log end
to_phonetic(file_name)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 116 def self.to_phonetic(file_name) message = '' f = File.open(file_name) raw_message = f.read() f.close() raw_message.each_char do |c| message += NumberStation.lookup_phonetic(c) end return message end
write_espeak_template_file(filename, sentence)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 90 def self.write_espeak_template_file(filename, sentence) f = File.open(filename, "w") f.write(sentence) f.close end
write_mp3(message, output_file_path)
click to toggle source
# File lib/number_station/phonetic_conversion.rb, line 108 def self.write_mp3(message, output_file_path) filename = NumberStation.data["resources"]["espeak_sentence_template"] sentence = NumberStation.generate_sentence(message) NumberStation.write_espeak_template_file(filename, sentence) NumberStation.call_espeak(filename, output_file_path) end