ece 0.1.0
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 +7 -0
- data/.gitignore +10 -0
- data/Gemfile +4 -0
- data/README.md +40 -0
- data/Rakefile +2 -0
- data/ece.gemspec +23 -0
- data/lib/ece.rb +3 -0
- data/lib/ece/ece.rb +89 -0
- data/lib/ece/version.rb +3 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 44649fdca6ff58ef3b0831277607fa979a2c206c
|
4
|
+
data.tar.gz: 8197c1f1d10916433b2ef9a42fce6fa4b47c12df
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f6e325e8147ed9d6f60fef039ce81fb632b01499b9e662b8cb5d20612714d0fbef19ec89eee9563580ce01bb7d6a7ff9278d0f8ace6162a63f2818faf656b202
|
7
|
+
data.tar.gz: 4cde40d586d950843e4e853a7c3f8d5c8137bdad88e5faa751380a59aba5e74d7e2cc1a5cdda5de83ef9e2ca6c9d1c14fac6cc8db19420112d76e8aedb0900cc
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Ece
|
2
|
+
|
3
|
+
Ruby implementation of encrypted content-encoding.
|
4
|
+
|
5
|
+
https://tools.ietf.org/html/draft-thomson-http-encryption-02
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'ece'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install ece
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
```
|
26
|
+
require 'ece'
|
27
|
+
|
28
|
+
key = Random.new.bytes(16)
|
29
|
+
salt = Random.new.bytes(16)
|
30
|
+
data = "Your very private data"
|
31
|
+
|
32
|
+
Ece.encrypt(data, key: key, salt: salt)
|
33
|
+
|
34
|
+
Ece.decrypt(data, key: key, salt: salt)
|
35
|
+
```
|
36
|
+
Data can be bytestring as well.
|
37
|
+
## Contributing
|
38
|
+
|
39
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/randomlogin/ece.
|
40
|
+
|
data/Rakefile
ADDED
data/ece.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ece/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ece"
|
8
|
+
spec.version = Ece::VERSION
|
9
|
+
spec.authors = ["Alexander Shevtsov"]
|
10
|
+
spec.email = ["randomlogin76@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Ruby implementation of encrypted content-encoding"
|
13
|
+
spec.homepage = "https://github.com/randomlogin/ece"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
|
+
spec.bindir = "exe"
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
spec.add_dependency 'hkdf'
|
23
|
+
end
|
data/lib/ece.rb
ADDED
data/lib/ece/ece.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'hkdf'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
#fore testing purposes only
|
6
|
+
#TODO: variable padding
|
7
|
+
|
8
|
+
class Ece
|
9
|
+
|
10
|
+
KEY_LENGTH=16
|
11
|
+
TAG_LENGTH=16
|
12
|
+
NONCE_LENGTH=12
|
13
|
+
|
14
|
+
def self.hmac_hash(key, input)
|
15
|
+
digest = OpenSSL::Digest.new('sha256')
|
16
|
+
OpenSSL::HMAC.digest(digest, key, input)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.hkdf_extract(salt, ikm)
|
20
|
+
hmac_hash(salt,ikm)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.extract_key(params)
|
24
|
+
raise "Salt must be 16-bytes long" unless params[:salt].length==16
|
25
|
+
key = HKDF.new(params[:key], salt: params[:salt], algorithm: 'sha256', info: "Content-Encoding: aesgcm128")
|
26
|
+
nonce = HKDF.new(params[:key], salt: params[:salt], algorithm: 'sha256', info: "Content-Encoding: nonce")
|
27
|
+
{key: key.next_bytes(KEY_LENGTH), nonce: nonce.next_bytes(NONCE_LENGTH)}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.generate_nonce(nonce, counter)
|
31
|
+
raise "Nonce must be #{NONCE_LENGTH} bytes long." unless nonce.length == NONCE_LENGTH
|
32
|
+
output = nonce.dup
|
33
|
+
integer = nonce[-6..-1].unpack('B*')[0].to_i(2) #taking last 6 bytes, treating as integer
|
34
|
+
x = ((integer ^ counter) & 0xffffff) + ((((integer / 0x1000000) ^ (counter / 0x1000000)) & 0xffffff) * 0x1000000)
|
35
|
+
output[-6..-1] = [x.to_s(16)].pack('H*')
|
36
|
+
output
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.encrypt_record(params, counter, buffer, pad=0)
|
40
|
+
raise "Key must be #{KEY_LENGTH} bytes long" unless params[:key].length == KEY_LENGTH
|
41
|
+
gcm = OpenSSL::Cipher.new('aes-128-gcm')
|
42
|
+
gcm.encrypt
|
43
|
+
gcm.key = params[:key]
|
44
|
+
gcm.iv = generate_nonce(params[:nonce], counter)
|
45
|
+
enc = gcm.update("\x00"+buffer) + gcm.final + gcm.auth_tag #enc = gcm.update("\x00"*pad+buffer)+gcm.final + gcm.auth_tag padding is not fully implemented for now
|
46
|
+
enc
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.encrypt(data, params)
|
50
|
+
key = extract_key(params)
|
51
|
+
rs = 4095 #look TODO
|
52
|
+
result = ""
|
53
|
+
counter = 0
|
54
|
+
(0..data.length).step(rs) do |i|
|
55
|
+
block = encrypt_record(key, counter, data[i..i+rs-1])
|
56
|
+
result += block
|
57
|
+
counter +=1
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.decrypt_record(params, counter, buffer, pad=0)
|
63
|
+
raise "Key must be #{KEY_LENGTH} bytes long" unless params[:key].length == KEY_LENGTH
|
64
|
+
gcm = OpenSSL::Cipher.new('aes-128-gcm')
|
65
|
+
gcm.decrypt
|
66
|
+
gcm.key = params[:key]
|
67
|
+
gcm.iv = generate_nonce(params[:nonce], counter)
|
68
|
+
gcm.auth_tag = buffer[-16..-1]
|
69
|
+
decrypted = gcm.update(buffer[0..-17]) + gcm.final
|
70
|
+
#padding = decrypted[0]
|
71
|
+
#padding_length = decrypted[0].unpack("C")
|
72
|
+
#raise Err unless padding = "\x00"*padding_length
|
73
|
+
decrypted[1..-1]
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.decrypt(data, params)
|
77
|
+
key = extract_key(params)
|
78
|
+
rs = 4096+16 #not changeable for now
|
79
|
+
result = ""
|
80
|
+
counter = 0
|
81
|
+
(0..data.length).step(rs) do |i|
|
82
|
+
block = decrypt_record(key, counter, data[i..i+rs-1])
|
83
|
+
result += block
|
84
|
+
counter +=1
|
85
|
+
end
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/lib/ece/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ece
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Shevtsov
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-21 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: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hkdf
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- randomlogin76@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- ece.gemspec
|
67
|
+
- lib/ece.rb
|
68
|
+
- lib/ece/ece.rb
|
69
|
+
- lib/ece/version.rb
|
70
|
+
homepage: https://github.com/randomlogin/ece
|
71
|
+
licenses: []
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.4.8
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Ruby implementation of encrypted content-encoding
|
93
|
+
test_files: []
|