sekret 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.
- checksums.yaml +7 -0
- data/README.md +30 -0
- data/Rakefile +19 -0
- data/lib/sekret.rb +30 -0
- data/lib/sekret/body_encryption.rb +87 -0
- data/lib/sekret/checksum.rb +25 -0
- data/lib/sekret/cli.rb +17 -0
- data/lib/sekret/cli/help.txt.erb +10 -0
- data/lib/sekret/cli/runner.rb +69 -0
- data/lib/sekret/configuration.rb +31 -0
- data/lib/sekret/decryptor.rb +64 -0
- data/lib/sekret/encoder.rb +36 -0
- data/lib/sekret/encryptor.rb +57 -0
- data/lib/sekret/errors.rb +40 -0
- data/lib/sekret/header.rb +95 -0
- data/lib/sekret/key_generator.rb +36 -0
- data/lib/sekret/version.rb +5 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ad0d96047fe97b5ec72912cf378904b8a469335a27e43e89b1581ce89e1b1c54
|
4
|
+
data.tar.gz: 6227fc843e7e64144e7317b4d0722942569f9b2fff3f4c488fd0add2d896cca8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: faf6946b2a53332e95ccf529e4ec4f7a838c33edbba16218ea66ab437f762a1647ae0c0d7f6f89b3f5909604d0016fd43bdc0a4164f0493be981d2897bd86b67
|
7
|
+
data.tar.gz: 4cd9b9230f599cc15b3a5811cb42b1661632251031dfec629e501975c5a1bed6b7d419a2186ef069495e478e2ec8e5e0d5f1fb8b0914e9ae7e3cd3c161203377
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Sekret
|
2
|
+
|
3
|
+
|
4
|
+
### Getting Setup
|
5
|
+
|
6
|
+
There are a few config options.
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
Sekret.configure do |config|
|
10
|
+
config.mac_sekret = 'Super Sekret'
|
11
|
+
config.public_key = File.read('path to public pem')
|
12
|
+
config.private_key = File.read('path to private pem')
|
13
|
+
end
|
14
|
+
```
|
15
|
+
|
16
|
+
### Encrypt Data
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
Sekret.encrypt('This is my secret message')
|
20
|
+
|
21
|
+
# => 'abc.123'
|
22
|
+
```
|
23
|
+
|
24
|
+
### Decrypt Data
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
Sekret.decrypt('abc.123')
|
28
|
+
|
29
|
+
# => 'This is my secret message'
|
30
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
task default: :spec
|
8
|
+
|
9
|
+
namespace :docs do
|
10
|
+
desc 'Generate docs'
|
11
|
+
task :generate do
|
12
|
+
YARD::CLI::Yardoc.run
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Get docs stats'
|
16
|
+
task :stats do
|
17
|
+
YARD::CLI::Stats.run('--list-undoc')
|
18
|
+
end
|
19
|
+
end
|
data/lib/sekret.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'sekret/configuration'
|
2
|
+
require 'sekret/decryptor'
|
3
|
+
require 'sekret/encryptor'
|
4
|
+
require 'sekret/errors'
|
5
|
+
require 'sekret/key_generator'
|
6
|
+
require 'sekret/version'
|
7
|
+
|
8
|
+
##
|
9
|
+
# Used for encrypting/decrypting data
|
10
|
+
module Sekret
|
11
|
+
##
|
12
|
+
# Encrypt the passed payload
|
13
|
+
#
|
14
|
+
# @param payload [String] The plaintext to encrypt
|
15
|
+
#
|
16
|
+
# @return [String] The encrypted payload
|
17
|
+
def self.encrypt(payload)
|
18
|
+
Sekret::Encryptor.new(Sekret.config.private_key, payload).call
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Decrypt the passed payload
|
23
|
+
#
|
24
|
+
# @param message [String] the encrypted message to decrypt
|
25
|
+
#
|
26
|
+
# @return [String] The un-encrypted payload
|
27
|
+
def self.decrypt(message)
|
28
|
+
Sekret::Decryptor.new(Sekret.config.public_key, message).call
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
require_relative 'checksum'
|
4
|
+
require_relative 'configuration'
|
5
|
+
require_relative 'errors'
|
6
|
+
|
7
|
+
module Sekret
|
8
|
+
##
|
9
|
+
# Performs the AES encryption on the message body
|
10
|
+
#
|
11
|
+
# @author Maddie Schipper
|
12
|
+
# @since 1.0.0
|
13
|
+
#
|
14
|
+
# @private
|
15
|
+
class BodyEncryption
|
16
|
+
##
|
17
|
+
# The algorithm used for encryption/decryption
|
18
|
+
ALGORITHM = 'AES-256-CBC'.freeze
|
19
|
+
|
20
|
+
class << self
|
21
|
+
##
|
22
|
+
# The result of the encryption
|
23
|
+
#
|
24
|
+
# @attr key [String] The random key used for encryption
|
25
|
+
# @attr iv [String] The random iv used for encryption
|
26
|
+
# @attr checksum [String] The HMAC-SHA256 of the encrypted body
|
27
|
+
# @attr body [String] The encrypted body
|
28
|
+
Result = Struct.new(:key, :iv, :checksum, :body)
|
29
|
+
|
30
|
+
##
|
31
|
+
# Encrypt a payload using a random key and iv
|
32
|
+
#
|
33
|
+
# @param plaintext [String] The payload to encrypt
|
34
|
+
#
|
35
|
+
# @return [Result]
|
36
|
+
def encrypt(plaintext)
|
37
|
+
key = OpenSSL::Cipher.new(ALGORITHM).random_key
|
38
|
+
iv = OpenSSL::Cipher.new(ALGORITHM).random_iv
|
39
|
+
aes = OpenSSL::Cipher.new(ALGORITHM)
|
40
|
+
aes.encrypt
|
41
|
+
aes.key = key
|
42
|
+
aes.iv = iv
|
43
|
+
cipher = aes.update(plaintext)
|
44
|
+
cipher << aes.final
|
45
|
+
digest = generate_digest(cipher)
|
46
|
+
Result.new(key, iv, digest, cipher)
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Decrypt the payload
|
51
|
+
#
|
52
|
+
# @param header [Header] The header that contains the key, iv, & checksum
|
53
|
+
# @param encrypted [String] The encrypted content
|
54
|
+
#
|
55
|
+
# @return [String] The un-encrypted message
|
56
|
+
def decrypt(header, encrypted)
|
57
|
+
validate_checksum!(header.authenticity, encrypted)
|
58
|
+
aes = OpenSSL::Cipher.new(ALGORITHM)
|
59
|
+
aes.decrypt
|
60
|
+
aes.key = header.key
|
61
|
+
aes.iv = header.iv
|
62
|
+
plaintext = aes.update(encrypted)
|
63
|
+
plaintext << aes.final
|
64
|
+
plaintext
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def generate_digest(body)
|
70
|
+
return nil if Sekret.config.mac_secret.nil?
|
71
|
+
Checksum.hmac_sha256(Sekret.config.mac_secret, body)
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_checksum!(checksum, body)
|
75
|
+
return if checksum.nil?
|
76
|
+
if Sekret.config.mac_secret.nil?
|
77
|
+
raise Sekret::Errors::MissingMacSecretError,
|
78
|
+
'The encrypted message contains an authenticity. But Sekret doesn\'t have a mac_secret'
|
79
|
+
end
|
80
|
+
digest = Checksum.hmac_sha256(Sekret.config.mac_secret, body)
|
81
|
+
if digest != checksum
|
82
|
+
raise Sekret::Errors::MissmatchedMacError, 'The message authenticity doesn\'t match.'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Sekret
|
4
|
+
##
|
5
|
+
# Checksum raw data
|
6
|
+
#
|
7
|
+
# @author Maddie Schipper
|
8
|
+
# @since 1.0.0
|
9
|
+
#
|
10
|
+
# @private
|
11
|
+
class Checksum
|
12
|
+
class << self
|
13
|
+
##
|
14
|
+
# Create a HMAC-SHA256 of a playload
|
15
|
+
#
|
16
|
+
# @param key [String] The key for the hash
|
17
|
+
# @param payload [String] The payload to hash
|
18
|
+
#
|
19
|
+
# @return [String] The HMAC-SHA256
|
20
|
+
def hmac_sha256(key, payload)
|
21
|
+
OpenSSL::HMAC.hexdigest('SHA256', key, payload)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/sekret/cli.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'cli/runner'
|
2
|
+
|
3
|
+
module Sekret
|
4
|
+
##
|
5
|
+
# CLI Interface for Sekret
|
6
|
+
#
|
7
|
+
# @private
|
8
|
+
module CLI
|
9
|
+
##
|
10
|
+
# Run the CLI
|
11
|
+
#
|
12
|
+
# @param args [Array<String>] An array of arguments
|
13
|
+
def self.run(args)
|
14
|
+
Sekret::CLI::Runner.new(args).call
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module Sekret
|
5
|
+
module CLI
|
6
|
+
##
|
7
|
+
# The class that handle the CLI
|
8
|
+
#
|
9
|
+
# @author Maddie Schipper
|
10
|
+
# @since 1.0.0
|
11
|
+
#
|
12
|
+
# @private
|
13
|
+
class Runner
|
14
|
+
##
|
15
|
+
# The arguments left after parsing options
|
16
|
+
#
|
17
|
+
# @return [Array<String>]
|
18
|
+
attr_reader :args
|
19
|
+
|
20
|
+
##
|
21
|
+
# Create a new runner instance
|
22
|
+
#
|
23
|
+
# @param args [Array<String>] The CLI arguments
|
24
|
+
def initialize(args)
|
25
|
+
@args = args
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Perform the CLI call
|
30
|
+
def call
|
31
|
+
command = args.shift
|
32
|
+
case command
|
33
|
+
when 'generate-keys'
|
34
|
+
perform_generate_keys
|
35
|
+
when 'help'
|
36
|
+
print_help
|
37
|
+
when 'version'
|
38
|
+
print_version
|
39
|
+
else
|
40
|
+
raise "Unknown Command #{command}. Try `sekret help`"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def perform_generate_keys
|
47
|
+
keys = Sekret::KeyGenerator.generate_rsa_keys
|
48
|
+
puts <<~EOF
|
49
|
+
Generated new keys:
|
50
|
+
Private Key
|
51
|
+
#{keys.private_key}
|
52
|
+
Public Key
|
53
|
+
#{keys.public_key}
|
54
|
+
EOF
|
55
|
+
end
|
56
|
+
|
57
|
+
def print_help
|
58
|
+
path = ::Pathname.new(__dir__).join('help.txt.erb')
|
59
|
+
content = File.read(path)
|
60
|
+
template = ERB.new(content)
|
61
|
+
STDOUT.puts(template.result)
|
62
|
+
end
|
63
|
+
|
64
|
+
def print_version
|
65
|
+
STDOUT.puts(Sekret::VERSION)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Sekret
|
2
|
+
##
|
3
|
+
# The configuration object
|
4
|
+
#
|
5
|
+
# @attr mac_secret [String] A random secret that will be used to generate the encryption checksum.
|
6
|
+
# @attr private_key [String] A RSA private key in pem format.
|
7
|
+
# @attr public_key [String] A RSA public key in pem format.
|
8
|
+
Configuration = Struct.new(:mac_secret, :private_key, :public_key)
|
9
|
+
|
10
|
+
##
|
11
|
+
# The config lock
|
12
|
+
CONFIG_MUTEX = Mutex.new
|
13
|
+
|
14
|
+
##
|
15
|
+
# Retuns a new config
|
16
|
+
#
|
17
|
+
# @return [Configuration]
|
18
|
+
#
|
19
|
+
# @private
|
20
|
+
def self.config
|
21
|
+
CONFIG_MUTEX.synchronize do
|
22
|
+
@config ||= Configuration.new(nil, nil, nil)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Configuration
|
28
|
+
def self.configure
|
29
|
+
yield config
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
require_relative 'encoder'
|
4
|
+
require_relative 'body_encryption'
|
5
|
+
require_relative 'errors'
|
6
|
+
|
7
|
+
module Sekret
|
8
|
+
##
|
9
|
+
# Handles decrypting a message
|
10
|
+
#
|
11
|
+
# @author Maddie Schipper
|
12
|
+
# @since 1.0.0
|
13
|
+
class Decryptor
|
14
|
+
##
|
15
|
+
# An intermediate representation of the decrypted message
|
16
|
+
#
|
17
|
+
# @attr header [String] The encrypted header from the message
|
18
|
+
# @attr body [String] The encrypted body of the message
|
19
|
+
Payload = Struct.new(:header, :body)
|
20
|
+
|
21
|
+
##
|
22
|
+
# Create a new instance of Decryptor
|
23
|
+
#
|
24
|
+
# @param public_key [String] The RSA public key used for decrypting the message. (Must be in pem format)
|
25
|
+
# @param payload [String] The message payload
|
26
|
+
def initialize(public_key, payload)
|
27
|
+
@key = OpenSSL::PKey::RSA.new(public_key)
|
28
|
+
@raw_payload = payload
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Perform the decryption
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
def call
|
36
|
+
payload = create_payload
|
37
|
+
header = decrypt_raw_header(payload.header)
|
38
|
+
case header.version
|
39
|
+
when 1
|
40
|
+
Sekret::BodyEncryption.decrypt(header, payload.body)
|
41
|
+
else
|
42
|
+
raise Sekret::Errors::UnsupportedVersionError, "Can't decrypt body with version: #{header.version}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def create_payload
|
49
|
+
parts = @raw_payload.split('.')
|
50
|
+
if parts.count != 2
|
51
|
+
raise Sekret::Errors::InvalidPayloadError, "Expected a header and a body. Found #{parts.count} parts."
|
52
|
+
end
|
53
|
+
Payload.new(
|
54
|
+
Sekret::Encoder.decode(parts[0]),
|
55
|
+
Sekret::Encoder.decode(parts[1])
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def decrypt_raw_header(raw)
|
60
|
+
raw_header = @key.public_decrypt(raw)
|
61
|
+
Sekret::Header.from_decrypted(JSON.parse(raw_header))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module Sekret
|
4
|
+
##
|
5
|
+
# Encode data objects into URL safe base64
|
6
|
+
#
|
7
|
+
# @author Maddie Schipper
|
8
|
+
# @since 1.0.0
|
9
|
+
#
|
10
|
+
# @private
|
11
|
+
class Encoder
|
12
|
+
class << self
|
13
|
+
##
|
14
|
+
# Encode the value into URL safe base64
|
15
|
+
#
|
16
|
+
# @param value [String] the data to encode
|
17
|
+
#
|
18
|
+
# @return [String] A URL safe base64 encoded string
|
19
|
+
def encode(value)
|
20
|
+
Base64.urlsafe_encode64(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Decode the URL safe base64 string into it's raw data
|
25
|
+
#
|
26
|
+
# @param value [String] URL safe base64 string
|
27
|
+
#
|
28
|
+
# @return [String] A decoded data string
|
29
|
+
def decode(value)
|
30
|
+
##
|
31
|
+
# Decode the URL safe base64 into it's raw format
|
32
|
+
Base64.urlsafe_decode64(value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative 'body_encryption'
|
2
|
+
require_relative 'encoder'
|
3
|
+
require_relative 'header'
|
4
|
+
|
5
|
+
module Sekret
|
6
|
+
##
|
7
|
+
# Encrypt a message
|
8
|
+
#
|
9
|
+
# @author Maddie Schipper
|
10
|
+
# @since 1.0.0
|
11
|
+
class Encryptor
|
12
|
+
##
|
13
|
+
# The version of the encryption format
|
14
|
+
VERSON = 1
|
15
|
+
|
16
|
+
##
|
17
|
+
# Create a new instance of Encryptor
|
18
|
+
#
|
19
|
+
# @param private_key [String] The RSA private key used for encrypting the message. (Must be in pem format)
|
20
|
+
# @param payload [String] The message payload
|
21
|
+
#
|
22
|
+
# @return [Encryptor]
|
23
|
+
def initialize(private_key, payload)
|
24
|
+
@key = OpenSSL::PKey::RSA.new(private_key)
|
25
|
+
@payload = payload
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Perform the encryption
|
30
|
+
#
|
31
|
+
# @return [String]
|
32
|
+
def call
|
33
|
+
result = Sekret::BodyEncryption.encrypt(@payload)
|
34
|
+
header = create_header(result)
|
35
|
+
[
|
36
|
+
Sekret::Encoder.encode(encrypt_header(header)),
|
37
|
+
Sekret::Encoder.encode(result.body)
|
38
|
+
].join('.')
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def create_header(result)
|
44
|
+
Sekret::Header.new(
|
45
|
+
result.checksum,
|
46
|
+
result.key,
|
47
|
+
result.iv,
|
48
|
+
VERSON,
|
49
|
+
Sekret::BodyEncryption::ALGORITHM
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
def encrypt_header(header)
|
54
|
+
@key.private_encrypt(header.to_s)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Sekret
|
2
|
+
##
|
3
|
+
# Custom errors raised by Sekret
|
4
|
+
module Errors
|
5
|
+
##
|
6
|
+
# The base Error
|
7
|
+
#
|
8
|
+
# @author Maddie Schipper
|
9
|
+
# @since 1.0.0
|
10
|
+
class BaseError < StandardError; end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Error raised when a `mac_secret` isn't available for creating the message authenticity
|
14
|
+
#
|
15
|
+
# @author Maddie Schipper
|
16
|
+
# @since 1.0.0
|
17
|
+
class MissingMacSecretError < BaseError; end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Error raised if the encryption checksum doesn't match
|
21
|
+
#
|
22
|
+
# @author Maddie Schipper
|
23
|
+
# @since 1.0.0
|
24
|
+
class MissmatchedMacError < BaseError; end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Error raised if the payload to be decrypted is invalid
|
28
|
+
#
|
29
|
+
# @author Maddie Schipper
|
30
|
+
# @since 1.0.0
|
31
|
+
class InvalidPayloadError < BaseError; end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Error raised if the message header has an unsupported version
|
35
|
+
#
|
36
|
+
# @author Maddie Schipper
|
37
|
+
# @since 1.0.0
|
38
|
+
class UnsupportedVersionError < BaseError; end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require_relative 'encoder'
|
4
|
+
|
5
|
+
module Sekret
|
6
|
+
##
|
7
|
+
# A Payload header
|
8
|
+
#
|
9
|
+
# @note You should never directly create a Header
|
10
|
+
#
|
11
|
+
# @author Maddie Schipper
|
12
|
+
# @since 1.0.0
|
13
|
+
#
|
14
|
+
# @private
|
15
|
+
class Header
|
16
|
+
##
|
17
|
+
# The authenticity token for the header
|
18
|
+
# @return [String]
|
19
|
+
attr_reader :authenticity
|
20
|
+
|
21
|
+
##
|
22
|
+
# The key used to encrypt the body
|
23
|
+
# @return [String]
|
24
|
+
attr_reader :key
|
25
|
+
|
26
|
+
##
|
27
|
+
# The initialization vector used to encrypt the body
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :iv
|
30
|
+
|
31
|
+
##
|
32
|
+
# The encryption version for the body
|
33
|
+
# @return [Integer]
|
34
|
+
attr_reader :version
|
35
|
+
|
36
|
+
##
|
37
|
+
# The encryption algorithm used to encrypt the body
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :algorithm
|
40
|
+
|
41
|
+
##
|
42
|
+
# Create a new header
|
43
|
+
#
|
44
|
+
# @note You should never directly create a Payload
|
45
|
+
#
|
46
|
+
# @param authenticity (see #authenticity)
|
47
|
+
# @param key (see #key)
|
48
|
+
# @param eiv (see #iv)
|
49
|
+
# @param version (see #version)
|
50
|
+
# @param algorithm (see #algorithm)
|
51
|
+
def initialize(authenticity, key, eiv, version, algorithm)
|
52
|
+
@authenticity = authenticity
|
53
|
+
@key = key
|
54
|
+
@iv = eiv
|
55
|
+
@version = version
|
56
|
+
@algorithm = algorithm
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# @private
|
61
|
+
#
|
62
|
+
# Create a header from a decrypted hash
|
63
|
+
def self.from_decrypted(hash)
|
64
|
+
new(
|
65
|
+
hash['aut'],
|
66
|
+
Encoder.decode(hash['key']),
|
67
|
+
Encoder.decode(hash['eiv']),
|
68
|
+
hash['ver'],
|
69
|
+
hash['alg']
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Convert the header into it's hash format
|
75
|
+
#
|
76
|
+
# @return [Hash]
|
77
|
+
def to_h
|
78
|
+
{
|
79
|
+
aut: authenticity,
|
80
|
+
key: Encoder.encode(key),
|
81
|
+
eiv: Encoder.encode(iv),
|
82
|
+
ver: version,
|
83
|
+
alg: algorithm
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Convert the header into it's string format
|
89
|
+
#
|
90
|
+
# @return [String]
|
91
|
+
def to_s
|
92
|
+
JSON.dump(to_h)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Sekret
|
4
|
+
##
|
5
|
+
# Create new keys for encryption
|
6
|
+
#
|
7
|
+
# @author Maddie Schipper
|
8
|
+
# @since 1.0.0
|
9
|
+
class KeyGenerator
|
10
|
+
##
|
11
|
+
# A new key object
|
12
|
+
#
|
13
|
+
# @attr public_key [String] Public key in pem format.
|
14
|
+
# @attr private_key [String] Private key in pem format.
|
15
|
+
Key = Struct.new(:public_key, :private_key)
|
16
|
+
|
17
|
+
class << self
|
18
|
+
##
|
19
|
+
# Generate a new RSA public/private key pair
|
20
|
+
#
|
21
|
+
# @param size [Integer] size of the RSA key to generate
|
22
|
+
# (defaults to 2048)
|
23
|
+
#
|
24
|
+
# @return [Key] the new public & private keys.
|
25
|
+
#
|
26
|
+
# @note The returned key is read-only
|
27
|
+
def generate_rsa_keys(size = 2048)
|
28
|
+
rsa_key = OpenSSL::PKey::RSA.new(size)
|
29
|
+
Key.new(
|
30
|
+
rsa_key.public_key.to_pem,
|
31
|
+
rsa_key.to_pem
|
32
|
+
).freeze
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sekret
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maddie Schipper
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.10.1
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.10.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.16.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.16.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.9.16
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.9.16
|
97
|
+
description: Create/Decode semetric encryption
|
98
|
+
email:
|
99
|
+
- me@maddiesch.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- lib/sekret.rb
|
107
|
+
- lib/sekret/body_encryption.rb
|
108
|
+
- lib/sekret/checksum.rb
|
109
|
+
- lib/sekret/cli.rb
|
110
|
+
- lib/sekret/cli/help.txt.erb
|
111
|
+
- lib/sekret/cli/runner.rb
|
112
|
+
- lib/sekret/configuration.rb
|
113
|
+
- lib/sekret/decryptor.rb
|
114
|
+
- lib/sekret/encoder.rb
|
115
|
+
- lib/sekret/encryptor.rb
|
116
|
+
- lib/sekret/errors.rb
|
117
|
+
- lib/sekret/header.rb
|
118
|
+
- lib/sekret/key_generator.rb
|
119
|
+
- lib/sekret/version.rb
|
120
|
+
homepage: https://github.com/maddiesch/sekret
|
121
|
+
licenses: []
|
122
|
+
metadata:
|
123
|
+
allowed_push_host: https://rubygems.org
|
124
|
+
yard.run: yri
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.7.6
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: Semetric Encryption
|
145
|
+
test_files: []
|