keyrack 0.3.0.pre → 0.3.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 +17 -0
- data/Gemfile +8 -15
- data/Guardfile +6 -0
- data/LICENSE.txt +4 -2
- data/Rakefile +2 -56
- data/keyrack.gemspec +22 -104
- data/lib/keyrack.rb +9 -1
- data/lib/keyrack/database.rb +64 -98
- data/lib/keyrack/event.rb +13 -0
- data/lib/keyrack/exceptions.rb +4 -0
- data/lib/keyrack/group.rb +225 -0
- data/lib/keyrack/migrator.rb +45 -0
- data/lib/keyrack/runner.rb +98 -44
- data/lib/keyrack/site.rb +92 -0
- data/lib/keyrack/ui/console.rb +234 -95
- data/lib/keyrack/utils.rb +0 -18
- data/lib/keyrack/version.rb +3 -0
- data/test/fixtures/database-3.dat +0 -0
- data/test/helper.rb +11 -1
- data/test/integration/test_interactive_console.rb +139 -0
- data/test/unit/store/test_filesystem.rb +21 -0
- data/test/unit/store/test_ssh.rb +32 -0
- data/test/unit/test_database.rb +201 -0
- data/test/unit/test_event.rb +41 -0
- data/test/unit/test_group.rb +703 -0
- data/test/unit/test_migrator.rb +105 -0
- data/test/unit/test_runner.rb +407 -0
- data/test/unit/test_site.rb +181 -0
- data/test/unit/test_store.rb +13 -0
- data/test/unit/test_utils.rb +8 -0
- data/test/unit/ui/test_console.rb +495 -0
- metadata +98 -94
- data/Gemfile.lock +0 -45
- data/TODO +0 -4
- data/VERSION +0 -1
- data/features/console.feature +0 -103
- data/features/step_definitions/keyrack_steps.rb +0 -61
- data/features/support/env.rb +0 -16
- data/test/fixtures/aes +0 -0
- data/test/fixtures/config.yml +0 -4
- data/test/fixtures/id_rsa +0 -54
- data/test/keyrack/store/test_filesystem.rb +0 -25
- data/test/keyrack/store/test_ssh.rb +0 -36
- data/test/keyrack/test_database.rb +0 -111
- data/test/keyrack/test_runner.rb +0 -111
- data/test/keyrack/test_store.rb +0 -15
- data/test/keyrack/test_utils.rb +0 -41
- data/test/keyrack/ui/test_console.rb +0 -308
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: efd84a41e075f8edc77908a7bb71ea21a3590af2
|
4
|
+
data.tar.gz: 3714b2f53884956c10b480ba128efcb58e463727
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d53d8a1ca8ce99b1147907d48d87a6e20a95efe4fcbe13af11d777e179ec294994b6aa903d4f189f27cda35bea060c7cb181e70d1f72f3ff9332b7fe799b9d85
|
7
|
+
data.tar.gz: e0d31fee61321d665a632ed2e59259778a37824ba19136834c3ece001ca3ef39798fcbe3605862e33a80bac26a1f6872cbbb2db1eb746cd9374c283f0cb9b56d
|
data/.gitignore
ADDED
data/Gemfile
CHANGED
@@ -1,18 +1,11 @@
|
|
1
|
-
source
|
2
|
-
|
3
|
-
#
|
4
|
-
|
5
|
-
gem 'net-scp', :require => 'net/scp'
|
6
|
-
gem 'highline'
|
7
|
-
gem 'copier'
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in keyrack.gemspec
|
4
|
+
gemspec
|
8
5
|
|
9
|
-
# Add dependencies to develop your gem here.
|
10
|
-
# Include everything needed to run rake, tests, features, etc.
|
11
6
|
group :development do
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem
|
15
|
-
gem
|
16
|
-
gem "cucumber"
|
17
|
-
gem 'test-unit'
|
7
|
+
gem 'guard-test'
|
8
|
+
gem 'rb-inotify'
|
9
|
+
gem 'ffi-ncurses'
|
10
|
+
gem 'rake'
|
18
11
|
end
|
data/Guardfile
ADDED
data/LICENSE.txt
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2012 Jeremy Stephens
|
2
|
+
|
3
|
+
MIT License
|
2
4
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
6
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,63 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
-
gem.name = "keyrack"
|
16
|
-
gem.homepage = "http://github.com/viking/keyrack"
|
17
|
-
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{Simple password manager}
|
19
|
-
gem.description = %Q{Simple password manager with local/remote database storage and RSA encryption.}
|
20
|
-
gem.email = "viking@pillageandplunder.net"
|
21
|
-
gem.authors = ["Jeremy Stephens"]
|
22
|
-
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
-
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
-
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
-
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
26
|
-
# gem.add_runtime_dependency 'net-scp'
|
27
|
-
# gem.add_runtime_dependency 'highline'
|
28
|
-
# gem.add_runtime_dependency 'clipboard'
|
29
|
-
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
30
|
-
# gem.add_development_dependency "bundler", "~> 1.0.0"
|
31
|
-
# gem.add_development_dependency "jeweler", "~> 1.5.1"
|
32
|
-
# gem.add_development_dependency "rcov", ">= 0"
|
33
|
-
# gem.add_development_dependency "mocha"
|
34
|
-
end
|
35
|
-
Jeweler::RubygemsDotOrgTasks.new
|
36
|
-
|
1
|
+
require "bundler/gem_tasks"
|
37
2
|
require 'rake/testtask'
|
3
|
+
|
38
4
|
Rake::TestTask.new(:test) do |test|
|
39
5
|
test.libs << 'lib' << 'test'
|
40
6
|
test.pattern = 'test/**/test_*.rb'
|
41
7
|
test.verbose = true
|
42
8
|
end
|
43
|
-
|
44
|
-
require 'rcov/rcovtask'
|
45
|
-
Rcov::RcovTask.new do |test|
|
46
|
-
test.libs << 'test'
|
47
|
-
test.pattern = 'test/**/test_*.rb'
|
48
|
-
test.verbose = true
|
49
|
-
end
|
50
|
-
|
51
9
|
task :default => :test
|
52
|
-
|
53
|
-
require 'rdoc/task'
|
54
|
-
Rake::RDocTask.new do |rdoc|
|
55
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
56
|
-
|
57
|
-
rdoc.rdoc_dir = 'rdoc'
|
58
|
-
rdoc.title = "keyrack #{version}"
|
59
|
-
rdoc.rdoc_files.include('README*')
|
60
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
61
|
-
end
|
62
|
-
|
63
|
-
task :build => :gemspec
|
data/keyrack.gemspec
CHANGED
@@ -1,110 +1,28 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'keyrack/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "keyrack"
|
8
|
+
gem.version = Keyrack::VERSION
|
9
|
+
gem.authors = ["Jeremy Stephens"]
|
10
|
+
gem.email = ["viking@pillageandplunder.net"]
|
11
|
+
gem.description = %q{Simple password manager with local/remote database storage and scrypt encryption.}
|
12
|
+
gem.summary = %q{Simple password manager}
|
13
|
+
gem.homepage = "http://github.com/viking/keyrack"
|
9
14
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
s.email = "viking@pillageandplunder.net"
|
15
|
-
s.executables = ["keyrack"]
|
16
|
-
s.extra_rdoc_files = [
|
17
|
-
"LICENSE.txt",
|
18
|
-
"README.rdoc",
|
19
|
-
"TODO"
|
20
|
-
]
|
21
|
-
s.files = [
|
22
|
-
".document",
|
23
|
-
".rvmrc",
|
24
|
-
"Gemfile",
|
25
|
-
"Gemfile.lock",
|
26
|
-
"LICENSE.txt",
|
27
|
-
"README.rdoc",
|
28
|
-
"Rakefile",
|
29
|
-
"TODO",
|
30
|
-
"VERSION",
|
31
|
-
"bin/keyrack",
|
32
|
-
"features/console.feature",
|
33
|
-
"features/step_definitions/keyrack_steps.rb",
|
34
|
-
"features/support/env.rb",
|
35
|
-
"keyrack.gemspec",
|
36
|
-
"lib/keyrack.rb",
|
37
|
-
"lib/keyrack/database.rb",
|
38
|
-
"lib/keyrack/runner.rb",
|
39
|
-
"lib/keyrack/store.rb",
|
40
|
-
"lib/keyrack/store/filesystem.rb",
|
41
|
-
"lib/keyrack/store/ssh.rb",
|
42
|
-
"lib/keyrack/ui.rb",
|
43
|
-
"lib/keyrack/ui/console.rb",
|
44
|
-
"lib/keyrack/utils.rb",
|
45
|
-
"test/fixtures/aes",
|
46
|
-
"test/fixtures/config.yml",
|
47
|
-
"test/fixtures/foo.txt",
|
48
|
-
"test/fixtures/id_rsa",
|
49
|
-
"test/helper.rb",
|
50
|
-
"test/keyrack/store/test_filesystem.rb",
|
51
|
-
"test/keyrack/store/test_ssh.rb",
|
52
|
-
"test/keyrack/test_database.rb",
|
53
|
-
"test/keyrack/test_runner.rb",
|
54
|
-
"test/keyrack/test_store.rb",
|
55
|
-
"test/keyrack/test_utils.rb",
|
56
|
-
"test/keyrack/ui/test_console.rb"
|
57
|
-
]
|
58
|
-
s.homepage = "http://github.com/viking/keyrack"
|
59
|
-
s.licenses = ["MIT"]
|
60
|
-
s.require_paths = ["lib"]
|
61
|
-
s.rubygems_version = "1.8.11"
|
62
|
-
s.summary = "Simple password manager"
|
63
|
-
s.test_files = [
|
64
|
-
"test/helper.rb",
|
65
|
-
"test/keyrack/store/test_filesystem.rb",
|
66
|
-
"test/keyrack/store/test_ssh.rb",
|
67
|
-
"test/keyrack/test_database.rb",
|
68
|
-
"test/keyrack/test_runner.rb",
|
69
|
-
"test/keyrack/test_store.rb",
|
70
|
-
"test/keyrack/test_utils.rb",
|
71
|
-
"test/keyrack/ui/test_console.rb"
|
72
|
-
]
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
73
19
|
|
74
|
-
|
75
|
-
|
20
|
+
gem.add_runtime_dependency 'net-scp'
|
21
|
+
gem.add_runtime_dependency 'highline'
|
22
|
+
gem.add_runtime_dependency 'clipboard'
|
23
|
+
gem.add_runtime_dependency 'scrypty'
|
76
24
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
s.add_runtime_dependency(%q<copier>, [">= 0"])
|
81
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
82
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
|
83
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
84
|
-
s.add_development_dependency(%q<mocha>, [">= 0"])
|
85
|
-
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
86
|
-
s.add_development_dependency(%q<test-unit>, [">= 0"])
|
87
|
-
else
|
88
|
-
s.add_dependency(%q<net-scp>, [">= 0"])
|
89
|
-
s.add_dependency(%q<highline>, [">= 0"])
|
90
|
-
s.add_dependency(%q<copier>, [">= 0"])
|
91
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
92
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
93
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
94
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
95
|
-
s.add_dependency(%q<cucumber>, [">= 0"])
|
96
|
-
s.add_dependency(%q<test-unit>, [">= 0"])
|
97
|
-
end
|
98
|
-
else
|
99
|
-
s.add_dependency(%q<net-scp>, [">= 0"])
|
100
|
-
s.add_dependency(%q<highline>, [">= 0"])
|
101
|
-
s.add_dependency(%q<copier>, [">= 0"])
|
102
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
103
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
|
104
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
105
|
-
s.add_dependency(%q<mocha>, [">= 0"])
|
106
|
-
s.add_dependency(%q<cucumber>, [">= 0"])
|
107
|
-
s.add_dependency(%q<test-unit>, [">= 0"])
|
108
|
-
end
|
25
|
+
gem.add_development_dependency 'bundler'
|
26
|
+
gem.add_development_dependency 'mocha'
|
27
|
+
gem.add_development_dependency 'test-unit'
|
109
28
|
end
|
110
|
-
|
data/lib/keyrack.rb
CHANGED
@@ -4,13 +4,21 @@ require 'optparse'
|
|
4
4
|
require 'securerandom'
|
5
5
|
require 'net/scp'
|
6
6
|
require 'highline'
|
7
|
-
require '
|
7
|
+
require 'clipboard'
|
8
|
+
require 'scrypty'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'digest'
|
8
11
|
|
9
12
|
module Keyrack
|
10
13
|
end
|
11
14
|
|
15
|
+
require File.dirname(__FILE__) + '/keyrack/exceptions'
|
12
16
|
require File.dirname(__FILE__) + '/keyrack/utils'
|
17
|
+
require File.dirname(__FILE__) + '/keyrack/event'
|
18
|
+
require File.dirname(__FILE__) + '/keyrack/site'
|
19
|
+
require File.dirname(__FILE__) + '/keyrack/group'
|
13
20
|
require File.dirname(__FILE__) + '/keyrack/database'
|
14
21
|
require File.dirname(__FILE__) + '/keyrack/store'
|
15
22
|
require File.dirname(__FILE__) + '/keyrack/ui'
|
16
23
|
require File.dirname(__FILE__) + '/keyrack/runner'
|
24
|
+
require File.dirname(__FILE__) + '/keyrack/migrator'
|
data/lib/keyrack/database.rb
CHANGED
@@ -1,126 +1,92 @@
|
|
1
1
|
module Keyrack
|
2
2
|
class Database
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
DEFAULT_ENCRYPT_OPTIONS = { :maxmem => 0, :maxmemfrac => 0.125, :maxtime => 5.0 }
|
4
|
+
DEFAULT_DECRYPT_OPTIONS = { :maxmem => 0, :maxmemfrac => 0.250, :maxtime => 10.0 }
|
5
|
+
VERSION = 4
|
6
|
+
|
7
|
+
def initialize(password, store, encrypt_options = {}, decrypt_options = {})
|
8
8
|
@dirty = false
|
9
|
+
@encrypt_options = DEFAULT_ENCRYPT_OPTIONS.merge(encrypt_options)
|
10
|
+
@decrypt_options = DEFAULT_DECRYPT_OPTIONS.merge(decrypt_options)
|
11
|
+
@store = store
|
12
|
+
@password = password_hash(password)
|
13
|
+
@database = decrypt(password)
|
14
|
+
setup_hooks
|
9
15
|
end
|
10
16
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
user_entry = site_entry.detect { |e| e[:username] == username }
|
18
|
-
if user_entry
|
19
|
-
# Update existing entry
|
20
|
-
user_entry[:password] = password
|
21
|
-
else
|
22
|
-
# Add new entry
|
23
|
-
site_entry.push({:username => username, :password => password})
|
24
|
-
end
|
25
|
-
elsif site_entry[:username] == username
|
26
|
-
# Update existing entry
|
27
|
-
site_entry[:password] = password
|
28
|
-
else
|
29
|
-
# Convert single entry into an array, then add new entry
|
30
|
-
hash[site] = [site_entry, {:username => username, :password => password}]
|
31
|
-
end
|
32
|
-
else
|
33
|
-
hash[site] = { :username => username, :password => password }
|
34
|
-
end
|
35
|
-
@dirty = true
|
17
|
+
def version
|
18
|
+
@database['version']
|
19
|
+
end
|
20
|
+
|
21
|
+
def top_group
|
22
|
+
@database['groups']['top']
|
36
23
|
end
|
37
24
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
25
|
+
def dirty?
|
26
|
+
@dirty
|
27
|
+
end
|
41
28
|
|
42
|
-
|
43
|
-
if
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
else
|
49
|
-
nil
|
50
|
-
end
|
29
|
+
def save(password)
|
30
|
+
if password_hash(password) == @password
|
31
|
+
@store.write(Scrypty.encrypt(@database.to_yaml, password,
|
32
|
+
*@encrypt_options.values_at(:maxmem, :maxmemfrac, :maxtime)))
|
33
|
+
@dirty = false
|
34
|
+
true
|
51
35
|
else
|
52
|
-
|
36
|
+
false
|
53
37
|
end
|
54
38
|
end
|
55
39
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
val = hash[key]
|
61
|
-
val.is_a?(Array) || (val.is_a?(Hash) && val.has_key?(:username))
|
62
|
-
end.sort
|
40
|
+
def change_password(current_password, new_password)
|
41
|
+
if password_hash(current_password) == @password
|
42
|
+
@password = password_hash(new_password)
|
43
|
+
true
|
63
44
|
else
|
64
|
-
|
65
|
-
[]
|
45
|
+
false
|
66
46
|
end
|
67
47
|
end
|
68
48
|
|
69
|
-
|
70
|
-
@data.keys.reject do |key|
|
71
|
-
val = @data[key]
|
72
|
-
val.is_a?(Array) || (val.is_a?(Hash) && val.has_key?(:username))
|
73
|
-
end.sort
|
74
|
-
end
|
49
|
+
private
|
75
50
|
|
76
|
-
def
|
77
|
-
|
51
|
+
def password_hash(password)
|
52
|
+
# Avoid storing the database password as-is in memory, but don't
|
53
|
+
# spend too much effort obfuscating it.
|
54
|
+
sha256 = Digest::SHA256.new
|
55
|
+
sha256.digest "#{password}-#{$$}"
|
78
56
|
end
|
79
57
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
58
|
+
def decrypt(password)
|
59
|
+
data = @store.read
|
60
|
+
if data
|
61
|
+
str = Scrypty.decrypt(data, password,
|
62
|
+
*@decrypt_options.values_at(:maxmem, :maxmemfrac, :maxtime))
|
63
|
+
hash = YAML.load(str)
|
64
|
+
migrated_hash = Migrator.run(hash)
|
65
|
+
if !migrated_hash.equal?(hash)
|
66
|
+
hash = migrated_hash
|
67
|
+
@dirty = true
|
68
|
+
end
|
86
69
|
|
87
|
-
|
88
|
-
|
89
|
-
|
70
|
+
top = Group.new
|
71
|
+
top.load(hash['groups']['top'])
|
72
|
+
hash['groups']['top'] = top
|
90
73
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
site_entry.delete_at(i)
|
97
|
-
hash[site] = site_entry[0]
|
98
|
-
when 1
|
99
|
-
hash.delete(site)
|
100
|
-
else
|
101
|
-
site_entry.delete_at(i)
|
102
|
-
end
|
74
|
+
hash
|
75
|
+
else
|
76
|
+
{'groups' => {'top' => Group.new('top')}, 'version' => VERSION}
|
77
|
+
end
|
78
|
+
end
|
103
79
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
108
|
-
elsif site_entry[:username] == username
|
109
|
-
hash.delete(site)
|
110
|
-
@dirty = true
|
80
|
+
def setup_hooks
|
81
|
+
@database['groups'].each_pair do |group_name, group|
|
82
|
+
add_group_hooks_for(group)
|
111
83
|
end
|
112
84
|
end
|
113
85
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
if data
|
118
|
-
cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC")
|
119
|
-
cipher.decrypt; cipher.key = @key; cipher.iv = @iv
|
120
|
-
Marshal.load(cipher.update(data) + cipher.final)
|
121
|
-
else
|
122
|
-
{}
|
123
|
-
end
|
86
|
+
def add_group_hooks_for(group)
|
87
|
+
group.after_event do |event|
|
88
|
+
@dirty = true
|
124
89
|
end
|
90
|
+
end
|
125
91
|
end
|
126
92
|
end
|