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.
@@ -0,0 +1,10 @@
1
+ module Metafusion
2
+ module Crypto
3
+ end
4
+ end
5
+
6
+ require 'base64'
7
+
8
+ require 'metafusion/crypto/version'
9
+ require 'metafusion/crypto/meta'
10
+ require 'metafusion/crypto/base'
@@ -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
+