chaocipher 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +47 -0
- data/chaocipher.gemspec +13 -0
- data/lib/chaocipher.rb +29 -0
- data/lib/chaocipher/alphabet.rb +44 -0
- data/lib/chaocipher/cipher.rb +53 -0
- data/rakefile +7 -0
- data/test/test_chaocipher.rb +30 -0
- metadata +74 -0
data/.gemtest
ADDED
File without changes
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
(MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2010 Adam Prescott
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
ChaoCipher
|
2
|
+
==========
|
3
|
+
|
4
|
+
ChaoCipher is a Ruby implementation of the Chaocipher cipher, invented by J. F. Byrne; the algorithm was disclosed in 2010, hence this small bit of code!
|
5
|
+
|
6
|
+
The Algorithm
|
7
|
+
-------------
|
8
|
+
|
9
|
+
You can find more about the Chaocipher at [Wikipedia/Chaocipher](http://en.wikipedia.org/wiki/Chaocipher), and you can read the [online PDF](http://www.mountainvistasoft.com/chaocipher/ActualChaocipher/Chaocipher-Revealed-Algorithm.pdf) which contains details about the algorithm itself, upon which this code is based. The algorithm isn't that involved and is actually quite rudimentary.
|
10
|
+
|
11
|
+
# How do I use this thing?
|
12
|
+
|
13
|
+
To install from RubyGems:
|
14
|
+
|
15
|
+
gem install chaocipher
|
16
|
+
|
17
|
+
To get the source:
|
18
|
+
|
19
|
+
git clone https://github.com/aprescott/chaocipher.git
|
20
|
+
|
21
|
+
To run the tests with the source:
|
22
|
+
|
23
|
+
rake test
|
24
|
+
|
25
|
+
To contribute:
|
26
|
+
|
27
|
+
* Fork it
|
28
|
+
* Make a new feature branch: `git checkout -b some-new-thing master`
|
29
|
+
* Hack away and add tests
|
30
|
+
* Pull request
|
31
|
+
|
32
|
+
## Basic usage
|
33
|
+
|
34
|
+
The Chaocipher works off two alphabets, a "left" and a "right" alphabet which are used for look-up during ciphering and deciphering. The initial two alphabets are all that is required to have a working cipher. For more details, it's probably best that you just read the PDF linked above.
|
35
|
+
|
36
|
+
require "chaocipher"
|
37
|
+
|
38
|
+
ciphertext_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
|
39
|
+
plaintext_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
|
40
|
+
|
41
|
+
cipher = ChaoCipher::Cipher.new(ciphertext_alphabet, plaintext_alphabet)
|
42
|
+
|
43
|
+
cipher.encrypt("WELLDONEISBETTERTHANWELLSAID") #=> "OAHQHCNYNXTSZJRRHJBYHQKSOUJY"
|
44
|
+
|
45
|
+
# Cryptographic security
|
46
|
+
|
47
|
+
I have no idea what the strength of this cipher is, so I wouldn't encrypt anything of utter importance with it, personally.
|
data/chaocipher.gemspec
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "chaocipher"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.authors = ["Adam Prescott"]
|
5
|
+
s.email = ["adam@aprescott.com"]
|
6
|
+
s.homepage = "https://github.com/aprescott/chaocipher"
|
7
|
+
s.summary = "A Ruby implementation of the Chaocipher cipher."
|
8
|
+
s.description = "ChaoCipher is a Ruby implementation of the Chaocipher cipher, invented by J. F. Byrne; the algorithm was disclosed in 2010."
|
9
|
+
s.files = Dir["{lib/**/*,test/**/*}"] + %w[LICENSE Gemfile rakefile README.md chaocipher.gemspec .gemtest]
|
10
|
+
s.require_path = "lib"
|
11
|
+
s.test_files = Dir["test/*"]
|
12
|
+
s.add_development_dependency "rake"
|
13
|
+
end
|
data/lib/chaocipher.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2010 Adam Prescott
|
2
|
+
# Licensed under the MIT license. See LICENSE.
|
3
|
+
|
4
|
+
# Ruby 1.8
|
5
|
+
unless Array.new.respond_to?(:rotate)
|
6
|
+
class Array
|
7
|
+
def rotate(n = 1)
|
8
|
+
rotate_amount = n % size
|
9
|
+
return self if rotate_amount < 1 # will be true if n < 1 or size < 2
|
10
|
+
self[rotate_amount..-1] + self[0..rotate_amount-1]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module ChaoCipher
|
16
|
+
ZENITH_INDEX = 0
|
17
|
+
NADIR_INDEX = 13
|
18
|
+
ZENITH_POSITION = ZENITH_INDEX + 1
|
19
|
+
NADIR_POSITION = NADIR_INDEX + 1
|
20
|
+
|
21
|
+
VERSION_TINY = 1
|
22
|
+
VERSION_MINOR = 0
|
23
|
+
VERSION_MAJOR = 0
|
24
|
+
|
25
|
+
VERSION = [VERSION_MAJOR, VERSION_MINOR, VERSION_TINY].join(".")
|
26
|
+
end
|
27
|
+
|
28
|
+
require "chaocipher/alphabet"
|
29
|
+
require "chaocipher/cipher"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ChaoCipher
|
2
|
+
class Alphabet
|
3
|
+
attr_reader :characters, :type
|
4
|
+
|
5
|
+
def initialize(characters, kind)
|
6
|
+
@type = kind
|
7
|
+
@characters = characters
|
8
|
+
raise(ArgumentError, "given alphabet is not a permutation of A-Z") unless self.class.valid?(@characters)
|
9
|
+
end
|
10
|
+
|
11
|
+
def zenith
|
12
|
+
@characters.first
|
13
|
+
end
|
14
|
+
|
15
|
+
def nadir
|
16
|
+
@characters[NADIR_INDEX]
|
17
|
+
end
|
18
|
+
|
19
|
+
def permute(new_zenith)
|
20
|
+
self.class.permute(@characters, new_zenith, type)
|
21
|
+
end
|
22
|
+
|
23
|
+
def permute!(new_zenith)
|
24
|
+
@characters.replace(permute(new_zenith))
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.permute(characters, new_zenith, type)
|
28
|
+
if type == :ciphertext
|
29
|
+
amount_to_skip = 1
|
30
|
+
else
|
31
|
+
amount_to_skip = 2
|
32
|
+
end
|
33
|
+
|
34
|
+
permuted_characters = characters.rotate(characters.index(new_zenith))
|
35
|
+
permuted_characters = permuted_characters.rotate unless type == :ciphertext
|
36
|
+
|
37
|
+
permuted_characters[0..amount_to_skip-1] + permuted_characters[amount_to_skip..NADIR_INDEX].rotate + permuted_characters[NADIR_INDEX+1..-1]
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.valid?(characters)
|
41
|
+
characters.sort.join("") =~ /[a-z]/i
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ChaoCipher
|
2
|
+
class Cipher
|
3
|
+
def initialize(ciphertext_alphabet, plaintext_alphabet)
|
4
|
+
@original_ciphertext_alphabet = ciphertext_alphabet
|
5
|
+
@original_plaintext_alphabet = plaintext_alphabet
|
6
|
+
@ciphertext_alphabet = Alphabet.new(ciphertext_alphabet.upcase.chars.to_a, :ciphertext)
|
7
|
+
@plaintext_alphabet = Alphabet.new(plaintext_alphabet.upcase.chars.to_a, :plaintext)
|
8
|
+
end
|
9
|
+
|
10
|
+
def reinitialize!
|
11
|
+
@ciphertext_alphabet = Alphabet.new(@original_ciphertext_alphabet.upcase.chars.to_a, :ciphertext)
|
12
|
+
@plaintext_alphabet = Alphabet.new(@original_plaintext_alphabet.upcase.chars.to_a, :plaintext)
|
13
|
+
end
|
14
|
+
|
15
|
+
def plaintext_letter_for(ciphertext_letter)
|
16
|
+
@plaintext_alphabet.characters[@ciphertext_alphabet.characters.index(ciphertext_letter)]
|
17
|
+
end
|
18
|
+
|
19
|
+
def ciphertext_letter_for(plaintext_letter)
|
20
|
+
@ciphertext_alphabet.characters[@plaintext_alphabet.characters.index(plaintext_letter)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def cipher(mode, text)
|
24
|
+
reinitialize!
|
25
|
+
|
26
|
+
converted_text = ""
|
27
|
+
|
28
|
+
text.chars.each do |character|
|
29
|
+
if mode == :encrypt
|
30
|
+
@last_converted_letter = ciphertext_letter_for(character)
|
31
|
+
@ciphertext_alphabet.permute!(@last_converted_letter)
|
32
|
+
@plaintext_alphabet.permute!(character)
|
33
|
+
else
|
34
|
+
@last_converted_letter = plaintext_letter_for(character)
|
35
|
+
@ciphertext_alphabet.permute!(character)
|
36
|
+
@plaintext_alphabet.permute!(@last_converted_letter)
|
37
|
+
end
|
38
|
+
|
39
|
+
converted_text << @last_converted_letter
|
40
|
+
end
|
41
|
+
|
42
|
+
converted_text
|
43
|
+
end
|
44
|
+
|
45
|
+
def encrypt(plaintext)
|
46
|
+
cipher(:encrypt, plaintext)
|
47
|
+
end
|
48
|
+
|
49
|
+
def decrypt(ciphertext)
|
50
|
+
cipher(:decrypt, ciphertext)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
require "chaocipher"
|
4
|
+
|
5
|
+
class TestChaoCipher < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
ciphertext_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
|
8
|
+
plaintext_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
|
9
|
+
@cipher = ChaoCipher::Cipher.new(ciphertext_alphabet, plaintext_alphabet)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_encryption
|
13
|
+
assert_equal "OAHQHCNYNXTSZJRRHJBYHQKSOUJY", @cipher.encrypt("WELLDONEISBETTERTHANWELLSAID")
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_decryption
|
17
|
+
assert_equal "WELLDONEISBETTERTHANWELLSAID", @cipher.decrypt("OAHQHCNYNXTSZJRRHJBYHQKSOUJY")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_reversible
|
21
|
+
ciphertext_alphabet = ("A".."Z").to_a.shuffle.join("")
|
22
|
+
plaintext_alphabet = ("A".."Z").to_a.shuffle.join("")
|
23
|
+
|
24
|
+
cipher = ChaoCipher::Cipher.new(ciphertext_alphabet, plaintext_alphabet)
|
25
|
+
|
26
|
+
str = ("A".."Z").to_a.shuffle.join("")
|
27
|
+
|
28
|
+
assert_equal str, cipher.decrypt(cipher.encrypt(str))
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chaocipher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Prescott
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-19 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :development
|
25
|
+
version_requirements: *id001
|
26
|
+
description: ChaoCipher is a Ruby implementation of the Chaocipher cipher, invented by J. F. Byrne; the algorithm was disclosed in 2010.
|
27
|
+
email:
|
28
|
+
- adam@aprescott.com
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files: []
|
34
|
+
|
35
|
+
files:
|
36
|
+
- lib/chaocipher/alphabet.rb
|
37
|
+
- lib/chaocipher/cipher.rb
|
38
|
+
- lib/chaocipher.rb
|
39
|
+
- test/test_chaocipher.rb
|
40
|
+
- LICENSE
|
41
|
+
- Gemfile
|
42
|
+
- rakefile
|
43
|
+
- README.md
|
44
|
+
- chaocipher.gemspec
|
45
|
+
- .gemtest
|
46
|
+
homepage: https://github.com/aprescott/chaocipher
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.2
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: A Ruby implementation of the Chaocipher cipher.
|
73
|
+
test_files:
|
74
|
+
- test/test_chaocipher.rb
|