enmail 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.14.6
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at ronald.tse@ribose.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in enmail.gemspec
4
+ gemspec
@@ -0,0 +1,115 @@
1
+ # EnMail
2
+
3
+ [![Build
4
+ Status](https://travis-ci.org/riboseinc/enmail.svg?branch=master)](https://travis-ci.org/riboseinc/enmail)
5
+
6
+ EnMail (Encrypted mail) helps the Ruby mail gem send secure encrypted messages.
7
+
8
+ The two ways for secure mail are:
9
+ * OpenPGP
10
+ * S/MIME
11
+
12
+ This gem allows you to select different OpenPGP implementations
13
+ including NetPGP and GnuPG as different OpenPGP adapters, and also
14
+ S/MIME.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem "enmail"
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ ```sh
27
+ bundle install
28
+ ```
29
+
30
+ Or install it yourself as:
31
+
32
+ ```sh
33
+ gem install enmail
34
+ ```
35
+
36
+ ## Configure
37
+
38
+ The `EnMail` gem provides a very easier interface to set custom configurations
39
+ or configure the underlying dependencies, we can configure it by adding an
40
+ initializer with the following code
41
+
42
+ ```ruby
43
+ EnMail.configure do |config|
44
+ config.sign_message = true
45
+ config.smime_adapter = :openssl
46
+ config.secret_key = "Secret Key String"
47
+
48
+ config.certificates_path = "CERTIFICATES_ROOT_PAH"
49
+ end
50
+ ```
51
+
52
+ Or
53
+
54
+ ```ruby
55
+ EnMail.configuration.certificates_path = "CERTIFICATES_ROOT_PAH"
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ```sh
61
+ bin/console
62
+ ```
63
+
64
+ ## Development
65
+
66
+ We are following Sandi Metz's Rules for this gem, you can read the
67
+ [description of the rules here][sandimetz]. All new code should follow these
68
+ rules. If you make changes in a pre-existing file that violates these rules you
69
+ should fix the violations as part of your contribution.
70
+
71
+ ### Setup
72
+
73
+ Clone the repository.
74
+
75
+ ```sh
76
+ git clone https://github.com/riboseinc/enmail
77
+ ```
78
+
79
+ Setup your environment.
80
+
81
+ ```sh
82
+ bin/setup
83
+ ```
84
+
85
+ Run the test suite
86
+
87
+ ```sh
88
+ bin/rspec
89
+ ```
90
+
91
+ ## Contributing
92
+
93
+ First, thank you for contributing! We love pull requests from everyone. By
94
+ participating in this project, you hereby grant [Ribose Inc.][ribose] the
95
+ right to grant or transfer an unlimited number of non exclusive licenses or
96
+ sub-licenses to third parties, under the copyright covering the contribution
97
+ to use the contribution by all means.
98
+
99
+ Here are a few technical guidelines to follow:
100
+
101
+ 1. Open an [issue][issues] to discuss a new feature.
102
+ 1. Write tests to support your new feature.
103
+ 1. Make sure the entire test suite passes locally and on CI.
104
+ 1. Open a Pull Request.
105
+ 1. [Squash your commits][squash] after receiving feedback.
106
+ 1. Party!
107
+
108
+ ## Credits
109
+
110
+ This gem is developed, maintained and funded by [Ribose Inc.][ribose]
111
+
112
+ [ribose]: https://www.ribose.com
113
+ [issues]: https://github.com/abunashir/enmail/issues
114
+ [squash]: https://github.com/thoughtbot/guides/tree/master/protocol/git#write-a-feature
115
+ [sandimetz]: http://robots.thoughtbot.com/post/50655960596/sandi-metz-rules-for-developers
@@ -0,0 +1,214 @@
1
+ # Ruby mail extension for sending/receiving secure mail
2
+
3
+ [//]: # (TODO: JL add interceptor)
4
+
5
+ OpenPGP [RFC 4880] and S/MIME [RFC 5751] are two methods for secure mail
6
+ delivery today.
7
+
8
+ Currently there is no existing mail gem extension (Ruby Gem) that allows
9
+ switching between the methods and are usually not well structured.
10
+
11
+ This work is to complete implementation of the mail-secure gem by
12
+ leveraging existing OpenPGP and S/MIME mail extension code to allow
13
+ secure email sending via either standard (or a combination of both).
14
+
15
+ The mail-secure gem uses the concept of "adapters" to support different
16
+ underlying libraries.
17
+
18
+ * For OpenPGP, there are two existing implementations: GnuPG and NetPGP.
19
+ * For S/MIME, the default Ruby OpenSSL implementation should be used.
20
+
21
+
22
+ ## Implementations to support:
23
+
24
+ * OpenPGP
25
+ * NetPGP
26
+ * GnuPG
27
+ * S/MIME
28
+ * OpenSSL
29
+
30
+ This gem allows you to select different OpenPGP implementations
31
+ including NetPGP and GnuPG as different OpenPGP adapters, and also
32
+ S/MIME.
33
+
34
+ ## References and notes
35
+
36
+ * <https://github.com/jkraemer/mail-gpg>
37
+ * <https://github.com/bluerail/mr_smime>
38
+
39
+ The `mail-gpg` gem hacks the default `mail` gem Deliverer to ensure the
40
+ OpenPGP encryption/signing step is done at the last. This is extremely
41
+ dirty and fragile.
42
+
43
+ The `mr_smime` gem uses an interceptor hook (supplied by the `mail` gem)
44
+ to encrypt/sign the email. The catch is the `mail` gem supports
45
+ multiple interceptors (like Rack middlewares) so there is no guarantee
46
+ that it is the last interceptor.
47
+
48
+ A better approach is to use the interceptor pattern, and hack the
49
+ interceptor methods in `mail` to force a particular interceptor (the one
50
+ to implement) to be at the very end.
51
+
52
+ Technically, this resulting implementation could allow usage of OpenPGP
53
+ to sign/encrypt a message, then use S/MIME to sign (and/or encrypt) the
54
+ OpenPGP-encoded message at the same time.
55
+
56
+
57
+ ## OpenPGP Example code
58
+
59
+ ```ruby
60
+ message = Mail.new
61
+ message.decrypt
62
+
63
+ signed_mail = message.sign(key)
64
+ encrypted_mail = message.encrypt(identity)
65
+
66
+ signed_email.signature_valid? # => true, false
67
+ signed_email.secure? # => true, false
68
+ signed_email.pgp # => :inline, :mime, nil
69
+ signed_email.pgp? # => true, false
70
+ signed_email.pgp_inline? # => true, false
71
+ signed_email.pgp_mime? # => true, false
72
+ encrypted_email.secure # => "OpenPGP RFC 4880", nil
73
+ encrypted_email.secure? # => true, false
74
+ signed_email.smime? # => true, false
75
+
76
+ Mail::Secure::OpenPGP.signature_valid?(signed_email) # => true, false
77
+ ```
78
+
79
+ ## OpenPGP Configuration
80
+
81
+ ```ruby
82
+ Mail::Secure.configuration = {
83
+ method: :openpgp,
84
+ implementation: :netpgp, # :gpgme
85
+
86
+ # Specify PGP key in 3 ways.
87
+ # Only providing the key:
88
+ key: "ASCII-ARMORED-PGP-KEY",
89
+ key: "non-armored-raw-bytes-pgp-key",
90
+ # or:
91
+ key_id: "key-id",
92
+ keyring: "/Users/whoami/keyring-location",
93
+ # or infer "keyring" from GNUPGHOME:
94
+ key_id: "key-id",
95
+ }
96
+
97
+ ```
98
+
99
+ ### Sample mail object
100
+
101
+ ```ruby
102
+ Mail.new do
103
+ to 'jane@doe.net'
104
+ from 'john@doe.net'
105
+ subject 'gpg test'
106
+ body "encrypt me!"
107
+ add_file "some_attachment.zip"
108
+
109
+ # Using default :method configuration:
110
+ secure encrypt: true, encrypt_for: Key.find("mike@kite.com")
111
+
112
+ # #secure's first argument is optional: :openpgp | :smime
113
+ # If missing, then use the default configuration.
114
+ secure :openpgp, encrypt: true, encrypt_for: Key.find("mike@kite.com")
115
+ secure :smime, encrypt: true, encrypt_for: Key.find("mike@kite.com")
116
+
117
+ # #secure as a long-hand:
118
+ secure :openpgp, sign: true
119
+ secure :openpgp, encrypt: true, encrypt_for: PrivateKey.find("myself")
120
+ secure :openpgp, sign: true, sign_as: PrivateKey.find("myself")
121
+ secure :openpgp, encrypt: true
122
+ secure :openpgp, encrypt: true, passphrase: "secret"
123
+ secure :openpgp, encrypt: true, passphrase_callback: ->(...) {}
124
+
125
+ # #openpgp or #smime as short-hand:
126
+ smime sign: true
127
+ smime encrypt: true, encrypt_for: PrivateKey.find("myself")
128
+ smime sign: true, sign_as: PrivateKey.find("myself")
129
+ openpgp encrypt: true
130
+ openpgp encrypt: true, passphrase: "secret"
131
+ openpgp encrypt: true, passphrase_callback: ->(...) {}
132
+
133
+ # encrypt and sign message with sender's private key, using the given
134
+ # passphrase to decrypt the key
135
+ openpgp encrypt: true, sign: true, password: 'secret'
136
+
137
+ # encrypt and sign message using a different key
138
+ openpgp encrypt: true, sign_as: 'joe@otherdomain.com', password: 'secret'
139
+
140
+
141
+ # encrypt and sign message and use a callback function to provide the
142
+ # passphrase.
143
+ openpgp encrypt: true, sign_as: 'joe@otherdomain.com',
144
+ passphrase_callback: ->(obj, uid_hint, passphrase_info, prev_was_bad, fd) {
145
+ puts "Enter passphrase for #{passphrase_info}: "
146
+ (IO.for_fd(fd, 'w') << readline.chomp).flush
147
+ }
148
+ end.deliver
149
+
150
+ ```
151
+
152
+ #### Encrypt mail using OpenPGP public key directly
153
+
154
+ ```ruby
155
+ johns_key = <<-END
156
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
157
+ Version: GnuPG vX.X.XX (GNU/Linux)
158
+
159
+ mQGiBEk39msRBADw1ExmrLD1OUMdfvA7cnVVYTC7CyqfNvHUVuuBDhV7azs
160
+ ....
161
+ END
162
+
163
+ Mail.new do
164
+ to 'john@foo.bar'
165
+ gpg encrypt: true, keys: { 'john@foo.bar' => johns_key }
166
+ end
167
+
168
+ ```
169
+
170
+ ### Decrypting mail using passphrase
171
+
172
+ ```ruby
173
+
174
+ mail = Mail.first
175
+ mail.subject # subject is never encrypted
176
+ if mail.encrypted?
177
+ # decrypt using your private key, protected by the given passphrase
178
+ plaintext_mail = mail.decrypt(password: 'abc')
179
+ # the plaintext_mail, is a full Mail::Message object, just decrypted
180
+ end
181
+
182
+ ```
183
+
184
+ ### Signing mail (simplest case)
185
+
186
+ ```ruby
187
+
188
+
189
+ Mail.new do
190
+ to 'jane@doe.net'
191
+ gpg sign: true
192
+ end.deliver
193
+
194
+ ```
195
+
196
+ ### Verifying signature
197
+
198
+ ```ruby
199
+
200
+ mail = Mail.first
201
+ if !mail.encrypted? && mail.signed?
202
+ verified = mail.verify
203
+ puts "signature(s) valid: #{verified.signature_valid?}"
204
+ puts "message signed by: #{verified.signatures.map{|sig|sig.from}.join("\n")}"
205
+ end
206
+
207
+
208
+ if mail.encrypted?
209
+ decrypted = mail.decrypt(verify: true, password: 's3cr3t')
210
+ puts "signature(s) valid: #{decrypted.signature_valid?}"
211
+ puts "message signed by: #{decrypted.signatures.map{|sig|sig.from}.join("\n")}"
212
+ end
213
+
214
+ ```
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "enmail"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||=
11
+ File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("rspec-core", "rspec")