yopass 1.0.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,11 @@
1
+ <%= erb :header %>
2
+ <form role="form" method="GET">
3
+ <div class="form-group">
4
+ <label>Password</label>
5
+ <input type="password" class="form-control" name="p" placeholder="Password to decrypt secret">
6
+ <input type="hidden" class="form-control" name="k" value="<%=key%>" hidden="true">
7
+ </div>
8
+ <button type="submit" class="btn btn-default">Submit</button>
9
+ </form>
10
+ <br/>
11
+ <%= erb :footer %>
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="">
8
+ <meta name="author" content="Johan Haals">
9
+
10
+ <title>YoPass Share Secrets</title>
11
+
12
+ <!-- Bootstrap core CSS -->
13
+ <link href="/css/bootstrap.min.css" rel="stylesheet">
14
+
15
+ <!-- Custom styles for this template -->
16
+ <link href="/css/jumbotron.css" rel="stylesheet">
17
+
18
+ <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
19
+ <!--[if lt IE 9]>
20
+ <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
21
+ <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
22
+ <![endif]-->
23
+ </head>
24
+
25
+ <body>
26
+
27
+ <div class="container">
28
+ <div class="header">
29
+ <h3 class="text-muted"><a href="/">YoPass</a> Share Secrets Securely</h3>
30
+ </div>
31
+
@@ -0,0 +1,56 @@
1
+ <%= erb :header %>
2
+ <form role="form" method="post">
3
+ <div class="form-group">
4
+ <label>Secret</label>
5
+ <textarea placeholder="Your secret" class="form-control" rows="6" name="secret"></textarea>
6
+ </div>
7
+ <label>Self destruct after</label>
8
+ <div class="radio">
9
+ <label>
10
+ <input type="radio" name="lifetime" value="1w" checked>1 Week
11
+ </label>
12
+ </div>
13
+ <div class="radio">
14
+ <label>
15
+ <input type="radio" name="lifetime" value="1d">1 Day
16
+ </label>
17
+ </div>
18
+ <div class="radio">
19
+ <label>
20
+ <input type="radio" name="lifetime" value="1h">1 Hour
21
+ </label>
22
+ </div>
23
+ <% if send_sms %>
24
+ <div class="form-group">
25
+ <label>Send decryption key over SMS</label>
26
+ <i>Remember country code</i>
27
+ <input type="input" class="form-control" name="mobile_number" placeholder="eg 46702224990">
28
+ </div>
29
+ <% end %>
30
+ <button type="submit" class="btn btn-primary">Store Secret</button>
31
+ </form>
32
+ <br/>
33
+ <div class="row marketing">
34
+ <div class="col-lg-6">
35
+ <h4><span class="glyphicon glyphicon-lock"></span> AES-256 Encryption</h4>
36
+ <p>Your secret is encrypted and no records of the decryption key is stored anywhere</p>
37
+
38
+ <h4><span class="glyphicon glyphicon-floppy-remove"></span> Never stored on disk</h4>
39
+ <p>Your secret is stored in memory to incease security</p>
40
+
41
+ <h4><span class="glyphicon glyphicon-eye-open"></span> Visible Once</h4>
42
+ <p>Your secret is only visible once to make sure it's never been seen by anyone except the receiver</p>
43
+ </div>
44
+
45
+ <div class="col-lg-6">
46
+ <h4><span class="glyphicon glyphicon-time"></span> Self Destruction</h4>
47
+ <p>All secrets will self destruct after X hours</p>
48
+
49
+ <h4><span class="glyphicon glyphicon-bullhorn"></span> Open Source</h4>
50
+ <p>This website is open source meaning you can submit feedback and patches to improve the project</p>
51
+
52
+ <h4><span class="glyphicon glyphicon-minus-sign"></span> No Caching</h4>
53
+ <p>Caching headers are disabled</p>
54
+ </div>
55
+ </div>
56
+ <%= erb :footer %>
@@ -0,0 +1,8 @@
1
+ <%= erb :header %>
2
+ <h2>URL for your secret</h2>
3
+ <p><b><%=url%></b></p>
4
+ <p>Your secret can only be viewed ONCE, do not open the URL yourself</p>
5
+ <% if key_sent_to_mobile %>
6
+ <p>The decryption key is sent to the receiver via sms, dont forget to provide the URL via another channel</p>
7
+ <% end %>
8
+ <%= erb :footer %>
data/lib/yopass.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'memcached'
2
+ require 'sinatra/base'
3
+ require 'securerandom'
4
+ require 'encryptor'
5
+ require 'yaml'
6
+ require 'uri'
7
+ require 'yopass/sms_provider'
8
+
9
+ class Yopass < Sinatra::Base
10
+ configure :development do
11
+ require 'sinatra/reloader'
12
+ register Sinatra::Reloader
13
+ set :config, YAML.load_file('conf/yopass.yaml')
14
+ end
15
+ configure :production do
16
+ set :config, YAML.load_file('/etc/yopass.yaml')
17
+ end
18
+ configure do
19
+ set :cache, Memcached.new(settings.config['memcached_url'])
20
+ set :public_folder, File.dirname(__FILE__) + '/static'
21
+ end
22
+
23
+ get '/' do
24
+ # display mobile number field if send_sms is true
25
+ erb :index, :locals => {:send_sms => settings.config['send_sms']}
26
+ end
27
+
28
+ post '/' do
29
+ headers 'Cache-Control' => 'no-cache, no-store, must-revalidate'
30
+ headers 'Pragma' => 'no-cache'
31
+ headers 'Expires' => '0'
32
+
33
+ lifetime = params[:lifetime]
34
+ # calculate lifetime in secounds
35
+ lifetime_options = { '1w' => 3600*24*7,
36
+ '1d' => 3600*24,
37
+ '1h' => 3600,
38
+ }
39
+ # Verify that user has posted a valid lifetime
40
+ return 'Invalid lifetime' unless lifetime_options.include? lifetime
41
+ return 'No secret submitted' if params[:secret].empty?
42
+ return 'This site is meant to store secrets not novels' if params[:secret].length >= 10000
43
+
44
+ # goes in URL
45
+ key = SecureRandom.urlsafe_base64 8
46
+ # password goes in URL or via SMS if provider is configured
47
+ password = SecureRandom.urlsafe_base64 8
48
+ # encrypt secret with generated password
49
+ data = Encryptor.encrypt(params[:secret], :key => password)
50
+ # store secret in memcached
51
+ settings.cache.set key, data, lifetime_options[lifetime]
52
+
53
+ if settings.config['send_sms'] == true and !params[:mobile_number].nil?
54
+ # strip everything except digits
55
+ mobile_number = params[:mobile_number].gsub(/[^0-9]/, "")
56
+ # load specified sms provider
57
+ sms = SmsProvider.create(settings.config['sms::provider'],
58
+ settings.config['sms::settings'])
59
+
60
+ unless params[:mobile_number].empty?
61
+ # TODO verification
62
+ sms.send(mobile_number, password)
63
+ return erb :secret_url, :locals => {
64
+ :url => URI.join(settings.config['http_base_url'], "get?k=#{key}"),
65
+ :key_sent_to_mobile => true }
66
+ end
67
+ end
68
+
69
+ erb :secret_url, :locals => {:url => URI.join(settings.config['http_base_url'], "get?k=#{key}&p=#{password}")}
70
+ end
71
+
72
+ get '/get' do
73
+ # No password added
74
+ return erb :get_secret, :locals => {:key => params[:k]} if params[:p].nil? or params[:p].empty?
75
+
76
+ # Disable all caching
77
+ headers 'Cache-Control' => 'no-cache, no-store, must-revalidate'
78
+ headers 'Pragma' => 'no-cache'
79
+ headers 'Expires' => '0'
80
+ begin
81
+ result = settings.cache.get params[:k]
82
+ rescue Memcached::NotFound
83
+ return erb :'404'
84
+ end
85
+ content_type 'text/plain'
86
+
87
+ begin
88
+ result = Encryptor.decrypt(:value => result, :key => params[:p])
89
+ rescue OpenSSL::Cipher::CipherError
90
+ return 'Invalid decryption key'
91
+ end
92
+ settings.cache.delete params[:k]
93
+ result
94
+ end
95
+
96
+ run! if app_file == $0
97
+ end
@@ -0,0 +1,11 @@
1
+ class SmsProvider
2
+ def self.create(provider, settings)
3
+ begin
4
+ require "yopass/sms_provider/#{provider.downcase}"
5
+ rescue LoadError => e
6
+ raise "Unsupported provider #{provider}: #{e}"
7
+ end
8
+ class_name = provider.split("_").map {|v| v.capitalize }.join
9
+ const_get(class_name).new settings
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ require 'open-uri'
2
+
3
+ class Bulksms
4
+ def initialize(settings)
5
+ @api_url = 'http://bulksms.vsms.net:5567/eapi/submission/send_sms/2/2.0'
6
+ @username = settings['username']
7
+ @password = settings['password']
8
+ @sender = settings['sender']
9
+ end
10
+
11
+ def send(to, message)
12
+ url = URI.join(@api_url, "?username=#{@username}&password=#{@password}" \
13
+ "&message=#{message}&msisdn=#{to}&sender=#{@sender}")
14
+ result = open(url).read
15
+ return true if result.include? "IN_PROGRESS"
16
+ false
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yopass
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Johan Haals
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: encryptor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: memcached
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Web service for sharing secrets more securely
56
+ email:
57
+ - jhaals@spotify.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - README.md
64
+ - conf/config.ru
65
+ - conf/yopass.yaml
66
+ - lib/static/css/bootstrap-theme.min.css
67
+ - lib/static/css/bootstrap.min.css
68
+ - lib/static/css/jumbotron.css
69
+ - lib/static/fonts/glyphicons-halflings-regular.eot
70
+ - lib/static/fonts/glyphicons-halflings-regular.svg
71
+ - lib/static/fonts/glyphicons-halflings-regular.ttf
72
+ - lib/static/fonts/glyphicons-halflings-regular.woff
73
+ - lib/static/foo.css
74
+ - lib/static/js/bootstrap.min.js
75
+ - lib/views/404.erb
76
+ - lib/views/footer.erb
77
+ - lib/views/get_secret.erb
78
+ - lib/views/header.erb
79
+ - lib/views/index.erb
80
+ - lib/views/secret_url.erb
81
+ - lib/yopass.rb
82
+ - lib/yopass/sms_provider.rb
83
+ - lib/yopass/sms_provider/bulksms.rb
84
+ homepage: https://github.com/jhaals/yopass
85
+ licenses:
86
+ - Apache 2.0
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ - conf
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '>='
96
+ - !ruby/object:Gem::Version
97
+ version: 1.8.7
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.0.3
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Secure sharing for secrets and passwords
109
+ test_files: []