metafusion-crypto 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.
- data/lib/metafusion/crypto.rb +10 -0
- data/lib/metafusion/crypto/base.rb +132 -0
- data/lib/metafusion/crypto/meta.rb +57 -0
- data/lib/metafusion/crypto/version.rb +19 -0
- data/spec/metafusion/crypto/base_spec.rb +113 -0
- data/spec/metafusion/crypto/meta_spec.rb +90 -0
- data/spec/metafusion/crypto/version_spec.rb +19 -0
- metadata +53 -0
@@ -0,0 +1,132 @@
|
|
1
|
+
# Cryptography helper module <tt>Metafusion::Crypto</tt> as well as
|
2
|
+
# <tt>Metafusion::Crypto::PrivateKey</tt> and
|
3
|
+
# <tt>Metafusion::Crypto::DigitalSignature</tt> classes.
|
4
|
+
|
5
|
+
require 'openssl'
|
6
|
+
require 'digest/sha1'
|
7
|
+
|
8
|
+
# Module that contains Cryptography helper methods and the
|
9
|
+
# <tt>Metafusion::Crypto::Key</tt> class to be utilized in
|
10
|
+
# public key encryption.
|
11
|
+
module Metafusion::Crypto
|
12
|
+
|
13
|
+
# Generate private and public keys
|
14
|
+
# 1. <tt>private_file</tt> - file name of private key to generate (default = "rsa_key")
|
15
|
+
# 2. <tt>public_file</tt> - file name of public key to generate (default = "#{private_key}.pub")
|
16
|
+
# 3. <tt>bits</tt> - number of bits for key (default = 1024)
|
17
|
+
# 4. <tt>clean</tt> - specifies if existing key files should
|
18
|
+
# zapped and replaced by newly generated keys (default = true)
|
19
|
+
#
|
20
|
+
# Returns the private key generated.
|
21
|
+
#
|
22
|
+
# Usage:
|
23
|
+
# priv_key = Metafusion::Crypto.generate_key_pair
|
24
|
+
def self.generate_key_pair(private_file = "rsa_key",
|
25
|
+
public_file = "#{private_file}.pub",
|
26
|
+
bits = 512, clean = true)
|
27
|
+
if clean
|
28
|
+
File.delete(private_file) if File.exists?(private_file)
|
29
|
+
File.delete(public_file) if File.exists?(public_file)
|
30
|
+
end
|
31
|
+
private_key = OpenSSL::PKey::RSA.new(bits)
|
32
|
+
File.open(private_file, "w+") do |fp|
|
33
|
+
fp << private_key.to_s
|
34
|
+
end
|
35
|
+
File.open(public_file, "w+") do |fp|
|
36
|
+
fp << private_key.public_key.to_s
|
37
|
+
end
|
38
|
+
private_key
|
39
|
+
end
|
40
|
+
|
41
|
+
# <tt>Metafusion::Crypto::DigitalSignature</tt> provides easier
|
42
|
+
# a more streamlined API to create digital signatures without
|
43
|
+
# needing to know what that entails.
|
44
|
+
#
|
45
|
+
# Usage:
|
46
|
+
# include Metafusion::Crypto
|
47
|
+
# sig = DigitalSignature.from_file('rsa_key.pub', 'rsa_key')
|
48
|
+
# original_text = "my clear text message"
|
49
|
+
# crypted_text = sig.encrypt(original_text)
|
50
|
+
# plain_text = sig.decrypt(crypted_text)
|
51
|
+
# puts "It worked - let's celebrate!" if original_text == plain_text
|
52
|
+
class DigitalSignature
|
53
|
+
# Class methods
|
54
|
+
class << self
|
55
|
+
# Loads and constructs key from file <tt>private_filename</tt> given.
|
56
|
+
def from_keys(public_filename = "rsa_key.pub",
|
57
|
+
private_filename = nil)
|
58
|
+
return self.new(File.read(public_filename)) unless private_filename
|
59
|
+
self.new(File.read(public_filename), File.read(private_filename))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Constructor that takes the private and public key data.
|
64
|
+
# Only the <tt>public_data</tt> is required since not all
|
65
|
+
# <tt>DigitalSignature</tt> class clients will have access
|
66
|
+
# to the private key.
|
67
|
+
def initialize(public_data, private_data = nil)
|
68
|
+
@private_key = OpenSSL::PKey::RSA.new(private_data) if private_data
|
69
|
+
@public_key = OpenSSL::PKey::RSA.new(public_data)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Encrypts given <tt>text</tt> using key instance. This assumes
|
73
|
+
# that private key data was provided at instantiation step.
|
74
|
+
def encrypt(text)
|
75
|
+
Base64.encode64(@private_key.send("private_encrypt", text)) if @private_key
|
76
|
+
end
|
77
|
+
|
78
|
+
# Decrypts given <tt>text</tt> using key instance.
|
79
|
+
def decrypt(text)
|
80
|
+
@public_key.send("public_decrypt", Base64.decode64(text))
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
attr_accessor :private_key, :public_key
|
85
|
+
end
|
86
|
+
|
87
|
+
# <tt>Metafusion::Crypto::PrivateKey</tt> provides class that wraps
|
88
|
+
# the boilerplate private key encryption API from the Ruby
|
89
|
+
# standard library OpenSSL implementation.
|
90
|
+
#
|
91
|
+
# Usage:
|
92
|
+
# include Metafusion::Crypto
|
93
|
+
# pkey = PrivateKey.new('mypassphrase')
|
94
|
+
# original_text = 'Yo yo yo. What up dog?'
|
95
|
+
# crypted_text = pkey.encrypt(original_text)
|
96
|
+
# plain_text = pkey.decrypt(crypted_text)
|
97
|
+
# puts "Let's roll and celebrate - it worked" if original_text == plain_text
|
98
|
+
class PrivateKey
|
99
|
+
# Class methods
|
100
|
+
class << self
|
101
|
+
# Read in private key from file
|
102
|
+
def from_file(key_file = 'rsa_key')
|
103
|
+
return self.new(File.read(key_file))
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Creates <tt>PrivateKey</tt> instance given
|
108
|
+
# <tt>raw_passphrase</tt> and <tt>cipher</tt>.
|
109
|
+
# The default cipher is AES-256-CBC.
|
110
|
+
def initialize(raw_passphrase, cipher = "aes-256-cbc")
|
111
|
+
@encrypt_cipher = OpenSSL::Cipher::Cipher.new(cipher)
|
112
|
+
@decrypt_cipher = OpenSSL::Cipher::Cipher.new(cipher)
|
113
|
+
@key = Digest::SHA1.hexdigest(raw_passphrase)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Encrypts given <tt>text</tt> using key instance
|
117
|
+
def encrypt(text)
|
118
|
+
@encrypt_cipher.encrypt(@key)
|
119
|
+
s = @encrypt_cipher.update(text)
|
120
|
+
s << @encrypt_cipher.final
|
121
|
+
Base64.encode64(s)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Decrypts given <tt>text</tt> using key instance
|
125
|
+
def decrypt(text)
|
126
|
+
@decrypt_cipher.decrypt(@key)
|
127
|
+
s = @decrypt_cipher.update(Base64.decode64(text))
|
128
|
+
s << @decrypt_cipher.final
|
129
|
+
s
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# meta.rb contains <tt>Metafusion::Crypto::Meta</tt> and related classes that
|
2
|
+
# help define the metadata of the <tt>Metafusion::Crypto4R</tt> project.
|
3
|
+
|
4
|
+
require('rubygems')
|
5
|
+
require('erb')
|
6
|
+
|
7
|
+
class Metafusion::Crypto::Meta #:nodoc:
|
8
|
+
attr_accessor :root_dir
|
9
|
+
attr_reader :gem_spec, :project_files, :spec_files
|
10
|
+
|
11
|
+
# Initializer for Metafusion::Crypto::Meta class. Takes <tt>root_dir</tt> as parameter.
|
12
|
+
def initialize(root_dir)
|
13
|
+
@root_dir = root_dir
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns package information defined in <tt>root_dir</tt>/pkg-info.yml
|
17
|
+
def pkg_info
|
18
|
+
yaml_file = File.join(@root_dir, 'pkg-info.yml')
|
19
|
+
ryaml = ERB.new(File.read(yaml_file), 0)
|
20
|
+
s = ryaml.result(binding)
|
21
|
+
YAML.load(s)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns RubyGems spec information
|
25
|
+
def spec_info
|
26
|
+
self.pkg_info['spec'] if self.pkg_info
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns list of project files
|
30
|
+
def project_files
|
31
|
+
@project_files ||= Dir.glob(File.join(@root_dir, 'lib/**/*.rb'))
|
32
|
+
@project_files
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns list of specification files
|
36
|
+
def spec_files
|
37
|
+
@spec_files ||= Dir.glob(File.join(@root_dir, 'spec/**/*_spec.rb'))
|
38
|
+
@spec_files
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns RubyGem specification for Metafusion::Crypto project
|
42
|
+
def gem_spec
|
43
|
+
@gem_spec ||= Gem::Specification.new do |spec|
|
44
|
+
self.spec_info.each do |key, val|
|
45
|
+
# if val.is_a?(Hash)
|
46
|
+
# puts val.inspect
|
47
|
+
# val.each do |k, v|
|
48
|
+
# spec.send(key, k, v)
|
49
|
+
# end
|
50
|
+
# else
|
51
|
+
spec.send("#{key}=", val)
|
52
|
+
# end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@gem_spec
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# version.rb contains <tt>Metafusion::Crypto::Version</tt> that provides helper
|
2
|
+
# methods related to versioning of the <tt>Metafusion::Crypto4R</tt> project.
|
3
|
+
|
4
|
+
module Metafusion::Crypto::Version #:nodoc:
|
5
|
+
MAJOR = 0
|
6
|
+
MINOR = 1
|
7
|
+
REVISION = 0
|
8
|
+
class << self
|
9
|
+
# Returns X.Y.Z formatted version string
|
10
|
+
def to_version
|
11
|
+
"#{MAJOR}.#{MINOR}.#{REVISION}"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns X-Y-Z formatted version name
|
15
|
+
def to_name
|
16
|
+
"#{MAJOR}_#{MINOR}_#{REVISION}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
PRIVATE_KEY = 'rsa_key'
|
4
|
+
PUBLIC_KEY = 'rsa_key.pub'
|
5
|
+
|
6
|
+
def remove_rsa_keys(priv = PRIVATE_KEY, pub = PUBLIC_KEY)
|
7
|
+
File.delete(priv) if File.exists?(priv)
|
8
|
+
File.delete(pub) if File.exists?(pub)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Metafusion::Crypto, ".generate_key_pair" do
|
12
|
+
before(:each) do
|
13
|
+
remove_rsa_keys
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create a private and public RSA key pair" do
|
17
|
+
Metafusion::Crypto.generate_key_pair
|
18
|
+
File.exists?(PRIVATE_KEY).should be_true
|
19
|
+
File.exists?(PUBLIC_KEY).should be_true
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:each) do
|
23
|
+
remove_rsa_keys
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Metafusion::Crypto::DigitalSignature do
|
28
|
+
before(:each) do
|
29
|
+
# ensure the keys are generated
|
30
|
+
Metafusion::Crypto.generate_key_pair
|
31
|
+
@private_key = "private key"
|
32
|
+
@public_key = "public key"
|
33
|
+
File.stub!(:read).and_return(@public_key, @private_key)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should create instance from from_keys class method" do
|
37
|
+
Metafusion::Crypto::DigitalSignature.should_receive(:new).with(@public_key,@private_key)
|
38
|
+
Metafusion::Crypto::DigitalSignature.from_keys(PUBLIC_KEY, PRIVATE_KEY)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should create instance from from_keys class method using private key data when only public key provided" do
|
42
|
+
Metafusion::Crypto::DigitalSignature.should_receive(:new).with(@public_key)
|
43
|
+
Metafusion::Crypto::DigitalSignature.from_keys(PUBLIC_KEY)
|
44
|
+
end
|
45
|
+
|
46
|
+
after(:each) do
|
47
|
+
remove_rsa_keys
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe Metafusion::Crypto::DigitalSignature do
|
52
|
+
before(:each) do
|
53
|
+
@original_text = "Charlotte Bronte rules"
|
54
|
+
Metafusion::Crypto.generate_key_pair
|
55
|
+
@digital_signature = Metafusion::Crypto::DigitalSignature.from_keys('rsa_key.pub', 'rsa_key')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should encrypt/decrypt round-trip back to original text" do
|
59
|
+
crypted_text = @digital_signature.encrypt(@original_text)
|
60
|
+
decrypted_text = @digital_signature.decrypt(crypted_text)
|
61
|
+
decrypted_text.should eql(@original_text)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should encrypt original text to a 90 character base64 string" do
|
65
|
+
crypted_text = @digital_signature.encrypt(@original_text)
|
66
|
+
crypted_text.size.should be(90)
|
67
|
+
end
|
68
|
+
|
69
|
+
after(:each) do
|
70
|
+
remove_rsa_keys
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe Metafusion::Crypto::PrivateKey do
|
75
|
+
before(:each) do
|
76
|
+
@original_text = "Was Jane Eyre the ultimate feminist?"
|
77
|
+
@private_key = Metafusion::Crypto::PrivateKey.new("currerbell1847")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should encrypt/decrypt round-trip back to original text" do
|
81
|
+
crypted_text = @private_key.encrypt(@original_text)
|
82
|
+
decrypted_text = @private_key.decrypt(crypted_text)
|
83
|
+
decrypted_text.should eql(@original_text)
|
84
|
+
end
|
85
|
+
|
86
|
+
after(:each) do
|
87
|
+
remove_rsa_keys
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe Metafusion::Crypto::PrivateKey, ".from_file" do
|
92
|
+
before(:each) do
|
93
|
+
@file_name = "key_file"
|
94
|
+
@key_content = "the key goes here"
|
95
|
+
File.stub!(:read).and_return(@key_content)
|
96
|
+
@pkey = mock(Metafusion::Crypto::PrivateKey)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should create new instance of PrivateKey with contents of key file supplied" do
|
100
|
+
Metafusion::Crypto::PrivateKey.should_receive(:new).with(@key_content).and_return(@pkey)
|
101
|
+
Metafusion::Crypto::PrivateKey.from_file(@file_name)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should read contents of file given" do
|
105
|
+
File.should_receive(:read).with(@file_name).and_return("")
|
106
|
+
Metafusion::Crypto::PrivateKey.from_file(@file_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
after(:each) do
|
110
|
+
@pkey = nil
|
111
|
+
@file_name = nil
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
def glob_files(*path_elements)
|
4
|
+
Dir.glob(File.join(*path_elements))
|
5
|
+
end
|
6
|
+
|
7
|
+
def load_erb_yaml(path, context)
|
8
|
+
ryaml = ERB.new(File.read(path), 0)
|
9
|
+
YAML.load(ryaml.result(context))
|
10
|
+
end
|
11
|
+
|
12
|
+
module ERBMetaMixin
|
13
|
+
# Needed to make the YAML load work...
|
14
|
+
def project_files
|
15
|
+
glob_files(@root_dir, 'lib', '**/*.rb')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Needed to make the YAML load work...
|
19
|
+
def spec_files
|
20
|
+
glob_files(@root_dir, 'spec', '**/*_spec.rb')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "Metafusion::Crypto::Meta cache policy" do
|
25
|
+
include ERBMetaMixin
|
26
|
+
before(:each) do
|
27
|
+
@root_dir = project_root_dir
|
28
|
+
@meta = Metafusion::Crypto::Meta.new(@root_dir)
|
29
|
+
@expected_pkg_info = load_erb_yaml(File.join(@root_dir, 'pkg-info.yml'), binding)
|
30
|
+
@expected_project_files = project_files
|
31
|
+
@expected_spec_files = spec_files
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should store value returned from project_files in @project_files after first glob" do
|
35
|
+
@meta.instance_eval("@project_files").should eql(nil)
|
36
|
+
@meta.project_files
|
37
|
+
@meta.instance_eval("@project_files").should eql(@expected_project_files)
|
38
|
+
@meta.project_files
|
39
|
+
@meta.instance_eval("@project_files").should eql(@expected_project_files)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should store value returned from spec_files in @spec_files after first glob" do
|
43
|
+
@meta.instance_eval("@spec_files").should eql(nil)
|
44
|
+
@meta.spec_files
|
45
|
+
@meta.instance_eval("@spec_files").should eql(@expected_spec_files)
|
46
|
+
@meta.spec_files
|
47
|
+
@meta.instance_eval("@spec_files").should eql(@expected_spec_files)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "Metafusion::Crypto::Meta" do
|
52
|
+
include ERBMetaMixin
|
53
|
+
before(:each) do
|
54
|
+
@root_dir = project_root_dir
|
55
|
+
@meta = Metafusion::Crypto::Meta.new(@root_dir)
|
56
|
+
@expected_yaml_hash = load_erb_yaml(File.join(@root_dir, 'pkg-info.yml'), binding)
|
57
|
+
@expected_project_files = project_files
|
58
|
+
@expected_spec_files = spec_files
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should load and return YAML file into Hash object upon #pkg_info call" do
|
62
|
+
yaml_hash = @meta.pkg_info
|
63
|
+
yaml_hash.should.eql? @expected_yaml_hash
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should return the embedded hash responding to key 'spec' of #pkg_info call upon #spec_info call" do
|
67
|
+
yaml_hash = @meta.spec_info
|
68
|
+
yaml_hash.should.eql? @expected_yaml_hash['spec']
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return list of files matching ROOT_DIR/lib/**/*.rb upon #project_files call" do
|
72
|
+
project_files = @meta.project_files
|
73
|
+
project_files.should.eql? @expected_project_files
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return list of files matching ROOT_DIR/spec/**/*.rb upon #spec_files call" do
|
77
|
+
spec_files = @meta.spec_files
|
78
|
+
spec_files.should.eql? @expected_spec_files
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return Gem specification based on YAML file contents and #project_files and #spec_files return values" do
|
82
|
+
spec = @meta.gem_spec
|
83
|
+
expected_spec_hash = @expected_yaml_hash['spec']
|
84
|
+
expected_spec_hash.each do |key, val|
|
85
|
+
unless val.is_a?(Hash)
|
86
|
+
spec.send(key).to_s.should eql(expected_spec_hash[key].to_s)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
|
+
|
3
|
+
VERSION_LIST = [Metafusion::Crypto::Version::MAJOR, Metafusion::Crypto::Version::MINOR, Metafusion::Crypto::Version::REVISION]
|
4
|
+
|
5
|
+
EXPECTED_VERSION = VERSION_LIST.join('.')
|
6
|
+
EXPECTED_NAME = VERSION_LIST.join('_')
|
7
|
+
|
8
|
+
describe Metafusion::Crypto::Version, ".to_version" do
|
9
|
+
it "should return #{EXPECTED_VERSION}" do
|
10
|
+
Metafusion::Crypto::Version.to_version.should eql(EXPECTED_VERSION)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Metafusion::Crypto::Version, ".to_name" do
|
15
|
+
it "should return #{EXPECTED_NAME}" do
|
16
|
+
Metafusion::Crypto::Version.to_name.should eql(EXPECTED_NAME)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: metafusion-crypto
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2007-09-30 00:00:00 -05:00
|
8
|
+
summary: Provides private key and digital signature encryption mechanisms for application developers that do not want to worry about the details.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: metafusion@googlegroups.com
|
12
|
+
homepage: http://metafusion.rubyforge.org
|
13
|
+
rubyforge_project: metafusion
|
14
|
+
description:
|
15
|
+
autorequire: metafusion/crypto
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.8.2
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Susan Potter
|
31
|
+
files:
|
32
|
+
- lib/metafusion/crypto.rb
|
33
|
+
- lib/metafusion/crypto/base.rb
|
34
|
+
- lib/metafusion/crypto/version.rb
|
35
|
+
- lib/metafusion/crypto/meta.rb
|
36
|
+
- spec/metafusion/crypto/base_spec.rb
|
37
|
+
- spec/metafusion/crypto/version_spec.rb
|
38
|
+
- spec/metafusion/crypto/meta_spec.rb
|
39
|
+
test_files: []
|
40
|
+
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
requirements:
|
50
|
+
- Ruby 1.8.4+
|
51
|
+
- jcode (for unicode support)
|
52
|
+
dependencies: []
|
53
|
+
|