aion-enigma 0.0.1

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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +27 -0
  3. data/lib/aion-enigma.rb +1 -0
  4. data/lib/enigma.rb +110 -0
  5. metadata +78 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 123f2307cf57a446b1c46823bd3507bd83ce4784
4
+ data.tar.gz: 9cac96a9c1fd6ab3c6a591dd303f450ceb5a055c
5
+ SHA512:
6
+ metadata.gz: 634e1f259feed493be4703935b9409461e6bc1dbb52c201551b09dcc81ca5484a73ee1d5c01020313b7fb45a8673e3d1f52e3c44af5bd9d8ee59cbcbe32050b8
7
+ data.tar.gz: 9fdcc2e6e9951444e2d4293fbef8180f1f8233fe4bfbf3f91cabbf862a53aac89faa85c5b3fb9b8d818f8942376eb6a7e6f0a3c0ca5317e8874bfa8118ba04bc
@@ -0,0 +1,27 @@
1
+ Enigma
2
+ ======
3
+
4
+ Enigma is a small utility for encrypting/decrypting a string based on a shared secret using AES-265-CBC.
5
+
6
+ Install
7
+ -------
8
+
9
+ Install gem via git
10
+ ```
11
+ gem 'aion-enigma'
12
+ ```
13
+
14
+ Usage
15
+ -----
16
+
17
+ ```ruby
18
+ secret_message = 'this is a secret message'
19
+ shared_secret = 'some shared secret'
20
+
21
+ enigma = Enigma.new(shared_secret)
22
+ encrypted_message = enigma.encrypt(secret_message)
23
+ # encrypted_message ≈> 'Gn3AZKG9aqv+ALTfI9ZbuQ==|7hI5iN1Jdm73zQB1nTBngX07SaX60nuirWQRtNygIgE='
24
+
25
+ message = enigma.decrypt(encrypted_message)
26
+ # message => 'this is a secret message'
27
+ ```
@@ -0,0 +1 @@
1
+ require 'enigma'
@@ -0,0 +1,110 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ class Enigma
5
+
6
+ class EncryptError < StandardError; end
7
+ class DecryptError < StandardError; end
8
+
9
+ # Creates an instance of Enigma using given shared secret
10
+ # @raise ArgumentError if secret is not a string
11
+ def initialize(secret)
12
+ unless secret.is_a? String
13
+ fail ArgumentError, 'secret must be a string'
14
+ end
15
+ @key = Digest::SHA1.hexdigest(secret)
16
+ end
17
+
18
+ # Encrypts a string.
19
+ #
20
+ # @param message a string to encrypt
21
+ # @return a String
22
+ # @raise ArgumentError if message is not a string
23
+ # @raise EncryptError if encryption failed
24
+ def encrypt(message)
25
+ unless message.is_a? String
26
+ fail ArgumentError, 'message must be a string'
27
+ end
28
+
29
+ begin
30
+ cipher = OpenSSL::Cipher.new('aes-256-cbc')
31
+
32
+ cipher.encrypt
33
+ cipher.key = @key
34
+
35
+ cipher.iv = iv = cipher.random_iv
36
+
37
+ encrypted = cipher.update(message)
38
+ encrypted << cipher.final
39
+
40
+ pack(iv, encrypted)
41
+ rescue => _
42
+ fail EncryptError, 'Could not encode message.'
43
+ end
44
+ end
45
+
46
+ # Decrypts an encrypted messages.
47
+ # If the secret does not match the encrypted message then
48
+ # an Enigma::DecryptError is raised.
49
+ #
50
+ # @param encrypted_message a string to decrypt (outputted by Enigma#encrypt)
51
+ # @return a String with the decrypted message
52
+ # @raise ArgumentError if encrypted_message is not a string
53
+ # @raise DecryptError if Decryption failed
54
+
55
+ def decrypt(encrypted_message)
56
+ unless encrypted_message.is_a? String
57
+ fail ArgumentError, 'encrypted_message must be a string'
58
+ end
59
+
60
+ begin
61
+ iv, encrypted_message = unpack(encrypted_message)
62
+
63
+ cipher = OpenSSL::Cipher.new('aes-256-cbc')
64
+ cipher.decrypt
65
+ cipher.key = @key
66
+
67
+ cipher.iv = iv
68
+
69
+ decrypted = cipher.update(encrypted_message)
70
+ decrypted << cipher.final
71
+
72
+ decrypted
73
+ rescue => _
74
+ fail DecryptError, 'Could not decode encrypted message.'
75
+ end
76
+ end
77
+
78
+ protected
79
+
80
+ # Packing the encrypted message into a string.
81
+ #
82
+ # Enigma#pack and Enigma#unpack can be overridden from a subclass.
83
+ # Just make sure that the following still holds:
84
+ #
85
+ # iv2, encrypted2 = unpack(pack(iv1, encrypted1)
86
+ # iv1 == iv2 and encrypted1 == encrypted2
87
+ #
88
+ # @param iv the random iv (bytes) generated by the cipher
89
+ # @param encrypted the encrypted bytes
90
+ # @return String with serialized iv and encrypted parameters
91
+ def pack(iv, encrypted)
92
+ [iv, encrypted].map { |x| Base64.encode64(x).strip }.join('|')
93
+ end
94
+
95
+ # Unpacking the encrypted_message into an array of iv and encrypted data.
96
+ #
97
+ # Enigma#pack and Enigma#unpack can be overridden from a subclass.
98
+ # Just make sure that the following still holds:
99
+ #
100
+ # iv2, encrypted2 = unpack(pack(iv1, encrypted1)
101
+ # iv1 == iv2 and encrypted1 == encrypted2
102
+ #
103
+ # @param encrypted_message as outputted by Enigma#pack
104
+ # @return Array containing iv bytes and encrypted bytes
105
+ def unpack(encrypted_message)
106
+ encrypted_message.split('|').map { |m| Base64.decode64(m) }
107
+ end
108
+
109
+ end
110
+
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aion-enigma
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Andersen
8
+ - Eugene Zainchkovskyy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-09-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '11.2'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '11.2'
28
+ - !ruby/object:Gem::Dependency
29
+ name: minitest
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '5.9'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '5.9'
42
+ description: Small utility for encrypting/decrypting a string based on a shared secret.
43
+ Based on AES-265-CBC.
44
+ email:
45
+ - michael@aion.dk
46
+ - eugene@3bytesahead.com
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - README.md
52
+ - lib/aion-enigma.rb
53
+ - lib/enigma.rb
54
+ homepage: https://github.com/aion-dk/enigma
55
+ licenses:
56
+ - MIT
57
+ metadata: {}
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project:
74
+ rubygems_version: 2.4.5.1
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: Encryption utility based on AES
78
+ test_files: []