enigma_ruby 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 12988cada24f1d22f2954abae0f25f952454cb870c3886683f72f32a5fce40c9
4
+ data.tar.gz: dcdb04c44fb455aa150932d2ae9dc4f48f1464f958bc2fb216853fc103a1136a
5
+ SHA512:
6
+ metadata.gz: 8a9c385e78a24de6d8704702b6e4d55fb2620de00316ec35e29ed9cc6d5bbf2c567c270effafbba69b8d3fd210cbca57cfc8260093a6d92d9929f0fdd3151668
7
+ data.tar.gz: 29c215ce716dddb4bfabb17a7f437e98df70f1d8db94a56111de720b54aa2e4dd1bfd153b37012c3ef003801bb6f9518d0d60e8216b9d55b4ec17b32dd109066
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ ## EnigmaRuby
2
+
3
+ [![Minitest](https://github.com/chibicco/enigma_ruby/actions/workflows/minitest.yml/badge.svg)](https://github.com/chibicco/enigma_ruby/actions/workflows/minitest.yml)
4
+
5
+ EnigmaRuby faithfully recreates the functionality of the historical Enigma machine in Ruby.
6
+ This gem allows you to encrypt and decrypt messages using customizable rotors, reflectors, and plugboards, offering a hands-on experience with classic cryptographic techniques.
7
+
8
+ ### Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'enigma_ruby'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ ```shell
19
+ $ bundle install
20
+ ```
21
+
22
+ Or install it yourself as:
23
+
24
+ ```shell
25
+ $ gem install enigma_ruby
26
+ ```
27
+
28
+ ### Usage
29
+
30
+ ```rub
31
+ require 'enigma_ruby'
32
+
33
+ EnigmaRuby.encrypt('HELLO WORLD')
34
+ ```
35
+
36
+ ### References
37
+
38
+ - [Enigma Machine - Wikipedia](https://en.wikipedia.org/wiki/Enigma_machine)
39
+ - [The_Imitation_Game](https://en.wikipedia.org/wiki/The_Imitation_Game)
40
+
41
+ ### License
42
+
43
+ The gem is available as open source under the terms of the MIT License.
@@ -0,0 +1,17 @@
1
+ module EnigmaRuby
2
+ class AdvanceRotorsCommand < Command
3
+ def initialize(rotors)
4
+ @rotors = rotors
5
+ end
6
+
7
+ def execute(_)
8
+ @rotors[0].advance
9
+ @rotors.each_with_index do |rotor, i|
10
+ next if i == 0
11
+ break unless @rotors[i - 1].at_notch?
12
+
13
+ rotor.advance
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module EnigmaRuby
2
+ class Command
3
+ def execute(context)
4
+ raise NotImplementedError, 'Subclasses must implement execute(context)'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module EnigmaRuby
2
+ class EncodeRotorBackwardCommand < Command
3
+ def initialize(rotors)
4
+ @rotors = rotors
5
+ end
6
+
7
+ def execute(context)
8
+ @rotors.reverse_each do |rotor|
9
+ context[:encoded_char] = rotor.encode_backward(context[:encoded_char])
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module EnigmaRuby
2
+ class EncodeRotorForwardCommand < Command
3
+ def initialize(rotors)
4
+ @rotors = rotors
5
+ end
6
+
7
+ def execute(context)
8
+ @rotors.each do |rotor|
9
+ context[:encoded_char] = rotor.encode_forward(context[:encoded_char])
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module EnigmaRuby
2
+ class ReflectCommand < Command
3
+ def execute(context)
4
+ context[:encoded_char] = Reflector.reflect(context[:encoded_char])
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module EnigmaRuby
2
+ class SwapPlugboardCommand < Command
3
+ def execute(context)
4
+ context[:encoded_char] = Plugboard.swap(context[:encoded_char])
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module EnigmaRuby
2
+ SKIP_CHARACTERS_REGEX = /[']/.freeze
3
+ NON_ENCRYPTED_CHARACTERS_REGEX = /[ .,;0-9]/.freeze
4
+
5
+ class Enigma
6
+ def initialize(rotor_settings = [])
7
+ initialize_rotors(rotor_settings)
8
+ @commands = [
9
+ SwapPlugboardCommand.new,
10
+ EncodeRotorForwardCommand.new(@rotors),
11
+ ReflectCommand.new,
12
+ EncodeRotorBackwardCommand.new(@rotors),
13
+ SwapPlugboardCommand.new,
14
+ AdvanceRotorsCommand.new(@rotors)
15
+ ]
16
+ end
17
+
18
+ def encrypt(cleartext)
19
+ encoded_text = ''
20
+ cleartext.each_char do |char|
21
+ next if SKIP_CHARACTERS_REGEX .match?(char)
22
+ next encoded_text << char if NON_ENCRYPTED_CHARACTERS_REGEX .match?(char)
23
+
24
+ context = { encoded_char: char }
25
+ @commands.each { |command| command.execute(context) }
26
+ encoded_text << context[:encoded_char]
27
+ end
28
+ encoded_text
29
+ end
30
+
31
+ private
32
+
33
+ def initialize_rotors(rotor_settings)
34
+ @rotors = rotor_settings.map { |config| Rotor.new(config[:wiring], config[:position]) }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module EnigmaRuby
3
+ class Plugboard
4
+ WIRING = {
5
+ 'A' => 'F', 'F' => 'A',
6
+ 'B' => 'E', 'E' => 'B',
7
+ 'C' => 'D', 'D' => 'C'
8
+ }.freeze
9
+
10
+ def self.swap(char)
11
+ WIRING[char] || char
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module EnigmaRuby
2
+ class Reflector
3
+ WIRING = 'YRUHQSLDPXNGOKMIEBFZCWVJAT'.freeze
4
+
5
+ def self.reflect(char)
6
+ index = char.ord - 'A'.ord
7
+ WIRING[index]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ module EnigmaRuby
2
+ class Rotor
3
+ def initialize(wiring, position = 0)
4
+ @wiring = wiring.chars
5
+ @position = @notch = position
6
+ end
7
+
8
+ def encode_forward(char)
9
+ index = (char.ord - 'A'.ord + @position) % 26
10
+ @wiring[index]
11
+ end
12
+
13
+ def encode_backward(char)
14
+ index = @wiring.index(char)
15
+ ((index - @position) % 26 + 'A'.ord).chr
16
+ end
17
+
18
+ def advance
19
+ @position = (@position + 1) % 26
20
+ end
21
+
22
+ def at_notch?
23
+ @position == @notch
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module EnigmaRuby
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,23 @@
1
+ require "enigma_ruby/version"
2
+ require "enigma_ruby/rotor"
3
+ require "enigma_ruby/reflector"
4
+ require "enigma_ruby/plugboard"
5
+ require "enigma_ruby/enigma"
6
+ require "enigma_ruby/commands/command"
7
+ require "enigma_ruby/commands/advance_rotors_command"
8
+ require "enigma_ruby/commands/encode_rotor_backward_command"
9
+ require "enigma_ruby/commands/encode_rotor_forward_command"
10
+ require "enigma_ruby/commands/reflect_command"
11
+ require "enigma_ruby/commands/swap_plugboard_command"
12
+
13
+ module EnigmaRuby
14
+ DEFAULT_ROTOR_SETTINGS = [
15
+ { wiring: 'EKMFLGDQVZNTOWYHXUSPAIBRCJ', position: 12 },
16
+ { wiring: 'AJDKSIRUXBLHWTMCQGZNPYFVOE', position: 2 },
17
+ { wiring: 'BDFHJLCPRTXVZNYEIWGAKMUSQO', position: 10 },
18
+ ].freeze
19
+
20
+ def self.encrypt(cleartext, rotor_settings = DEFAULT_ROTOR_SETTINGS)
21
+ Enigma.new(rotor_settings).encrypt(cleartext)
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enigma_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - chibicco
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-07-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: This gem allows you to simulate the encryption process of the Enigma
56
+ machine.
57
+ email:
58
+ - me@chibicco.dev
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - README.md
64
+ - lib/enigma_ruby.rb
65
+ - lib/enigma_ruby/commands/advance_rotors_command.rb
66
+ - lib/enigma_ruby/commands/command.rb
67
+ - lib/enigma_ruby/commands/encode_rotor_backward_command.rb
68
+ - lib/enigma_ruby/commands/encode_rotor_forward_command.rb
69
+ - lib/enigma_ruby/commands/reflect_command.rb
70
+ - lib/enigma_ruby/commands/swap_plugboard_command.rb
71
+ - lib/enigma_ruby/enigma.rb
72
+ - lib/enigma_ruby/plugboard.rb
73
+ - lib/enigma_ruby/reflector.rb
74
+ - lib/enigma_ruby/rotor.rb
75
+ - lib/enigma_ruby/version.rb
76
+ homepage: https://github.com/chibicco/enigma_ruby/
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.5.15
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: A Ruby implementation of the Enigma machine
99
+ test_files: []