session_keys 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b74b3a502d1899a68ff8b16541ea362382c8669
4
- data.tar.gz: 52dda96d9ce724e94029fb0cd721dc60a5cf0b20
3
+ metadata.gz: e0173c199f8a44a3f43f5ddb65c1252e30ceeeb6
4
+ data.tar.gz: 4685fc8e3585592c591ca82e2cbcce91b40c9aa7
5
5
  SHA512:
6
- metadata.gz: 00fea5dc09be245cd39b32f8cc836ba2610384911730c5e32eed10e4c87368530d753bc35fde5a6b13ad751de9a21e8414c9801d9849be38f55ec4f107634b54
7
- data.tar.gz: f5a9b84aea86470d7a2cc1d0613bf409d3285d3911487b25a2d41fe4345323d48a29fd0e3c4a928f87c27f67bf61c4c91b8c0336f9dca118f5fd0fd71da49ab2
6
+ metadata.gz: a169ab65770b8c88d64e3ab03fd7d1060e22233fe036e353b52d35bf993201ddcf508c9040d0c2fb8a68374d6ea3fb14a0f01647cdab1c208928ec591196e2a8
7
+ data.tar.gz: ddadf6ca0160a531406c98f8b9ca9af1c1b5acf41ba12244e0540f56dd4c8cf77ea6e98f824cc79bc8a41d649d8804eadc74e048987802faca70efacfea2ff72
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,7 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.0
4
- - 2.2.4
3
+ - 2.2.5
5
4
  - 2.3.1
6
- - jruby-9.0.5.0
7
5
  before_install: gem install bundler -v 1.12.1
@@ -0,0 +1,12 @@
1
+ # CHANGELOG
2
+
3
+ ## v1.0.0 (9/8/2016)
4
+
5
+ - Major refactor and simplification
6
+ - Compatible with grempe/session-keys-js
7
+
8
+ ## v0.1.0 (4/30/2016)
9
+
10
+ This is the initial ALPHA quality release.
11
+
12
+ It is for review only and should not yet be used in production.
data/Gemfile CHANGED
@@ -2,8 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in session_keys.gemspec
4
4
  gemspec
5
-
6
- # FIXME : remove when @bascule publishes new rbnacl release
7
- # including commit : dc1e8d10b8fc4784130b0864d45b9275a9e979dc
8
- # https://github.com/cryptosphere/rbnacl/pull/135
9
- gem 'rbnacl', git: 'https://github.com/cryptosphere/rbnacl.git'
data/README.md CHANGED
@@ -1,35 +1,25 @@
1
- # SessionKeys
1
+ # sessionKeys (Ruby)
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/session-keys-rb.svg)](https://badge.fury.io/rb/session-keys-rb)
3
+ [![Gem Version](https://badge.fury.io/rb/session_keys.svg)](https://badge.fury.io/rb/session_keys)
4
4
  [![Dependency Status](https://gemnasium.com/badges/github.com/grempe/session-keys-rb.svg)](https://gemnasium.com/github.com/grempe/session-keys-rb)
5
5
  [![Build Status](https://travis-ci.org/grempe/session-keys-rb.svg?branch=master)](https://travis-ci.org/grempe/session-keys-rb)
6
6
  [![Coverage Status](https://coveralls.io/repos/github/grempe/session-keys-rb/badge.svg?branch=master)](https://coveralls.io/github/grempe/session-keys-rb?branch=master)
7
7
  [![Code Climate](https://codeclimate.com/github/grempe/session-keys-rb/badges/gpa.svg)](https://codeclimate.com/github/grempe/session-keys-rb)
8
8
  [![Inline docs](http://inch-ci.org/github/grempe/session-keys-rb.svg?branch=master)](http://inch-ci.org/github/grempe/session-keys-rb)
9
9
 
10
- SessionKeys is a cryptographic tool for the deterministic generation of
11
- NaCl compatible [Curve25519](https://cr.yp.to/ecdh.html) encryption and
12
- [Ed25519](http://ed25519.cr.yp.to) digital signature keys.
10
+ `sessionKeys` is a cryptographic tool for the generation of unique user IDs,
11
+ and NaCl compatible [Curve25519](https://cr.yp.to/ecdh.html) encryption, and
12
+ [Ed25519](http://ed25519.cr.yp.to) digital signature keys using Ruby.
13
13
 
14
- The strength of the system lies in the fact that the keypairs are derived from
15
- passing an identifier, such as a username or email address, and a high-entropy
16
- passphrase through the `SHA256` hash and the `scrypt` key derivation
17
- functions. This means that no private key material need ever be stored to disk.
18
- The generated keys are deterministic; for any given ID, password, and
19
- strength combination the same keys will always be returned.
14
+ It is compatible with [grempe/session-keys-js](https://github.com/grempe/session-keys-js)
15
+ which can generates identical IDs and crypto keys using Javascript when given the
16
+ same username and passphrase values. Both libraries have extensive tests to
17
+ ensure they remain interoperable.
20
18
 
21
- The generated ID is passed through `SHA256` and `scrypt` and is derived from
22
- only the ID parameter your provide and a common salt.
19
+ The strength of the system lies in the fact that the keypairs are derived from passing an identifier such as a username or email address, and a high-entropy passphrase through the SHA256 cryptographic one-way hash function, and then 'stretching' that username/password into strong key material using the scrypt key derivation function.
23
20
 
24
- The password is also passed through `SHA256` and `scrypt` and NaCl encryption
25
- and signing keypairs are derived from the combination of the stretched ID,
26
- your password, and a common salt.
27
-
28
- ## WARNING : BETA CODE
29
-
30
- This code is new and has not yet been tested in production. Use at your own risk.
31
- The interface should be fairly stable now but should not be considered fully
32
- stable until v1.0.0 is released.
21
+ For an overview of the security design, please see the README for the companion
22
+ project [grempe/session-keys-js](https://github.com/grempe/session-keys-js)
33
23
 
34
24
  ## Installation
35
25
 
@@ -51,6 +41,40 @@ Or install it yourself as:
51
41
  $ gem install session_keys
52
42
  ```
53
43
 
44
+ ## Usage
45
+
46
+ ``` ruby
47
+ SessionKeys.generate('user@example.com', 'my strong passphrase')
48
+
49
+ {
50
+ id: '...',
51
+ byte_keys: [...],
52
+ hex_keys: [...],
53
+ nacl_encryption_key_pairs: [...],
54
+ nacl_encryption_key_pairs_base64: [...],
55
+ nacl_signing_key_pairs: [...],
56
+ nacl_signing_key_pairs_base64: [...],
57
+ process_time: 250
58
+ }
59
+
60
+ ```
61
+
62
+ Security Note : Each Array will contain eight values. Since each value at a
63
+ particular Array index is derived from the same key material it is recommended
64
+ to choose the different key types you need from different Array indexes. This
65
+ ensures that each key type was not derived from the same value.
66
+
67
+ ```
68
+ # uuid : array index 0
69
+ output.hex_keys[0]
70
+
71
+ # encryption keypair : array index 1
72
+ output.nacl_encryption_key_pairs[1]
73
+
74
+ # signing keypair : array index 2
75
+ output.nacl_signing_key_pairs[2]
76
+ ```
77
+
54
78
  ### Installation Security : Signed Ruby Gem
55
79
 
56
80
  The SessionKeys gem is cryptographically signed. To be sure the gem you install hasn’t
@@ -58,7 +82,7 @@ been tampered with you can install it using the following method:
58
82
 
59
83
  Add required public keys (if you haven’t already) as trusted certificates
60
84
 
61
- ``` text
85
+ ```
62
86
  # Caveat: Gem certificates are trusted globally, such that adding a
63
87
  # cert.pem for one gem automatically trusts all gems signed by that cert.
64
88
  gem cert --add <(curl -Ls https://raw.githubusercontent.com/cryptosphere/rbnacl/master/bascule.cert)
@@ -101,13 +125,6 @@ You can also clone the repository and verify the signatures locally using your
101
125
  own GnuPG installation. You can find my certificates and read about how to conduct
102
126
  this verification at [https://www.rempe.us/keys/](https://www.rempe.us/keys/).
103
127
 
104
- ## Usage
105
-
106
- ``` ruby
107
- keys = SessionKeys.generate('user@example.com', 'my strong passphrase')
108
- #=> {...}
109
- ```
110
-
111
128
  ## Development
112
129
 
113
130
  After checking out the repo, run `bin/setup` to install dependencies. Then,
@@ -0,0 +1,113 @@
1
+ # Gem Release Process
2
+
3
+ Don't use the `bundle exec rake release` task. It is more convenient,
4
+ but it skips the process of signing the version release task.
5
+
6
+ ## Run Tests
7
+
8
+ ```sh
9
+ $ bundle exec rake test
10
+ $ rake wwtd
11
+ ```
12
+
13
+ ## Git Push
14
+
15
+ ```sh
16
+ $ git push
17
+ ```
18
+
19
+ Check for regressions in automated tests:
20
+
21
+ * [https://travis-ci.org/grempe/session-keys-rb](https://travis-ci.org/grempe/session-keys-rb)
22
+ * [https://coveralls.io/github/grempe/session-keys-rb?branch=master](https://coveralls.io/github/grempe/session-keys-rb?branch=master)
23
+ * [https://codeclimate.com/github/grempe/session-keys-rb](https://codeclimate.com/github/grempe/session-keys-rb)
24
+ * [http://inch-ci.org/github/grempe/session-keys-rb](http://inch-ci.org/github/grempe/session-keys-rb)
25
+
26
+ ## Bump Version Number and edit CHANGELOG.md
27
+
28
+ ```sh
29
+ $ vi lib/session_keys/version.rb
30
+ $ git add lib/session_keys/version.rb
31
+ $ vi CHANGELOG.md
32
+ $ git add CHANGELOG.md
33
+ ```
34
+
35
+ ## Local Build and Install w/ Signed Gem
36
+
37
+ The `build` step should ask for PEM passphrase to sign gem. If it does
38
+ not ask it means that the signing cert is not present.
39
+
40
+ Add certs:
41
+
42
+ ```sh
43
+ gem cert --add <(curl -Ls https://raw.github.com/grempe/session-keys-rb/master/certs/gem-public_cert_grempe.pem)
44
+ gem cert --add <(curl -Ls https://raw.githubusercontent.com/cryptosphere/rbnacl/master/bascule.cert)
45
+ ```
46
+
47
+ Build:
48
+
49
+ ```sh
50
+ $ rake build
51
+ Enter PEM pass phrase:
52
+ session_keys 0.1.0 built to pkg/session_keys-0.1.0.gem.
53
+ ```
54
+
55
+ Install locally w/ Cert:
56
+
57
+ ```sh
58
+ $ gem uninstall session_keys
59
+ $ rbenv rehash
60
+ $ gem install pkg/session_keys-0.1.0.gem -P MediumSecurity
61
+ Successfully installed session_keys-0.1.0.gem
62
+ 1 gem installed
63
+ ```
64
+
65
+ ## Git Commit Version and CHANGELOG Changes, Tag and push to Github
66
+
67
+ ```sh
68
+ $ git add lib/session_keys/version.rb
69
+ $ git add CHANGELOG.md
70
+ $ git commit -m 'Bump version v0.1.1'
71
+ $ git tag -s v0.1.1 -m "v0.1.1" SHA1_OF_COMMIT
72
+ ```
73
+
74
+ Verify last commit and last tag are GPG signed:
75
+
76
+ ```
77
+ $ git tag -v v0.1.0
78
+ ...
79
+ gpg: Good signature from "Glenn Rempe (Code Signing Key) <glenn@rempe.us>" [ultimate]
80
+ ...
81
+ ```
82
+
83
+ ```
84
+ $ git log --show-signature
85
+ ...
86
+ gpg: Good signature from "Glenn Rempe (Code Signing Key) <glenn@rempe.us>" [ultimate]
87
+ ...
88
+ ```
89
+
90
+ Push code and tags to GitHub:
91
+
92
+ ```
93
+ $ git push
94
+ $ git push --tags
95
+ ```
96
+
97
+ ## Push gem to Rubygems.org
98
+
99
+ ```sh
100
+ $ gem push pkg/session_keys-0.1.0.gem
101
+ ```
102
+
103
+ Verify Gem Push at [https://rubygems.org/gems/session_keys](https://rubygems.org/gems/session_keys)
104
+
105
+ ## Create a GitHub Release
106
+
107
+ Specify the tag we just pushed to attach release to. Copy notes from CHANGELOG.md
108
+
109
+ [https://github.com/grempe/session-keys-rb/releases](https://github.com/grempe/session-keys-rb/releases)
110
+
111
+ ## Announce Release on Twitter
112
+
113
+ The normal blah, blah, blah.
@@ -6,75 +6,31 @@ require 'base64'
6
6
 
7
7
  # SessionKeys deterministic cryptographic key generation.
8
8
  module SessionKeys
9
- # Opslimit represents a maximum amount of computations to perform.
10
- # Raising this number will make the function require more CPU cycles to
11
- # compute a key.
12
- #
13
- # Number of scrypt computations for scrypt to perform for interactive security setting.
14
- # Set to SCRYPT_MEMLIMIT_INTERACTIVE / 32
15
- #
16
- # For interactive, online operations, `SCRYPT_OPSLIMIT_INTERACTIVE` and
17
- # `SCRYPT_MEMLIMIT_INTERACTIVE` provide a safe base line for these two parameters.
18
- # However, using higher values may improve security.
19
- #
20
- # See : https://download.libsodium.org/doc/password_hashing/scrypt.html
21
- SCRYPT_OPSLIMIT_INTERACTIVE = 2**19
22
-
23
- # Memlimit is the maximum amount of RAM that the function will use, in
24
- # bytes. It is highly recommended to allow the function to use at least 16
25
- # megabytes.
26
- #
27
- # Max RAM in Bytes to be used by scrypt for interactive security setting.
28
- SCRYPT_MEMLIMIT_INTERACTIVE = 2**24
29
-
30
- # Number of scrypt computations for scrypt to perform for sensitive security setting.
31
- # Set to SCRYPT_MEMLIMIT_SENSITIVE / 32
32
- #
33
- # For highly sensitive data, `SCRYPT_OPSLIMIT_SENSITIVE` and `SCRYPT_MEMLIMIT_SENSITIVE` can
34
- # be used as an alternative. But with these parameters, deriving a key takes
35
- # about 2 seconds on a 2.8 Ghz Core i7 CPU and requires up to 1 gigabyte of
36
- # dedicated RAM.
37
- SCRYPT_OPSLIMIT_SENSITIVE = 2**25
38
-
39
- # Max RAM in Bytes to be used by scrypt for sensitive security setting.
40
- SCRYPT_MEMLIMIT_SENSITIVE = 2**30
41
-
42
- # Size in Bytes of the scrypt derived output for the id
43
- SCRYPT_DIGEST_SIZE_ID = 32
44
-
45
- # Size in Bytes of the scrypt derived output for the password
46
- SCRYPT_DIGEST_SIZE_PASSWORD = 256
47
-
48
- # A site-wide 32 Byte common random value that will be concatenated with a value
49
- # being hashed for some additional measure of security against dictionary
50
- # style attacks. This value was randomly chosen but must be the same across
51
- # implementations and is assumed public.
52
- PEPPER = 'f01f0a0c44a2d1e7e5b00d7dc78941d404474a90ce7f4ae9d1432bf76fa169e7'.freeze
9
+ # Size in bytes of the scrypt derived output
10
+ SCRYPT_DIGEST_SIZE = 256
53
11
 
54
12
  # Deterministically generates a collection of derived encryption key material from
55
- # a provided id and password. Uses SHA256 and scrypt for key derivation.
13
+ # a provided id and password/passphrase. Uses SHA256 and scrypt for key derivation.
56
14
  #
57
- # @param id [String] a unique UTF-8 String identifier such as a username or
15
+ # @param id [String] a unique US-ASCII or UTF-8 encoded String identifier such as a username or
58
16
  # email address. Max length 256 characters.
59
- # @param password [String] a cryptographically strong UTF-8 password or
17
+ # @param password [String] a cryptographically strong US-ASCII or UTF-8 encoded password or
60
18
  # passphrase. Max length 256 characters.
61
- # @param strength [Symbol] the desired strength of the key derivation. Can be
62
- # the symbols :interactive or (:sensitive).
63
19
  # @param min_password_entropy [Integer] the minimum (75) estimated entropy allowed
64
20
  # for the password. This will be measured with Zxcvbn.
65
21
  # @return [Hash] returns a Hash of keys and derived key material.
66
22
  # @raise [ArgumentError] if invalid arguments are provided.
67
- def self.generate(id, password, strength = :sensitive, min_password_entropy = 75)
68
- unless id.is_a?(String) && id.encoding.name == 'UTF-8'
69
- raise ArgumentError, 'invalid id, not a UTF-8 string'
23
+ def self.generate(id, password, min_password_entropy = 75)
24
+ unless id.is_a?(String) && ['US-ASCII', 'UTF-8'].include?(id.encoding.name)
25
+ raise ArgumentError, 'invalid id, not a US-ASCII or UTF-8 string'
70
26
  end
71
27
 
72
28
  unless id.length.between?(1,256)
73
29
  raise ArgumentError, 'invalid id, must be between 1 and 256 characters in length'
74
30
  end
75
31
 
76
- unless password.is_a?(String) && password.encoding.name == 'UTF-8'
77
- raise ArgumentError, 'invalid password, not a UTF-8 string'
32
+ unless password.is_a?(String) && ['US-ASCII', 'UTF-8'].include?(password.encoding.name)
33
+ raise ArgumentError, 'invalid password, not a US-ASCII or UTF-8 string'
78
34
  end
79
35
 
80
36
  # Enforce max length only due to Zxcvbn taking a *long* time to
@@ -92,32 +48,10 @@ module SessionKeys
92
48
  raise ArgumentError, "invalid password, must be at least #{min_password_entropy} bits of estimated entropy"
93
49
  end
94
50
 
95
- unless [:interactive, :sensitive].include?(strength)
96
- raise ArgumentError, 'invalid strength, must be :interactive (min), or :sensitive (strong)'
97
- end
98
-
99
51
  start_processing_time = Time.now
100
52
 
101
- # Run the ID and a 'pepper' (an app common salt) through scrypt. This will be
102
- # the system ID for this user. This processing is done to prevent knowledge
103
- # of the user on the server side and prevent the ability to reverse this
104
- # ID back into a username or email. Using scrypt instead of a SHA256 Hash
105
- # is so that it will also take unreasonable effort for someone with a list
106
- # of user identifiers from looking up users on the system quickly even if
107
- # provided with a local copy of the DB.
108
53
  id_sha256_bytes = RbNaCl::Hash.sha256(id.bytes.pack('C*'))
109
-
110
- id_sha256_pepper_bytes = RbNaCl::Hash.sha256(
111
- "#{id}#{id.length}#{PEPPER}#{PEPPER.length}".bytes.pack('C*')
112
- )
113
-
114
- id_scrypt_hex = RbNaCl::PasswordHash.scrypt(
115
- id_sha256_bytes,
116
- id_sha256_pepper_bytes,
117
- SCRYPT_OPSLIMIT_INTERACTIVE,
118
- SCRYPT_MEMLIMIT_INTERACTIVE,
119
- SCRYPT_DIGEST_SIZE_ID
120
- ).bytes.map { |byte| '%02x' % byte }.join
54
+ id_sha256_hex = id_sha256_bytes.bytes.map { |byte| '%02x' % byte }.join
121
55
 
122
56
  # libsodium : By design, a password whose length is 65 bytes or more is
123
57
  # reduced to SHA-256(password). This can have security implications if the
@@ -125,63 +59,67 @@ module SessionKeys
125
59
  # SHA-256. Or when upgrading passwords previously hashed with unsalted
126
60
  # SHA-256 to scrypt. If this is a concern, passwords should be pre-hashed
127
61
  # before being hashed using scrypt.
128
- password_sha256_bytes = RbNaCl::Hash.sha256(password.bytes.pack('C*'))
62
+ scrypt_key = RbNaCl::Hash.sha256(password.bytes.pack('C*'))
129
63
 
130
- password_sha256_pepper_bytes = RbNaCl::Hash.sha256(
131
- "#{id_scrypt_hex}#{id_scrypt_hex.length}#{PEPPER}#{PEPPER.length}".bytes.pack('C*')
132
- )
64
+ # Tie the sycrypt password bytes to the ID they are associate with by
65
+ # utilizing the ID as the salt. Include the ID length and an additional
66
+ # string to harden the salt.
67
+ scrypt_salt = RbNaCl::Hash.sha256([id_sha256_hex,
68
+ id_sha256_hex.length,
69
+ 'session_keys'].join('').bytes.pack('C*'))
133
70
 
134
- # Derive SCRYPT_DIGEST_SIZE_PASSWORD secret bytes. They will be split
135
- # into 32 Byte chunks to serve as deterministic seeds for ID or key
136
- # generation. Some derived bytes are reserved for future use.
71
+ # Derive SCRYPT_DIGEST_SIZE secret bytes
137
72
  password_digest = RbNaCl::PasswordHash.scrypt(
138
- password_sha256_bytes,
139
- password_sha256_pepper_bytes,
140
- strength == :interactive ? SCRYPT_OPSLIMIT_INTERACTIVE : SCRYPT_OPSLIMIT_SENSITIVE,
141
- strength == :interactive ? SCRYPT_MEMLIMIT_INTERACTIVE : SCRYPT_MEMLIMIT_SENSITIVE,
142
- SCRYPT_DIGEST_SIZE_PASSWORD
73
+ scrypt_key,
74
+ scrypt_salt,
75
+ 16384 * 32,
76
+ 16384 * 32 * 32,
77
+ SCRYPT_DIGEST_SIZE
143
78
  ).bytes
144
79
 
145
- # Break up the scrypt digest into 32 Byte seeds.
146
- secret_bytes = []
147
- (SCRYPT_DIGEST_SIZE_PASSWORD/32).times { secret_bytes << password_digest.shift(32) }
148
-
149
- # Seed 0 : RbNaCl::SimpleBox
150
- # The seed bytes are used as a 32 Byte key suitable for
151
- # simple symetric key encryption using `RbNaCl::SimpleBox`. SimpleBox is
152
- # a wrapper around NaCl SecretBox construct with automated nonce management.
153
- #
154
- # To encrypt/decreypt with this object try:
155
- # ciphertext = nacl_simple_box.encrypt('foobar')
156
- # plaintext = nacl_simple_box.decrypt(ciphertext)
157
- nacl_simple_box_key = secret_bytes[0].pack('C*').force_encoding('ASCII-8BIT')
158
- nacl_simple_box = RbNaCl::SimpleBox.from_secret_key(nacl_simple_box_key)
159
-
160
- # Seed 1 : NaCl Box Keypair
161
- nacl_enc_sec_seed = secret_bytes[1].pack('C*').force_encoding('ASCII-8BIT')
162
- nacl_enc_sec_key = RbNaCl::PrivateKey.new(nacl_enc_sec_seed)
163
- nacl_enc_pub_key = nacl_enc_sec_key.public_key
164
-
165
- # Seed 2 : NaCl Signing Keypair
166
- nacl_sig_sec_seed = secret_bytes[2].pack('C*').force_encoding('ASCII-8BIT')
167
- nacl_sig_sec_key = RbNaCl::SigningKey.new(nacl_sig_sec_seed)
168
- nacl_sig_pub_key = nacl_sig_sec_key.verify_key
169
-
170
- # Seed 3 : Reserved for future use.
171
- # Seed 4 : Reserved for future use.
172
- # Seed 5 : Reserved for future use.
173
- # Seed 6 : Reserved for future use.
174
- # Seed 7 : Reserved for future use.
80
+ num_keys = SCRYPT_DIGEST_SIZE / 32
81
+
82
+ byte_keys = []
83
+ num_keys.times { byte_keys << password_digest.shift(32) }
84
+
85
+ hex_keys = byte_keys.map { |key|
86
+ key.map { |byte| '%02x' % byte }.join
87
+ }
88
+
89
+ nacl_encryption_key_pairs = byte_keys.map { |key|
90
+ seed = key.pack('C*').force_encoding('ASCII-8BIT')
91
+ sec_key = RbNaCl::PrivateKey.new(seed)
92
+ pub_key = sec_key.public_key
93
+ {secret_key: sec_key, public_key: pub_key}
94
+ }
95
+
96
+ nacl_encryption_key_pairs_base64 = nacl_encryption_key_pairs.map { |keypair|
97
+ pub_key = Base64.strict_encode64(keypair[:public_key].to_bytes)
98
+ sec_key = Base64.strict_encode64(keypair[:secret_key].to_bytes)
99
+ {secret_key: sec_key, public_key: pub_key}
100
+ }
101
+
102
+ nacl_signing_key_pairs = byte_keys.map { |key|
103
+ seed = key.pack('C*').force_encoding('ASCII-8BIT')
104
+ sec_key = RbNaCl::SigningKey.new(seed)
105
+ pub_key = sec_key.verify_key
106
+ {secret_key: sec_key, public_key: pub_key}
107
+ }
108
+
109
+ nacl_signing_key_pairs_base64 = nacl_signing_key_pairs.map { |keypair|
110
+ pub_key = Base64.strict_encode64(keypair[:public_key].to_bytes)
111
+ sec_key = Base64.strict_encode64(keypair[:secret_key].to_bytes)
112
+ {secret_key: sec_key, public_key: pub_key}
113
+ }
175
114
 
176
115
  {
177
- id: id_scrypt_hex,
178
- nacl_simple_box: nacl_simple_box,
179
- nacl_enc_pub_key: nacl_enc_pub_key,
180
- nacl_enc_sec_key: nacl_enc_sec_key,
181
- nacl_sig_pub_key: nacl_sig_pub_key,
182
- nacl_sig_sec_key: nacl_sig_sec_key,
183
- nacl_enc_pub_key_b64: Base64.strict_encode64(nacl_enc_pub_key.to_bytes),
184
- nacl_sig_pub_key_b64: Base64.strict_encode64(nacl_sig_pub_key.to_bytes),
116
+ id: id_sha256_hex,
117
+ byte_keys: byte_keys,
118
+ hex_keys: hex_keys,
119
+ nacl_encryption_key_pairs: nacl_encryption_key_pairs,
120
+ nacl_encryption_key_pairs_base64: nacl_encryption_key_pairs_base64,
121
+ nacl_signing_key_pairs: nacl_signing_key_pairs,
122
+ nacl_signing_key_pairs_base64: nacl_signing_key_pairs_base64,
185
123
  process_time: ((Time.now - start_processing_time)*1000).round(2)
186
124
  }
187
125
  end
@@ -1,3 +1,3 @@
1
1
  module SessionKeys
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -18,29 +18,21 @@ Gem::Specification.new do |spec|
18
18
  end
19
19
 
20
20
  spec.summary = <<-EOF
21
- SessionKeys generates a deterministic user ID and NaCl encryption/signing
21
+ SessionKeys generates deterministic user IDs and NaCl encryption/signing
22
22
  keypairs from an identifier, such as a username or email address, a
23
23
  password, and a strength value.
24
24
  EOF
25
25
 
26
26
  spec.description = <<-EOF
27
27
  SessionKeys is a cryptographic tool for the deterministic generation of
28
- NaCl compatible [Curve25519](https://cr.yp.to/ecdh.html) encryption and
29
- [Ed25519](http://ed25519.cr.yp.to) digital signature keys.
28
+ NaCl compatible Curve25519 encryption and Ed25519 digital signature keys.
30
29
 
31
- The strength of the system lies in the fact that the keypairs are derived from
30
+ The strength of the system is rooted in the fact that the keypairs are derived from
32
31
  passing an identifier, such as a username or email address, and a high-entropy
33
- passphrase through the `SHA256` hash and the `scrypt` key derivation
34
- functions. This means that no private key material need ever be stored to disk.
35
- The generated keys are deterministic; for any given ID, password, and
36
- strength combination the same keys will always be returned.
37
-
38
- The generated ID is passed through `SHA256` and `scrypt` and is derived from
39
- only the ID parameter your provide and a common salt.
40
-
41
- The password is also passed through `SHA256` and `scrypt` and NaCl encryption
42
- and signing keypairs are derived from the combination of the stretched ID,
43
- your password, and a common salt.
32
+ passphrase through the SHA256 one-way hash and the scrypt key derivation
33
+ functions. This means that no private key material need ever be writter to
34
+ disk or transmitted. The generated keys are deterministic; for any given ID,
35
+ password, and strength combination the same keys will always be returned.
44
36
  EOF
45
37
 
46
38
  spec.homepage = 'https://github.com/grempe/session-keys-rb'
@@ -51,10 +43,7 @@ Gem::Specification.new do |spec|
51
43
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
52
44
  spec.require_paths = ['lib']
53
45
 
54
- # FIXME : uncomment when @bascule publishes new rbnacl release
55
- # and remove from Gemfile.
56
- # https://github.com/cryptosphere/rbnacl/pull/135
57
- # spec.add_dependency 'rbnacl', '~> 3.3.0'
46
+ spec.add_dependency 'rbnacl', '~> 3.4.0'
58
47
  spec.add_dependency 'rbnacl-libsodium', '~> 1.0'
59
48
  spec.add_dependency 'zxcvbn-ruby', '~> 0.1'
60
49
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: session_keys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glenn Rempe
@@ -30,8 +30,22 @@ cert_chain:
30
30
  zieXiXZSAojfFx9g91fKdIrlPbInHU/BaCxXSLBwvOM0drE+c2ue9X8gB55XAhzX
31
31
  37oBiw==
32
32
  -----END CERTIFICATE-----
33
- date: 2016-05-01 00:00:00.000000000 Z
33
+ date: 2016-09-08 00:00:00.000000000 Z
34
34
  dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rbnacl
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 3.4.0
42
+ type: :runtime
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 3.4.0
35
49
  - !ruby/object:Gem::Dependency
36
50
  name: rbnacl-libsodium
37
51
  requirement: !ruby/object:Gem::Requirement
@@ -160,22 +174,14 @@ dependencies:
160
174
  version: '1.3'
161
175
  description: |2
162
176
  SessionKeys is a cryptographic tool for the deterministic generation of
163
- NaCl compatible [Curve25519](https://cr.yp.to/ecdh.html) encryption and
164
- [Ed25519](http://ed25519.cr.yp.to) digital signature keys.
177
+ NaCl compatible Curve25519 encryption and Ed25519 digital signature keys.
165
178
 
166
- The strength of the system lies in the fact that the keypairs are derived from
179
+ The strength of the system is rooted in the fact that the keypairs are derived from
167
180
  passing an identifier, such as a username or email address, and a high-entropy
168
- passphrase through the `SHA256` hash and the `scrypt` key derivation
169
- functions. This means that no private key material need ever be stored to disk.
170
- The generated keys are deterministic; for any given ID, password, and
171
- strength combination the same keys will always be returned.
172
-
173
- The generated ID is passed through `SHA256` and `scrypt` and is derived from
174
- only the ID parameter your provide and a common salt.
175
-
176
- The password is also passed through `SHA256` and `scrypt` and NaCl encryption
177
- and signing keypairs are derived from the combination of the stretched ID,
178
- your password, and a common salt.
181
+ passphrase through the SHA256 one-way hash and the scrypt key derivation
182
+ functions. This means that no private key material need ever be writter to
183
+ disk or transmitted. The generated keys are deterministic; for any given ID,
184
+ password, and strength combination the same keys will always be returned.
179
185
  email:
180
186
  - glenn@rempe.us
181
187
  executables: []
@@ -188,10 +194,12 @@ files:
188
194
  - ".ruby-version"
189
195
  - ".travis.yml"
190
196
  - ".yardopts"
197
+ - CHANGELOG.md
191
198
  - CODE_OF_CONDUCT.md
192
199
  - Gemfile
193
200
  - LICENSE.txt
194
201
  - README.md
202
+ - RELEASE.md
195
203
  - Rakefile
196
204
  - bin/console
197
205
  - bin/setup
@@ -222,8 +230,7 @@ rubyforge_project:
222
230
  rubygems_version: 2.5.1
223
231
  signing_key:
224
232
  specification_version: 4
225
- summary: SessionKeys generates a deterministic user ID and NaCl encryption/signing
233
+ summary: SessionKeys generates deterministic user IDs and NaCl encryption/signing
226
234
  keypairs from an identifier, such as a username or email address, a password, and
227
235
  a strength value.
228
236
  test_files: []
229
- has_rdoc:
metadata.gz.sig CHANGED
@@ -1,3 +1 @@
1
- Q^�Ő`�:�
2
- �gcO����ب�g�f$���È��W˷[���e M���U��cOK��zZj��4ɺ��L�9�|m��85CgE�o�H%��0���~yl�"�I'�>̼���HjX�N�`�/T�D�ۤ��7/�o��Γ��%�H�kӕ���3I���ox��e̟2+��6[��5�q<N�>TW�$^0�;8U�dW�.����k[�E]��v��I��R����8�3B������߹A
3
- ��Ÿk?
1
+ Sg{��˟��{��ۂHY���:M���J���UU-�M?ǭ�F��@�W9�� � ���h��x�r}�C����N�Ǚ�6�k3�����֞������y����s��\ �$i��]=��,P��������h)�