scl 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +90 -5
- data/Rakefile +9 -1
- data/lib/scl/aes.rb +3 -3
- data/lib/scl/control/aes.rb +10 -0
- data/lib/scl/control/controller.rb +0 -1
- data/lib/scl/control/rsa.rb +1 -1
- data/lib/scl/digest.rb +1 -1
- data/lib/scl/formats/auto.rb +2 -2
- data/lib/scl/formats/words.rb +1 -1
- data/lib/scl/rsa.rb +5 -4
- data/lib/scl/secret_share.rb +53 -52
- data/lib/scl/version.rb +1 -1
- data/scl.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd44c29e009a373f15867aabba011afd2081eec8
|
4
|
+
data.tar.gz: fd478293a6d0cf19c22d6b13c8aac6dfbb755ecc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40f19d23ec8425cfbe315c74b5be4329c5f494822ac54f0a3d3025bac27df4332547bb7b0e2a6546eb81ed1357dbbf9611ba36314eaeff5a3e8d0ab4ce826d75
|
7
|
+
data.tar.gz: 052ad1a09df6f1280680b433ccb9d8242abf6dfebb32ede7943ca6be47667a02dfdf2de5a2c4dfbe8e158e67067a5071e0b4639fdc754423cfbd054748600f45
|
data/README.md
CHANGED
@@ -1,8 +1,22 @@
|
|
1
1
|
# Scl (Simple Crypto Library)
|
2
2
|
|
3
|
-
|
3
|
+
Scl is the Ruby *Simple Cryptography Library*. It comes with both a library for use in a Ruby codebase and a fully featured command line tool for all of your basic cryptography needs.
|
4
4
|
|
5
|
-
|
5
|
+
As anybody in the crypto-space knows using any cryptography library that has not been extensively audited and battle-tested in a security critical system is asking for trouble, hence:<br/>
|
6
|
+
**This library is intended for use in hobbyist projects or educational purposes. Use at own risk**
|
7
|
+
|
8
|
+
For much of its functionality it is simply a fairly thin wrapper over OpenSSL functions and primitives and therefore should be quite robust and performant. It couples this with a clean and easy to use API making it a fantastic tool to learn about what cryptography has to offer.
|
9
|
+
|
10
|
+
With learning in mind it covers some of the most widely used and exciting functionality offered to us by cryptography.
|
11
|
+
|
12
|
+
* [Diffie Hellman key-exchange](#diffie-hellman-key-exchange)
|
13
|
+
* [Public-key encryption (RSA)](#rsa-encryption)
|
14
|
+
* [Public-key verification (RSA)](#rsa-verification)
|
15
|
+
* [Shamirs secret sharing](#shamirs-secret-sharing)
|
16
|
+
* [AES Block Cipher Encryption](#aes-encryption)
|
17
|
+
* [HMAC and Digests](#hmac-and-digests)
|
18
|
+
|
19
|
+
This tool provides basic insight around what each of the above has to offer us, and how you might potentially use these in unison to offer secure and/or verifiable solutions. Each of the above modules can be used from the command line interface, or imported directly into your code
|
6
20
|
|
7
21
|
## Installation
|
8
22
|
|
@@ -20,6 +34,76 @@ Or install it yourself as:
|
|
20
34
|
|
21
35
|
$ gem install scl
|
22
36
|
|
37
|
+
## Usage (per module)
|
38
|
+
|
39
|
+
### Diffie Hellman Key Exchange
|
40
|
+
#### What is it?
|
41
|
+
Diffie–Hellman key exchange (D–H) is a method of securely exchanging cryptographic keys over a public channel and was one of the first public-key protocols as originally conceptualized by Ralph Merkle and named after Whitfield Diffie and Martin Hellman.<sup>[[1]]</sup>
|
42
|
+
|
43
|
+
#### How do I use it?
|
44
|
+
##### CLI
|
45
|
+
##### Library
|
46
|
+
#### Why is it great?
|
47
|
+
* You can agree on a shared secret on a public-channel without exposing anything to an eavesdropper.
|
48
|
+
* This means you do not need to trust your communication channel for it to be effective! (You could securely communicate using snail mail, smoke signals, carrier pigeons) and as long as both parties to the transmission properly secure the generated private and shared keys of the exchange you can know your communication is secure and private
|
49
|
+
* You do not need to share any secrets to complete the exchange.
|
50
|
+
* You can negotitate a new secret per transmission for perfect forward secrecy
|
51
|
+
|
52
|
+
#### How does it work?
|
53
|
+
|
54
|
+
### RSA(Encryption)
|
55
|
+
#### What is it?
|
56
|
+
RSA can be used to encrypt and decrypt messages utilising public-key cryptography.
|
57
|
+
|
58
|
+
Public key cryptography, or asymmetrical cryptography, is any cryptographic system that uses pairs of keys: public keys which may be disseminated widely, and private keys which are known only to the owner. This accomplishes two functions: authentication, which is when the public key is used to verify that a holder of the paired private key sent the message, and encryption, whereby only the holder of the paired private key can decrypt the message encrypted with the public key.<sup>[[2]]</sup>
|
59
|
+
|
60
|
+
#### How do I use it?
|
61
|
+
##### CLI
|
62
|
+
##### Library
|
63
|
+
#### Why is it great?
|
64
|
+
* You can use your private key to prove a message came from you
|
65
|
+
* Anyone can use your public key to construct a message for your eyes only
|
66
|
+
* You can establish secure communications between two or more parties without the need to engage in a key-negotiation process
|
67
|
+
* See also RSA(Verification)
|
68
|
+
|
69
|
+
#### How does it work?
|
70
|
+
|
71
|
+
### RSA(Verification)
|
72
|
+
#### What is it?
|
73
|
+
RSA can be used to generate digital signatures for a message and to compare a given signature with one generated from a digital message.
|
74
|
+
|
75
|
+
A digital signature is a mathematical scheme for demonstrating the authenticity of digital messages or documents. A valid digital signature gives a recipient reason to believe that the message was created by a known sender (authentication), that the sender cannot deny having sent the message (non-repudiation), and that the message was not altered in transit (integrity)<sup>[[3]]</sup>
|
76
|
+
#### How do I use it?
|
77
|
+
##### CLI
|
78
|
+
##### Library
|
79
|
+
#### Why is it great?
|
80
|
+
* See also RSA(Encryption)
|
81
|
+
#### How does it work?
|
82
|
+
|
83
|
+
### Shamir's Secret Sharing
|
84
|
+
#### What is it?
|
85
|
+
#### How do I use it?
|
86
|
+
##### CLI
|
87
|
+
##### Library
|
88
|
+
#### Why is it great?
|
89
|
+
#### How does it work?
|
90
|
+
|
91
|
+
### AES Encryption
|
92
|
+
#### What is it?
|
93
|
+
#### How do I use it?
|
94
|
+
##### CLI
|
95
|
+
##### Library
|
96
|
+
#### Why is it great?
|
97
|
+
#### How does it work?
|
98
|
+
|
99
|
+
### HMAC and Digests
|
100
|
+
#### What is it?
|
101
|
+
#### How do I use it?
|
102
|
+
##### CLI
|
103
|
+
##### Library
|
104
|
+
#### Why is it great?
|
105
|
+
#### How does it work?
|
106
|
+
|
23
107
|
## CLI
|
24
108
|
|
25
109
|
SCL Comes with a command line interface that allows you to perform basic encryption, decryption and key generation and key negotiation operations.
|
@@ -52,9 +136,6 @@ scl aes encrypt [file] # Encrypt from file
|
|
52
136
|
scl aes encrypt --key="abc" [file] # Enc
|
53
137
|
```
|
54
138
|
|
55
|
-
## Usage
|
56
|
-
|
57
|
-
TODO: Write usage instructions here
|
58
139
|
|
59
140
|
## Development
|
60
141
|
|
@@ -69,3 +150,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERN
|
|
69
150
|
## Code of Conduct
|
70
151
|
|
71
152
|
Everyone interacting in the Scl project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/scl/blob/master/CODE_OF_CONDUCT.md).
|
153
|
+
|
154
|
+
[1]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
|
155
|
+
[2]: https://en.wikipedia.org/wiki/Public-key_cryptography
|
156
|
+
[3]: https://en.wikipedia.org/wiki/Digital_signature
|
data/Rakefile
CHANGED
data/lib/scl/aes.rb
CHANGED
@@ -5,12 +5,12 @@ module Scl
|
|
5
5
|
@block_size = block_size || 256
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
8
|
+
def build_cipher
|
9
9
|
OpenSSL::Cipher::AES.new(@block_size, @block_cipher)
|
10
10
|
end
|
11
11
|
|
12
12
|
def encrypt(plaintext, key=nil, iv=nil)
|
13
|
-
block_cipher =
|
13
|
+
block_cipher = build_cipher
|
14
14
|
block_cipher.encrypt
|
15
15
|
block_cipher.key = key ||= block_cipher.random_key
|
16
16
|
block_cipher.iv = iv ||= block_cipher.random_iv
|
@@ -18,7 +18,7 @@ module Scl
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def decrypt(ciphertext, key, iv)
|
21
|
-
block_cipher =
|
21
|
+
block_cipher = build_cipher
|
22
22
|
block_cipher.decrypt
|
23
23
|
block_cipher.key = key
|
24
24
|
block_cipher.iv = iv
|
data/lib/scl/control/aes.rb
CHANGED
@@ -42,6 +42,16 @@ module Scl
|
|
42
42
|
)
|
43
43
|
end
|
44
44
|
|
45
|
+
help <<-HELP,
|
46
|
+
ciphers. Prints a list of supported ciphers
|
47
|
+
|
48
|
+
e.g
|
49
|
+
scl aes ciphers
|
50
|
+
HELP
|
51
|
+
def ciphers
|
52
|
+
puts OpenSSL::Cipher.ciphers.select{|x| x[/^aes/]}
|
53
|
+
end
|
54
|
+
|
45
55
|
private
|
46
56
|
def aes
|
47
57
|
Scl::AES.new(args.block_size, args.block_cipher)
|
@@ -46,7 +46,6 @@ module Scl
|
|
46
46
|
case "#{format}".strip
|
47
47
|
when "base64" then Format::BASE64
|
48
48
|
when "qrcode" then Format::QRCODE
|
49
|
-
when "base64" then Format::BASE64
|
50
49
|
when "words" then Format::WORDS
|
51
50
|
when "hex" then Format::HEX
|
52
51
|
when "binary","text","none" then Format::BINARY
|
data/lib/scl/control/rsa.rb
CHANGED
data/lib/scl/digest.rb
CHANGED
@@ -18,7 +18,7 @@ module Scl
|
|
18
18
|
def self.digest_exists?(digest)
|
19
19
|
begin
|
20
20
|
OpenSSL::Digest.const_get(digest.upcase)
|
21
|
-
rescue NameError
|
21
|
+
rescue NameError
|
22
22
|
puts "Couldn't get digest type. #{digest}"
|
23
23
|
puts "Try $ scl digest list – for a list of supported digests"
|
24
24
|
return false
|
data/lib/scl/formats/auto.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Scl
|
2
2
|
class Scl::Auto < Scl::Format
|
3
3
|
def encode(data)
|
4
|
-
sorted = (data.chars.map(&:ord).uniq.sort) - [10]
|
4
|
+
sorted = (data.force_encoding("binary").chars.map(&:ord).uniq.sort) - [10]
|
5
5
|
if sorted.first < 32 || sorted.max > 126
|
6
6
|
Scl::Format::BASE64.encode(data)
|
7
7
|
else
|
@@ -11,7 +11,7 @@ module Scl
|
|
11
11
|
|
12
12
|
def decode(data)
|
13
13
|
png = Regexp.new("\x89PNG".force_encoding("binary"))
|
14
|
-
if /^#{png}/ === data
|
14
|
+
if /^#{png}/ === data.force_encoding("binary")
|
15
15
|
Scl::Format::QRCODE.decode(data)
|
16
16
|
elsif data[/[^A-Za-z0-9\+\/\n=]/]
|
17
17
|
Scl::Format::BINARY.decode(data)
|
data/lib/scl/formats/words.rb
CHANGED
data/lib/scl/rsa.rb
CHANGED
@@ -9,13 +9,14 @@ module Scl
|
|
9
9
|
@public = public
|
10
10
|
@private = private
|
11
11
|
end
|
12
|
+
@output_encoder = output_encoder
|
12
13
|
@public = Key.new(@public)
|
13
14
|
@private = Key.new(@private)
|
14
15
|
end
|
15
16
|
|
16
17
|
def save(dir, name='rsa-keypair')
|
17
|
-
IO.write(File.join(dir, "#{name}.pub"), output_encoder.encode(@public.export))
|
18
|
-
IO.write(File.join(dir, "#{name}.priv"), output_encoder.encode(@private.export))
|
18
|
+
IO.write(File.join(dir, "#{name}.pub"), @output_encoder.encode(@public.export))
|
19
|
+
IO.write(File.join(dir, "#{name}.priv"), @output_encoder.encode(@private.export))
|
19
20
|
dir
|
20
21
|
end
|
21
22
|
|
@@ -24,8 +25,8 @@ module Scl
|
|
24
25
|
RSA.new(public: rsa_pair.public_key, private: rsa_pair)
|
25
26
|
end
|
26
27
|
|
27
|
-
def self.encrypt(msg)
|
28
|
-
pair = self.generate
|
28
|
+
def self.encrypt(msg, key_size=1024)
|
29
|
+
pair = self.generate(key_size)
|
29
30
|
[pair.private.export, pair.public.export, pair.private.encrypt(msg)]
|
30
31
|
end
|
31
32
|
|
data/lib/scl/secret_share.rb
CHANGED
@@ -13,39 +13,16 @@ module Scl
|
|
13
13
|
@shares = shares
|
14
14
|
end
|
15
15
|
|
16
|
-
def random()
|
17
|
-
@seen ||= { nil => true}
|
18
|
-
number = Random.rand(1...PRIME) while @seen[number]
|
19
|
-
@seen[number] = true
|
20
|
-
OpenSSL::BN.new(number)
|
21
|
-
end
|
22
|
-
|
23
|
-
def chunks(secret)
|
24
|
-
Enumerator.new do |enum|
|
25
|
-
as_hex = secret.each_byte.map{|b| b.to_s(16).rjust(2, '0') }.join
|
26
|
-
as_hex.chars.each_slice(64) do |slice|
|
27
|
-
chunk = OpenSSL::BN.new(slice.join.ljust(64, ?0), 16)
|
28
|
-
enum << chunk
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def evaluate_polynomial(polynomial, x)
|
34
|
-
polynomial.reverse.reduce(OpenSSL::BN.new(0)) do |mem, value|
|
35
|
-
((mem * x) % PRIME + value) % PRIME
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
16
|
def generate(secret)
|
40
17
|
polynomials = chunks(secret).map do |chunk|
|
41
|
-
|
18
|
+
[chunk] + (@minimum - 1).times.map do |i|
|
42
19
|
random
|
43
20
|
end
|
44
21
|
end
|
45
22
|
|
46
23
|
@shares.times.map do |i|
|
47
24
|
result = ''
|
48
|
-
|
25
|
+
polynomials.map do |polynomial|
|
49
26
|
x = random
|
50
27
|
y = evaluate_polynomial(polynomial, x)
|
51
28
|
result << base64_encode(x)
|
@@ -55,34 +32,7 @@ module Scl
|
|
55
32
|
end
|
56
33
|
end
|
57
34
|
|
58
|
-
def base64_encode(number)
|
59
|
-
return ::Base64.urlsafe_encode64(number.to_s(16).rjust(64, ?0).scan(/../).map{|x| x.hex.chr}.join)
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.base64_decode(number)
|
63
|
-
::Base64.urlsafe_decode64(number).chars.map{|x| "0#{x.ord.to_s(16)}"[-2..-1] }.join.rjust(64, ?0).hex
|
64
|
-
end
|
65
|
-
|
66
|
-
def self.extended_gcd(a, b)
|
67
|
-
abs = ->(v){ v < 0 ? v * -1 : v}
|
68
|
-
last_remainder, remainder = abs[a], abs[b]
|
69
|
-
x, last_x, y, last_y = 0, 1, 1, 0
|
70
|
-
while remainder != 0
|
71
|
-
last_remainder, (quotient, remainder) = remainder, last_remainder./(remainder)
|
72
|
-
x, last_x = last_x - quotient*x, x
|
73
|
-
y, last_y = last_y - quotient*y, y
|
74
|
-
end
|
75
|
-
|
76
|
-
return last_remainder, last_x * (a < 0 ? -1 : 1)
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.mod_inverse(e, p=PRIME)
|
80
|
-
g, x = extended_gcd(e, p)
|
81
|
-
x % p
|
82
|
-
end
|
83
|
-
|
84
35
|
def self.combine(shares, encoder: nil)
|
85
|
-
abs = ->(v){ v < 0 ? v * -1 : v}
|
86
36
|
decoded = shares.map do |share|
|
87
37
|
share = encoder && encoder != Format::BASE64 ? encoder.decode(share) : share
|
88
38
|
share.chars.each_slice(ENCODED_CHUNK_SIZE).map(&:join).each_slice(2).map do |random, polynomial|
|
@@ -118,5 +68,56 @@ module Scl
|
|
118
68
|
}
|
119
69
|
end.join
|
120
70
|
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def random()
|
74
|
+
@seen ||= { nil => true}
|
75
|
+
number = Random.rand(1...PRIME) while @seen[number]
|
76
|
+
@seen[number] = true
|
77
|
+
OpenSSL::BN.new(number)
|
78
|
+
end
|
79
|
+
|
80
|
+
def chunks(secret)
|
81
|
+
Enumerator.new do |enum|
|
82
|
+
as_hex = secret.each_byte.map{|b| b.to_s(16).rjust(2, '0') }.join
|
83
|
+
as_hex.chars.each_slice(64) do |slice|
|
84
|
+
chunk = OpenSSL::BN.new(slice.join.ljust(64, ?0), 16)
|
85
|
+
enum << chunk
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def evaluate_polynomial(polynomial, x)
|
91
|
+
polynomial.reverse.reduce(OpenSSL::BN.new(0)) do |mem, value|
|
92
|
+
((mem * x) % PRIME + value) % PRIME
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def base64_encode(number)
|
98
|
+
return ::Base64.urlsafe_encode64(number.to_s(16).rjust(64, ?0).scan(/../).map{|x| x.hex.chr}.join)
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.base64_decode(number)
|
102
|
+
::Base64.urlsafe_decode64(number).chars.map{|x| "0#{x.ord.to_s(16)}"[-2..-1] }.join.rjust(64, ?0).hex
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.extended_gcd(a, b)
|
106
|
+
abs = ->(v){ v < 0 ? v * -1 : v}
|
107
|
+
last_remainder, remainder = abs[a], abs[b]
|
108
|
+
x, last_x, y, last_y = 0, 1, 1, 0
|
109
|
+
while remainder != 0
|
110
|
+
last_remainder, (quotient, remainder) = remainder, last_remainder./(remainder)
|
111
|
+
x, last_x = last_x - quotient*x, x
|
112
|
+
y, last_y = last_y - quotient*y, y
|
113
|
+
end
|
114
|
+
|
115
|
+
return last_remainder, last_x * (a < 0 ? -1 : 1)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.mod_inverse(e, p=PRIME)
|
119
|
+
_, x = extended_gcd(e, p)
|
120
|
+
x % p
|
121
|
+
end
|
121
122
|
end
|
122
123
|
end
|
data/lib/scl/version.rb
CHANGED
data/scl.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Scl::VERSION
|
9
9
|
spec.authors = ["Wouter Coppieters"]
|
10
10
|
spec.email = ["wouter@youdo.co.nz"]
|
11
|
-
|
11
|
+
spec.homepage = "https://github.com/wouterken/scl"
|
12
12
|
spec.summary = "Simple crypto library"
|
13
13
|
spec.description = "Simple crypto library"
|
14
14
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11-
|
11
|
+
date: 2017-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,7 +94,7 @@ files:
|
|
94
94
|
- lib/scl/secret_share.rb
|
95
95
|
- lib/scl/version.rb
|
96
96
|
- scl.gemspec
|
97
|
-
homepage:
|
97
|
+
homepage: https://github.com/wouterken/scl
|
98
98
|
licenses: []
|
99
99
|
metadata: {}
|
100
100
|
post_install_message:
|