krypter 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +49 -4
- data/lib/krypter.rb +14 -12
- data/test/krypter_test.rb +83 -0
- metadata +57 -20
- data/.gems +0 -1
- data/krypter.gemspec +0 -14
- data/makefile +0 -4
- data/test/krypter.rb +0 -73
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb0a9a64893aff504e77095a510ba548c8b40492
|
4
|
+
data.tar.gz: d2d33978f856c3aa0cb92f3554f9623e90658de4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e8476f5bbcaf9b8b919255fc4e26e870845b85969c0dd993c74e3233b0ad7b0b0261b64d992c47116c2ac2c32f49d171abefb10f48e65fa5198dd595e1a6d23
|
7
|
+
data.tar.gz: d082f85b4c2107e683285c6819f2d761c64f592dff1f27fd1f0fc82178933269ebcc16e8fd3ace5862f9b4a59c7be9db575aa8282d0f13d04e32fa70f40606e8
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,29 @@
|
|
1
|
-
krypter
|
1
|
+
Krypter [](https://travis-ci.org/frodsan/krypter)
|
2
2
|
=======
|
3
3
|
|
4
4
|
Encrypts messages with authentication.
|
5
5
|
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem "krypter"
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
```
|
18
|
+
$ bundle
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
```
|
24
|
+
$ gem install krypter
|
25
|
+
```
|
26
|
+
|
6
27
|
Usage
|
7
28
|
-----
|
8
29
|
|
@@ -39,16 +60,40 @@ to prevent tampering and chosen ciphertext attacks.
|
|
39
60
|
The defaults can be changed when instantiating the encryptor object.
|
40
61
|
|
41
62
|
```ruby
|
42
|
-
encryptor =
|
63
|
+
encryptor = Krypter.new(secret,
|
43
64
|
cipher: "aes-256-cbc",
|
44
65
|
digest: "SHA256",
|
45
66
|
separator: "--"
|
46
67
|
)
|
47
68
|
```
|
48
69
|
|
49
|
-
|
70
|
+
Contributing
|
50
71
|
------------
|
51
72
|
|
73
|
+
Fork the project with:
|
74
|
+
|
52
75
|
```
|
53
|
-
$
|
76
|
+
$ git clone git@gitlab.com:frodsan/krypter.git
|
77
|
+
```
|
78
|
+
|
79
|
+
To install dependencies, use:
|
80
|
+
|
54
81
|
```
|
82
|
+
$ bundle install
|
83
|
+
```
|
84
|
+
|
85
|
+
To run the test suite, do:
|
86
|
+
|
87
|
+
```
|
88
|
+
$ rake test
|
89
|
+
```
|
90
|
+
|
91
|
+
For bug reports and pull requests, use [GitLab][issues].
|
92
|
+
|
93
|
+
License
|
94
|
+
-------
|
95
|
+
|
96
|
+
Krypter is released under the [MIT License][mit].
|
97
|
+
|
98
|
+
[mit]: http://www.opensource.org/licenses/MIT
|
99
|
+
[issues]: https://gitlab.com/frodsan/krypter/issues
|
data/lib/krypter.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "base64"
|
2
3
|
require "openssl"
|
3
4
|
|
@@ -5,7 +6,12 @@ class Krypter
|
|
5
6
|
InvalidSignature = Class.new(StandardError)
|
6
7
|
InvalidMessage = Class.new(StandardError)
|
7
8
|
|
8
|
-
def initialize(
|
9
|
+
def initialize(
|
10
|
+
secret,
|
11
|
+
cipher: "aes-256-cbc",
|
12
|
+
digest: "SHA256",
|
13
|
+
separator: "--"
|
14
|
+
)
|
9
15
|
@cipher = cipher
|
10
16
|
@digest = digest
|
11
17
|
@separator = separator
|
@@ -14,21 +20,17 @@ class Krypter
|
|
14
20
|
end
|
15
21
|
|
16
22
|
def encrypt(message)
|
17
|
-
|
23
|
+
sign(_encrypt(message))
|
18
24
|
end
|
19
25
|
|
20
26
|
def decrypt(message)
|
21
|
-
ciphertext = verify(message)
|
22
|
-
|
23
|
-
if ciphertext
|
24
|
-
return _decrypt(ciphertext)
|
25
|
-
end
|
27
|
+
(ciphertext = verify(message)) && _decrypt(ciphertext)
|
26
28
|
end
|
27
29
|
|
28
30
|
private
|
29
31
|
|
30
32
|
def hmac(secret, message)
|
31
|
-
|
33
|
+
OpenSSL::HMAC.hexdigest(@digest, secret, message)
|
32
34
|
end
|
33
35
|
|
34
36
|
def _encrypt(message)
|
@@ -40,7 +42,7 @@ class Krypter
|
|
40
42
|
ciphertext = cipher.update(message)
|
41
43
|
ciphertext << cipher.final
|
42
44
|
|
43
|
-
|
45
|
+
[ciphertext, iv].join(@separator)
|
44
46
|
end
|
45
47
|
|
46
48
|
def _decrypt(encrypted)
|
@@ -63,11 +65,11 @@ class Krypter
|
|
63
65
|
encoded = Base64.strict_encode64(value)
|
64
66
|
signature = authenticate(encoded)
|
65
67
|
|
66
|
-
|
68
|
+
[encoded, signature].join(@separator)
|
67
69
|
end
|
68
70
|
|
69
71
|
def authenticate(message)
|
70
|
-
|
72
|
+
hmac(@sign_secret, message)
|
71
73
|
end
|
72
74
|
|
73
75
|
def verify(message)
|
@@ -91,6 +93,6 @@ class Krypter
|
|
91
93
|
result |= char ^ cmp[index]
|
92
94
|
end
|
93
95
|
|
94
|
-
|
96
|
+
result == 0
|
95
97
|
end
|
96
98
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "bundler/setup"
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "minitest/pride"
|
5
|
+
require "minitest/sugar"
|
6
|
+
require "securerandom"
|
7
|
+
require_relative "../lib/krypter"
|
8
|
+
|
9
|
+
class KrypterTest < Minitest::Test
|
10
|
+
setup do
|
11
|
+
@encryptor = Krypter.new(SecureRandom.hex(32))
|
12
|
+
end
|
13
|
+
|
14
|
+
test "encrypts and decrypts" do
|
15
|
+
encrypted = @encryptor.encrypt("message")
|
16
|
+
decrypted = @encryptor.decrypt(encrypted)
|
17
|
+
|
18
|
+
assert_equal("message", decrypted)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "encrypt returns different ciphertexts" do
|
22
|
+
encrypted1 = @encryptor.encrypt("message")
|
23
|
+
encrypted2 = @encryptor.encrypt("message")
|
24
|
+
|
25
|
+
assert encrypted1 != encrypted2
|
26
|
+
end
|
27
|
+
|
28
|
+
test "wrong signature" do
|
29
|
+
encrypted = @encryptor.encrypt("message")
|
30
|
+
separator = @encryptor.instance_variable_get(:@separator)
|
31
|
+
ciphertext, signature = encrypted.split(separator)
|
32
|
+
|
33
|
+
message = [signature, ciphertext] * separator
|
34
|
+
assert_raises(Krypter::InvalidSignature) do
|
35
|
+
@encryptor.decrypt(message)
|
36
|
+
end
|
37
|
+
|
38
|
+
message = [ciphertext, signature.reverse] * separator
|
39
|
+
assert_raises(Krypter::InvalidSignature) do
|
40
|
+
@encryptor.decrypt(message)
|
41
|
+
end
|
42
|
+
|
43
|
+
message = [ciphertext.reverse, signature] * separator
|
44
|
+
assert_raises(Krypter::InvalidSignature) do
|
45
|
+
@encryptor.decrypt(message)
|
46
|
+
end
|
47
|
+
|
48
|
+
message = [ciphertext.reverse, signature.reverse] * separator
|
49
|
+
assert_raises(Krypter::InvalidSignature) do
|
50
|
+
@encryptor.decrypt(message)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
test "tampered data" do
|
55
|
+
encrypted = @encryptor.encrypt("message")
|
56
|
+
separator = @encryptor.instance_variable_get(:@separator)
|
57
|
+
|
58
|
+
ciphertext, iv = @encryptor.send(:verify, encrypted).split(separator)
|
59
|
+
|
60
|
+
message = @encryptor.send(:sign, [iv, ciphertext] * separator)
|
61
|
+
assert_raises(Krypter::InvalidMessage) do
|
62
|
+
@encryptor.decrypt(message)
|
63
|
+
end
|
64
|
+
|
65
|
+
message = @encryptor.send(:sign, [ciphertext, iv.reverse] * separator)
|
66
|
+
assert_raises(Krypter::InvalidMessage) do
|
67
|
+
@encryptor.decrypt(message)
|
68
|
+
end
|
69
|
+
|
70
|
+
message = @encryptor.send(:sign, [ciphertext.reverse, iv] * separator)
|
71
|
+
assert_raises(Krypter::InvalidMessage) do
|
72
|
+
@encryptor.decrypt(message)
|
73
|
+
end
|
74
|
+
|
75
|
+
str = [ciphertext.reverse, iv.reverse] * separator
|
76
|
+
|
77
|
+
message = @encryptor.send(:sign, str)
|
78
|
+
|
79
|
+
assert_raises(Krypter::InvalidMessage) do
|
80
|
+
@encryptor.decrypt(message)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
metadata
CHANGED
@@ -1,46 +1,82 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: krypter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francesco Rodríguez
|
8
|
-
- Mayn Kjær
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-04-08 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
14
|
+
name: minitest
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
16
|
requirements:
|
18
|
-
- - "
|
17
|
+
- - "~>"
|
19
18
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
19
|
+
version: '5.8'
|
21
20
|
type: :development
|
22
21
|
prerelease: false
|
23
22
|
version_requirements: !ruby/object:Gem::Requirement
|
24
23
|
requirements:
|
25
|
-
- - "
|
24
|
+
- - "~>"
|
26
25
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
version: '5.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest-sugar
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.39'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.39'
|
69
|
+
description: Load environment variables from .env
|
70
|
+
email: hello@frodsan.com
|
32
71
|
executables: []
|
33
72
|
extensions: []
|
34
73
|
extra_rdoc_files: []
|
35
74
|
files:
|
36
|
-
- ".gems"
|
37
75
|
- LICENSE
|
38
76
|
- README.md
|
39
|
-
- krypter.gemspec
|
40
77
|
- lib/krypter.rb
|
41
|
-
-
|
42
|
-
|
43
|
-
homepage: https://github.com/harmoni-io/krypter
|
78
|
+
- test/krypter_test.rb
|
79
|
+
homepage: https://gitlab.com/frodsan/krypter
|
44
80
|
licenses:
|
45
81
|
- MIT
|
46
82
|
metadata: {}
|
@@ -60,8 +96,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
96
|
version: '0'
|
61
97
|
requirements: []
|
62
98
|
rubyforge_project:
|
63
|
-
rubygems_version: 2.
|
99
|
+
rubygems_version: 2.5.1
|
64
100
|
signing_key:
|
65
101
|
specification_version: 4
|
66
|
-
summary:
|
67
|
-
test_files:
|
102
|
+
summary: Load environment variables from .env
|
103
|
+
test_files:
|
104
|
+
- test/krypter_test.rb
|
data/.gems
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
cutest -v 1.2.1
|
data/krypter.gemspec
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |s|
|
2
|
-
s.name = "krypter"
|
3
|
-
s.version = "1.0.0"
|
4
|
-
s.summary = "Encrypts and signs messages."
|
5
|
-
s.description = s.summary
|
6
|
-
s.authors = ["Francesco Rodríguez", "Mayn Kjær"]
|
7
|
-
s.email = ["frodsan@me.com", "mayn.kjaer@gmail.com"]
|
8
|
-
s.homepage = "https://github.com/harmoni-io/krypter"
|
9
|
-
s.license = "MIT"
|
10
|
-
|
11
|
-
s.files = `git ls-files`.split("\n")
|
12
|
-
|
13
|
-
s.add_development_dependency "cutest"
|
14
|
-
end
|
data/makefile
DELETED
data/test/krypter.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
require "cutest"
|
2
|
-
require "securerandom"
|
3
|
-
require_relative "../lib/krypter"
|
4
|
-
|
5
|
-
setup do
|
6
|
-
Krypter.new(SecureRandom.hex(32))
|
7
|
-
end
|
8
|
-
|
9
|
-
test "encrypts and decrypts" do |encryptor|
|
10
|
-
encrypted = encryptor.encrypt("message")
|
11
|
-
decrypted = encryptor.decrypt(encrypted)
|
12
|
-
|
13
|
-
assert_equal("message", decrypted)
|
14
|
-
end
|
15
|
-
|
16
|
-
test "encrypt returns different ciphertexts" do |encryptor|
|
17
|
-
encrypted1 = encryptor.encrypt("message")
|
18
|
-
encrypted2 = encryptor.encrypt("message")
|
19
|
-
|
20
|
-
assert encrypted1 != encrypted2
|
21
|
-
end
|
22
|
-
|
23
|
-
test "wrong signature" do |encryptor|
|
24
|
-
encrypted = encryptor.encrypt("message")
|
25
|
-
separator = encryptor.instance_variable_get(:@separator)
|
26
|
-
ciphertext, signature = encrypted.split(separator)
|
27
|
-
|
28
|
-
message = [signature, ciphertext] * separator
|
29
|
-
assert_raise(Krypter::InvalidSignature) do
|
30
|
-
encryptor.decrypt(message)
|
31
|
-
end
|
32
|
-
|
33
|
-
message = [ciphertext, signature.reverse] * separator
|
34
|
-
assert_raise(Krypter::InvalidSignature) do
|
35
|
-
encryptor.decrypt(message)
|
36
|
-
end
|
37
|
-
|
38
|
-
message = [ciphertext.reverse, signature] * separator
|
39
|
-
assert_raise(Krypter::InvalidSignature) do
|
40
|
-
encryptor.decrypt(message)
|
41
|
-
end
|
42
|
-
|
43
|
-
message = [ciphertext.reverse, signature.reverse] * separator
|
44
|
-
assert_raise(Krypter::InvalidSignature) do
|
45
|
-
encryptor.decrypt(message)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
test "tampered data" do |encryptor|
|
50
|
-
encrypted = encryptor.encrypt("message")
|
51
|
-
separator = encryptor.instance_variable_get(:@separator)
|
52
|
-
ciphertext, iv = encryptor.send(:verify, encrypted).split(separator)
|
53
|
-
|
54
|
-
message = encryptor.send(:sign, [iv, ciphertext] * separator)
|
55
|
-
assert_raise(Krypter::InvalidMessage) do
|
56
|
-
encryptor.decrypt(message)
|
57
|
-
end
|
58
|
-
|
59
|
-
message = encryptor.send(:sign, [ciphertext, iv.reverse] * separator)
|
60
|
-
assert_raise(Krypter::InvalidMessage) do
|
61
|
-
encryptor.decrypt(message)
|
62
|
-
end
|
63
|
-
|
64
|
-
message = encryptor.send(:sign, [ciphertext.reverse, iv] * separator)
|
65
|
-
assert_raise(Krypter::InvalidMessage) do
|
66
|
-
encryptor.decrypt(message)
|
67
|
-
end
|
68
|
-
|
69
|
-
message = encryptor.send(:sign, [ciphertext.reverse, iv.reverse] * separator)
|
70
|
-
assert_raise(Krypter::InvalidMessage) do
|
71
|
-
encryptor.decrypt(message)
|
72
|
-
end
|
73
|
-
end
|