fling 0.0.3 → 0.0.4
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/.rubocop.yml +3 -0
- data/CHANGES.md +4 -0
- data/fling.gemspec +1 -0
- data/lib/fling/box.rb +71 -0
- data/lib/fling/cli.rb +22 -0
- data/lib/fling/config.rb +25 -0
- data/lib/fling/version.rb +1 -1
- data/lib/fling.rb +1 -0
- data/spec/fling/box_spec.rb +21 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0c35e2e75fc50c7e36b7f39db74ba04321ce966
|
4
|
+
data.tar.gz: 660ff1f26c8262383c2706e84f06d6e23ce858e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a85101e0c8b75968d81bbe66e5155ea509a5181f941d448fc38504bb3404e7f4cce1cd6bd029f793e1ccc46333a70288b3a95c5ff6faafed6e8f566c12deba94
|
7
|
+
data.tar.gz: cdd34537276aa1a3f4ae03a81ae4f0a051cc81a390e79d6fda0ebe583dcc922196fcb6f1b633d2beec75a5e0f69dc43ee00dddc0f7440fa4d48fa4193ae006b2
|
data/.rubocop.yml
CHANGED
data/CHANGES.md
CHANGED
data/fling.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_runtime_dependency "thor"
|
22
22
|
spec.add_runtime_dependency "colorize"
|
23
23
|
spec.add_runtime_dependency "base32"
|
24
|
+
spec.add_runtime_dependency "rbnacl-libsodium"
|
24
25
|
|
25
26
|
spec.add_development_dependency "bundler", "~> 1.9"
|
26
27
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/lib/fling/box.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require "json"
|
2
|
+
require "rbnacl/libsodium"
|
3
|
+
|
4
|
+
module Fling
|
5
|
+
# Simple encryption with password-derived keys
|
6
|
+
class Box
|
7
|
+
attr_reader :key, :fingerprint
|
8
|
+
|
9
|
+
SALT_SIZE = 32
|
10
|
+
FINGERPRINT_SIZE = 32
|
11
|
+
|
12
|
+
SCRYPT_OPSLIMIT = 2**25
|
13
|
+
SCRYPT_MEMLIMIT = 2**30
|
14
|
+
|
15
|
+
def self.encrypt(password, plaintext, options = {})
|
16
|
+
salt = RbNaCl::Random.random_bytes(SALT_SIZE)
|
17
|
+
box = new(password, salt, options)
|
18
|
+
salt + box.encrypt(plaintext)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.decrypt(password, ciphertext, options = {})
|
22
|
+
salt = ciphertext[0, SALT_SIZE]
|
23
|
+
ciphertext = ciphertext[SALT_SIZE, ciphertext.length - SALT_SIZE]
|
24
|
+
box = new(password, salt, options)
|
25
|
+
box.decrypt(ciphertext)
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(password, salt, options = {})
|
29
|
+
opts = {
|
30
|
+
scrypt_opslimit: SCRYPT_OPSLIMIT,
|
31
|
+
scrypt_memlimit: SCRYPT_MEMLIMIT
|
32
|
+
}.merge(options)
|
33
|
+
|
34
|
+
@key = RbNaCl::PasswordHash.scrypt(
|
35
|
+
password.force_encoding("BINARY"),
|
36
|
+
salt.force_encoding("BINARY"),
|
37
|
+
opts[:scrypt_opslimit],
|
38
|
+
opts[:scrypt_memlimit],
|
39
|
+
RbNaCl::SecretBox::KEYBYTES
|
40
|
+
)
|
41
|
+
|
42
|
+
@fingerprint = Encoding.encode(RbNaCl::Hash.blake2b(@key, digest_size: FINGERPRINT_SIZE))
|
43
|
+
end
|
44
|
+
|
45
|
+
def encrypt(data = {})
|
46
|
+
# Ensure data is a simple flat hash of strings
|
47
|
+
data = data.map do |key, value|
|
48
|
+
fail TypeError, "bad key: #{key.inspect}" unless key.is_a?(String) || key.is_a?(Symbol)
|
49
|
+
fail TypeError, "bad value: #{value.inspect}" unless value.is_a?(String)
|
50
|
+
[key.to_s, value]
|
51
|
+
end.flatten
|
52
|
+
|
53
|
+
json = JSON.generate(Hash[*data])
|
54
|
+
encryption_box.encrypt(json.force_encoding("BINARY"))
|
55
|
+
end
|
56
|
+
|
57
|
+
def decrypt(ciphertext)
|
58
|
+
json = encryption_box.decrypt(ciphertext.force_encoding("BINARY"))
|
59
|
+
JSON.parse(json)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Hide contents of instance variables from inspection
|
63
|
+
alias_method :inspect, :to_s
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def encryption_box
|
68
|
+
RbNaCl::SimpleBox.from_secret_key(@key)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/fling/cli.rb
CHANGED
@@ -9,5 +9,27 @@ module Fling
|
|
9
9
|
require "fling/setup"
|
10
10
|
Setup.run
|
11
11
|
end
|
12
|
+
|
13
|
+
desc "provision FILE", "Create encrypted Fling configuration"
|
14
|
+
def provision(config_file)
|
15
|
+
say "Provisioning #{config_file}"
|
16
|
+
|
17
|
+
introducer = ask "What is your introducer FURL? (e.g. pb://...)"
|
18
|
+
dropcap = ask "What is your 'dropcap'? (e.g. URI:DIR2:...)"
|
19
|
+
password = ask "Please enter a password to encrypt the config:", echo: false
|
20
|
+
|
21
|
+
say "\nGenerating encrypted config, please wait..."
|
22
|
+
|
23
|
+
config = Config.generate_encrypted(
|
24
|
+
password,
|
25
|
+
"introducer" => introducer,
|
26
|
+
"dropcap" => dropcap,
|
27
|
+
"convergence" => Encoding.encode(RbNaCl::Random.random_bytes(32)),
|
28
|
+
"salt" => Encoding.encode(RbNaCl::Random.random_bytes(32))
|
29
|
+
)
|
30
|
+
|
31
|
+
File.open(config_file, "w") { |file| file << config }
|
32
|
+
say "Created #{config_file}"
|
33
|
+
end
|
12
34
|
end
|
13
35
|
end
|
data/lib/fling/config.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require "json"
|
2
2
|
require "uri"
|
3
|
+
require "base64"
|
4
|
+
require "rbnacl"
|
3
5
|
|
4
6
|
module Fling
|
5
7
|
# Configuration for the local Tahoe cluster
|
@@ -17,6 +19,20 @@ module Fling
|
|
17
19
|
new(JSON.parse(json))
|
18
20
|
end
|
19
21
|
|
22
|
+
# Generate an encrypted configuration
|
23
|
+
def self.generate_encrypted(password, config)
|
24
|
+
ciphertext = Box.encrypt(password, generate_json(config))
|
25
|
+
|
26
|
+
"-----BEGIN ENCRYPTED FLING CONFIGURATION-----\n" +
|
27
|
+
Base64.encode64(ciphertext) +
|
28
|
+
"------END ENCRYPTED FLING CONFIGURATION------\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Generate a JSON configuration
|
32
|
+
def self.generate_json(config)
|
33
|
+
new(config).as_json
|
34
|
+
end
|
35
|
+
|
20
36
|
def initialize(options = {})
|
21
37
|
CONFIG_KEYS.each do |key|
|
22
38
|
fail ArgumentError, "missing key: #{key}" unless options[key]
|
@@ -38,5 +54,14 @@ module Fling
|
|
38
54
|
fail ConfigError, "bad #{key} (wrong size): #{b32_value}" if value.size != 32
|
39
55
|
end
|
40
56
|
end
|
57
|
+
|
58
|
+
def as_json
|
59
|
+
{
|
60
|
+
introducer: introducer,
|
61
|
+
convergence: convergence,
|
62
|
+
salt: salt,
|
63
|
+
dropcap: dropcap
|
64
|
+
}
|
65
|
+
end
|
41
66
|
end
|
42
67
|
end
|
data/lib/fling/version.rb
CHANGED
data/lib/fling.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Fling::Box do
|
4
|
+
let(:example_password) { "artifical accept common any later" }
|
5
|
+
let(:example_salt) { "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
|
6
|
+
let(:example_key) { "dzneyh62qzzmsuvglnmmliupc3cwmdptlyz63saxp6ktl5sojzca" }
|
7
|
+
let(:example_fingerprint) { "3rqs343l5icb4fbx4na3fgjwqij7rntba3dprkppjst7r7enxurq" }
|
8
|
+
let(:example_message) { Hash.new(foo: "x", bar: "y", baz: "z") }
|
9
|
+
|
10
|
+
let(:example_box) { described_class.new(example_password, example_salt) }
|
11
|
+
|
12
|
+
it "derives keys" do
|
13
|
+
expect(Fling::Encoding.encode(example_box.key)).to eq example_key
|
14
|
+
expect(example_box.fingerprint).to eq example_fingerprint
|
15
|
+
end
|
16
|
+
|
17
|
+
it "encrypts and decrypts hashes" do
|
18
|
+
ciphertext = example_box.encrypt(example_message)
|
19
|
+
expect(example_box.decrypt(ciphertext)).to eq example_message
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rbnacl-libsodium
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: bundler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,12 +133,14 @@ files:
|
|
119
133
|
- bin/setup
|
120
134
|
- fling.gemspec
|
121
135
|
- lib/fling.rb
|
136
|
+
- lib/fling/box.rb
|
122
137
|
- lib/fling/cli.rb
|
123
138
|
- lib/fling/config.rb
|
124
139
|
- lib/fling/encoding.rb
|
125
140
|
- lib/fling/setup.rb
|
126
141
|
- lib/fling/version.rb
|
127
142
|
- spec/fixtures/fling.json
|
143
|
+
- spec/fling/box_spec.rb
|
128
144
|
- spec/fling/config_spec.rb
|
129
145
|
- spec/fling/encoding_spec.rb
|
130
146
|
- spec/fling_spec.rb
|