encrypted_text 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -5
- data/lib/encrypted_text/codec.rb +13 -28
- data/lib/encrypted_text/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
encrypted_text
|
2
2
|
==============
|
3
3
|
|
4
|
-
Password-based, two-way encryption with string output. Uses AES encryption
|
4
|
+
Password-based, two-way encryption with string output. Uses AES encryption.
|
5
5
|
|
6
6
|
Usage example
|
7
7
|
-------------
|
8
8
|
|
9
|
-
In order to encode or decode a message, you should know the **key** and **signature** ahead of time.
|
9
|
+
In order to encode or decode a message, you should know the **key** and **signature** ahead of time.
|
10
|
+
|
11
|
+
- The key is a 16-, 24-, or 32-character string, used as an AES encryption key.
|
12
|
+
- The signature is prepended to the message before encryption, and verified after decryption.
|
10
13
|
|
11
14
|
```ruby
|
12
15
|
require 'encrypted_text'
|
@@ -20,7 +23,7 @@ encoded = codec.encode("Hello, world!")
|
|
20
23
|
original_message = codec.decode(encoded)
|
21
24
|
```
|
22
25
|
|
23
|
-
You can also add a random
|
26
|
+
You can also add a random salt, so that repeated encodings of the same message produce different results.
|
24
27
|
|
25
28
|
```ruby
|
26
29
|
# Continued from previous example
|
@@ -34,6 +37,6 @@ b = codec.encode(message) # Should be a different result!
|
|
34
37
|
Motivation
|
35
38
|
----------
|
36
39
|
|
37
|
-
|
40
|
+
Among other things, this library is useful for generating tokens that seem opaque to the outside world, but actually encode real information.
|
38
41
|
|
39
|
-
|
42
|
+
For example, in situations where tokens are passed from a service to an outside party and then back again, the service needs some way of resolving tokens passed back to it. Oftentimes this means performing a lookup on a stored mapping (e.g. a database query) between the token and some kind of cleartext data that outside parties never see. But this comes with all the clumsiness of maintaining and interacting with a persistent data store. For some applications, it might be acceptable simply to encode data directly into the token itself, using a secret that only the originating service has access to. EncryptedText provides a simple API to accomplish this.
|
data/lib/encrypted_text/codec.rb
CHANGED
@@ -11,11 +11,10 @@ module EncryptedText
|
|
11
11
|
attr_reader :charset, :key, :salt_size
|
12
12
|
|
13
13
|
KEY_CHAR_SIZES = [16, 24, 32] # An AES key must be 8-bit char strings of these lengths
|
14
|
-
|
14
|
+
SALT_CHARSET = Array(32..126).map{ |i| i.chr } # Printable ASCII chars go from 32 to 126
|
15
15
|
|
16
16
|
def initialize(opts)
|
17
17
|
config = {
|
18
|
-
:charset => DEFAULT_CHARSET,
|
19
18
|
:signature => '',
|
20
19
|
:key => nil,
|
21
20
|
:salt_size => 0,
|
@@ -28,18 +27,9 @@ module EncryptedText
|
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
def charset=(charset)
|
32
|
-
@charset = charset
|
33
|
-
@reverse_charset = @charset.each.with_index.reduce({}) do |res, (c, i)|
|
34
|
-
res[c] = i
|
35
|
-
res
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
30
|
def key=(key)
|
31
|
+
@engine = FastAES.new(key)
|
40
32
|
@key = key
|
41
|
-
@engine = FastAES.new(@key)
|
42
|
-
@key
|
43
33
|
end
|
44
34
|
|
45
35
|
def salt_size=(s)
|
@@ -47,18 +37,9 @@ module EncryptedText
|
|
47
37
|
@salt_size = s
|
48
38
|
end
|
49
39
|
|
50
|
-
def base_encode(val, from_base)
|
51
|
-
val.b(from_base).to_a.map{ |id| @charset[id] }.join
|
52
|
-
end
|
53
|
-
|
54
|
-
def base_decode(val)
|
55
|
-
val.split.map{ |c| @reverse_charset.fetch(c) }.b(@charset.size).to_i
|
56
|
-
end
|
57
|
-
|
58
40
|
def encode(message)
|
59
|
-
|
60
|
-
|
61
|
-
encrypted = @engine.encrypt(signed)
|
41
|
+
signed_and_salted = @signature + random_salt + message
|
42
|
+
encrypted = @engine.encrypt(signed_and_salted)
|
62
43
|
hex_string = '1' + encrypted.to_hex_string.split(' ').join # Add "1" prefix in case hex_string has leading zeroes
|
63
44
|
encoded = Radix.convert(hex_string.upcase, 16, 62) # Radix requires allcaps
|
64
45
|
end
|
@@ -69,16 +50,20 @@ module EncryptedText
|
|
69
50
|
hex_string = hex_string[1..-1] if hex_string[0] == '1' # remove "1" prefix
|
70
51
|
hex_string = "0" + hex_string if (hex_string.size % 2) != 0 # Make sure we have an even number of hex digits
|
71
52
|
byte_string = hex_string.to_byte_string
|
72
|
-
decrypted = @engine.decrypt(
|
53
|
+
decrypted = @engine.decrypt(byte_string)
|
73
54
|
rescue #TODO: don't use generic rescue here
|
74
55
|
raise EncryptedText::Err::CannotDecrypt
|
75
56
|
end
|
76
57
|
|
77
58
|
# Ensure that the message is signed correctly
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
59
|
+
raise EncryptedText::Err::BadSignature unless decrypted.index(@signature) == 0
|
60
|
+
|
61
|
+
# Remove signature and salt
|
62
|
+
decrypted[(@signature.size + @salt_size)..-1]
|
63
|
+
end
|
64
|
+
|
65
|
+
def random_salt
|
66
|
+
(0...@salt_size).map{ SALT_CHARSET.sample }.join
|
82
67
|
end
|
83
68
|
|
84
69
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: encrypted_text
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fast-aes
|