sgpg 0.1.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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE +674 -0
- data/README.md +50 -0
- data/bin/sgpg +72 -0
- data/lib/sgpg/archive.rb +91 -0
- data/lib/sgpg/cryptsetup.rb +69 -0
- data/lib/sgpg/gpg.rb +47 -0
- data/lib/sgpg/helper.rb +14 -0
- data/lib/sgpg/mount.rb +67 -0
- data/lib/sgpg/option.rb +9 -0
- data/lib/sgpg/version.rb +5 -0
- data/lib/sgpg/yaml_config.rb +68 -0
- data/lib/sgpg.rb +90 -0
- data/sgpg.gemspec +45 -0
- data.tar.gz.sig +0 -0
- metadata +97 -0
- metadata.gz.sig +0 -0
data/README.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Sgpg
|
2
|
+
Short gpg, tool for manage your gpg key (backup tarball, unprivileged keys, etc)
|
3
|
+
|
4
|
+
Followed my [post](https://szorfein.github.io/gpg/build-secure-gpg-key/) to
|
5
|
+
create a secure gpg key, i need to update my key all the 6 month on each PC
|
6
|
+
and each time, it's very very annoying so i build this tool to gain in time
|
7
|
+
and sanity :).
|
8
|
+
|
9
|
+
So with this tool, 'i,you,we' should use no more than 3 commands max instead of 50...
|
10
|
+
|
11
|
+
You always need to create a gpg key as well
|
12
|
+
|
13
|
+
gpg --expert --full-generate-key
|
14
|
+
|
15
|
+
## Install sgpg locally
|
16
|
+
|
17
|
+
gem install sgpg
|
18
|
+
|
19
|
+
You also need to install dependencies: tar, cryptsetup, shred and gpg.
|
20
|
+
|
21
|
+
## Configure
|
22
|
+
The config is located at ~/.config/sgpg/config.yml. You can use the command line with `--save`:
|
23
|
+
|
24
|
+
sgpg --disk /dev/sdc2 --disk-encrypt --key szorfein@protonmail.com --save
|
25
|
+
|
26
|
+
You can register the disk/by-id or disk/by-uuid if you prefer.
|
27
|
+
|
28
|
+
sgpg --disk /dev/disk/by-id/wmn-0xXXXX-part2 --disk-encrypt --save
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
sgpg -h
|
33
|
+
|
34
|
+
When subkeys expire:
|
35
|
+
|
36
|
+
sgpg --last-master --edit-key # update expired keys, change password, etc...
|
37
|
+
sgpg --export
|
38
|
+
sgpg --close # unmount and close disk
|
39
|
+
|
40
|
+
Import the last unpriviliged key (laptop and other)
|
41
|
+
|
42
|
+
sgpg --last-lesser --edit-key # trust (555)
|
43
|
+
sgpg --close # unmount and close disk
|
44
|
+
|
45
|
+
## Gem push
|
46
|
+
|
47
|
+
gem login
|
48
|
+
gem build sgpg.gemspec
|
49
|
+
gem push sgpg-0.0.1.gem
|
50
|
+
|
data/bin/sgpg
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'sgpg'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
config_file = Sgpg::YamlConfig.new
|
8
|
+
config_file.load
|
9
|
+
|
10
|
+
options = config_file.config
|
11
|
+
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = 'Usage: sgpg.rb [options]'
|
14
|
+
|
15
|
+
opts.on('-d', '--disk DEV', 'Specify device disk to use to save your keys') do |dev|
|
16
|
+
options[:disk] = dev
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on('--disk-encrypt', 'If we need to use cryptsetup to open the disk.') do
|
20
|
+
options[:crypted] = true
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('-k', '--key NAME', 'Use the key name, default use ENV["USER"]') do |name|
|
24
|
+
options[:keyname] = name
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('-e', '--edit-key', 'Edit your secret key.') do
|
28
|
+
Sgpg::Main.edit_key(options)
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-l', '--list-key', "Display the last secret key #{Sgpg::MOUNTPOINT}.") do
|
32
|
+
Sgpg.list_keys(options[:keyname])
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('-o', '--open', "Open and mount device disk at #{Sgpg::MOUNTPOINT}.") do
|
36
|
+
Sgpg.open(options[:disk], options[:crypted])
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on('-p', '--path-key PATH', 'use archive PATH') do |path|
|
40
|
+
raise "path #{path} didn't found" unless File.exist? path
|
41
|
+
|
42
|
+
options[:keypath] = path
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on('--last-master', 'Use the last archive master') do
|
46
|
+
options[:keypath] = Sgpg.last_key(options, 'master')
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on('--last-lesser', 'Use the last archive lesser (unpriviliged)') do
|
50
|
+
options[:keypath] = Sgpg.last_key(options, 'lesser')
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on('-c', '--close', 'Unmount and close disk device.') do
|
54
|
+
Sgpg.close(options[:disk], options[:crypted])
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on('-s', '--save', 'Save current optargs in the config file') do
|
58
|
+
config_file.save(options)
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on('--export', 'Export your current master key and create both archives (master and lesser)') do
|
62
|
+
Sgpg::Main.export_secret(options)
|
63
|
+
Sgpg::Main.lesser_keys(options)
|
64
|
+
end
|
65
|
+
end.parse!
|
66
|
+
|
67
|
+
raise 'no disk to use' if !options[:disk] || options[:disk] == ''
|
68
|
+
raise 'no key to use' if !options[:keyname] || options[:keybase] == ''
|
69
|
+
|
70
|
+
puts config_file
|
71
|
+
|
72
|
+
puts "Sgpg v.#{Sgpg::VERSION}"
|
data/lib/sgpg/archive.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Sgpg
|
6
|
+
# Interact with program tar from unix
|
7
|
+
class Archive
|
8
|
+
# Code here
|
9
|
+
def initialize(key, name = ENV['USER'])
|
10
|
+
@key = key || ''
|
11
|
+
@name = name
|
12
|
+
@date = Time.now.strftime('%Y-%m-%d')
|
13
|
+
puts "create key #{@name}-#{@date}-master.tar"
|
14
|
+
FileUtils.mkdir_p Sgpg::WORKDIR
|
15
|
+
@gpg = Gpg.new(@name)
|
16
|
+
# make it compatabble with Tails Linux
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_master_tar
|
20
|
+
Dir.chdir(Sgpg::WORKDIR)
|
21
|
+
@gpg.export_secret_keys(Sgpg::WORKDIR)
|
22
|
+
create_tar('master')
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_lesser_tar
|
26
|
+
Dir.chdir(Sgpg::WORKDIR)
|
27
|
+
@gpg.export_subkey(Sgpg::WORKDIR)
|
28
|
+
@gpg.delete_keys
|
29
|
+
@gpg.import_lesser_keys
|
30
|
+
@gpg.export_secret_keys(Sgpg::WORKDIR)
|
31
|
+
create_tar('lesser')
|
32
|
+
end
|
33
|
+
|
34
|
+
def extract
|
35
|
+
raise 'No key found, try with --path-key PATH.' unless File.exist?(@key)
|
36
|
+
|
37
|
+
Dir.chdir(Sgpg::WORKDIR)
|
38
|
+
puts "Unpacking archive #{@key}..."
|
39
|
+
system('tar', 'xvf', @key)
|
40
|
+
end
|
41
|
+
|
42
|
+
def import
|
43
|
+
@gpg.delete_keys
|
44
|
+
puts 'Importing gpg keys...'
|
45
|
+
keys = Dir.glob("#{Sgpg::WORKDIR}/*.key")
|
46
|
+
import_secret(keys)
|
47
|
+
import_public(keys)
|
48
|
+
@gpg.edit_key
|
49
|
+
end
|
50
|
+
|
51
|
+
def move(pathdir)
|
52
|
+
raise "Dir #{pathdir} no found." unless Dir.exist?(pathdir)
|
53
|
+
|
54
|
+
tar = Dir.glob("#{Sgpg::WORKDIR}/*.tar")
|
55
|
+
raise 'No archive found.' unless tar.length >= 1
|
56
|
+
|
57
|
+
mv(tar, pathdir)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def import_secret(keys)
|
63
|
+
keys.each { |k| system('gpg', '-a', '--import', k) if k.match(/secret/) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def import_public(keys)
|
67
|
+
keys.each { |k| system('gpg', '-a', '--import', k) if k.match(/public/) }
|
68
|
+
end
|
69
|
+
|
70
|
+
# suffix should be 'master' or 'lesser' (keys without privilege)
|
71
|
+
def create_tar(suffix = 'master')
|
72
|
+
if suffix == 'master'
|
73
|
+
system("tar -cf #{@name}-#{@date}-#{suffix}-keys.tar *.key revocation.cert")
|
74
|
+
else
|
75
|
+
system("tar -cf #{@name}-#{@date}-#{suffix}-keys.tar *.key")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def mv(tar, pathdir)
|
80
|
+
puts "Moving archive at #{pathdir}..."
|
81
|
+
case Helper.auth?
|
82
|
+
when :root
|
83
|
+
tar.each { |f| FileUtils.mv(f, "#{pathdir}/#{f}") }
|
84
|
+
when :sudo
|
85
|
+
tar.each { |f| system('sudo', 'mv', f, "#{pathdir}/") }
|
86
|
+
when :doas
|
87
|
+
tar.each { |f| system('doas', 'mv', f, "#{pathdir}/") }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/cryptsetup.rb
|
4
|
+
|
5
|
+
module Sgpg
|
6
|
+
# Manipule program cryptsetup
|
7
|
+
class Cryptsetup
|
8
|
+
class InvalidDisk < StandardError; end
|
9
|
+
|
10
|
+
def initialize(disk)
|
11
|
+
raise "no disk #{disk} specified..." unless disk
|
12
|
+
|
13
|
+
@disk = disk
|
14
|
+
@mapname = 'sgpg'
|
15
|
+
end
|
16
|
+
|
17
|
+
# tails linux make persistent volume on second partiton 'disk_name'2
|
18
|
+
def open
|
19
|
+
check_disk
|
20
|
+
|
21
|
+
case Helper.auth?
|
22
|
+
when :root
|
23
|
+
open_with
|
24
|
+
when :doas
|
25
|
+
open_with 'doas'
|
26
|
+
when :sudo
|
27
|
+
open_with 'sudo'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def close
|
32
|
+
case Helper.auth?
|
33
|
+
when :root
|
34
|
+
close_with
|
35
|
+
when :doas
|
36
|
+
close_with 'doas'
|
37
|
+
when :sudo
|
38
|
+
close_with 'sudo'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def check_disk
|
45
|
+
raise InvalidDisk, "Disk #{@disk} not exist or not plugged." unless
|
46
|
+
File.exist?(@disk)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def open_with(prefix = '')
|
52
|
+
if prefix
|
53
|
+
puts "openning disk #{@disk} with #{prefix}..."
|
54
|
+
else
|
55
|
+
puts "openning disk #{@disk}..."
|
56
|
+
end
|
57
|
+
|
58
|
+
raise "unable to open #{@disk} #{prefix}" unless
|
59
|
+
system(prefix, 'cryptsetup', 'open', '--type', 'luks', @disk, @mapname)
|
60
|
+
end
|
61
|
+
|
62
|
+
def close_with(prefix = '')
|
63
|
+
puts "closing disk #{@disk}..."
|
64
|
+
|
65
|
+
raise "closing disk #{@disk} failed" unless
|
66
|
+
system(prefix, 'cryptsetup', 'close', @mapname)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/sgpg/gpg.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sgpg
|
4
|
+
# Interact with GnuPG from unix
|
5
|
+
class Gpg
|
6
|
+
# Code here
|
7
|
+
def initialize(keyname)
|
8
|
+
@keyname = keyname
|
9
|
+
puts "using key #{@keyname}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete_keys
|
13
|
+
return unless system('gpg', '-k', @keyname)
|
14
|
+
|
15
|
+
puts "Found older key name #{@keyname}, need to be deleted to import new..."
|
16
|
+
system('gpg', '--delete-secret-keys', @keyname)
|
17
|
+
system('gpg', '--delete-keys', @keyname)
|
18
|
+
end
|
19
|
+
|
20
|
+
def edit_key
|
21
|
+
raise "No key #{@keyname} found." unless system('gpg', '-k', @keyname)
|
22
|
+
|
23
|
+
system('gpg', '--edit-key', @keyname)
|
24
|
+
end
|
25
|
+
|
26
|
+
def export_secret_keys(pathdir)
|
27
|
+
raise "No dir #{pathdir} exist" unless File.exist?(pathdir)
|
28
|
+
|
29
|
+
output = "#{pathdir}/#{@keyname}"
|
30
|
+
system("gpg --armor --export-secret-keys #{@keyname} > #{output}-secret.key")
|
31
|
+
system("gpg --armor --export #{@keyname} > #{output}-public.key")
|
32
|
+
end
|
33
|
+
|
34
|
+
def export_subkey(pathdir)
|
35
|
+
raise "No dir #{pathdir} exist" unless File.exist?(pathdir)
|
36
|
+
|
37
|
+
system("gpg --export-secret-subkeys #{@keyname} > #{pathdir}/subkeys")
|
38
|
+
end
|
39
|
+
|
40
|
+
def import_lesser_keys
|
41
|
+
keypath = "#{Sgpg::WORKDIR}/subkeys"
|
42
|
+
raise "No key #{keypath} exist" unless File.exist?(keypath)
|
43
|
+
|
44
|
+
system('gpg', '--import', keypath)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/sgpg/helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/helper.rb
|
4
|
+
|
5
|
+
module Sgpg
|
6
|
+
# Reusable functions for the program
|
7
|
+
module Helper
|
8
|
+
def self.auth?
|
9
|
+
return :root if Process.uid == '0'
|
10
|
+
return :doas if File.exist?('/bin/doas') || File.exist?('/sbin/doas')
|
11
|
+
return :sudo if File.exist?('/bin/sudo') || File.exist?('/sbin/sudo')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/sgpg/mount.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/mount.rb
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
module Sgpg
|
8
|
+
# (un)mount a device to a mountpoint
|
9
|
+
class Mount
|
10
|
+
# Argument 'disk' = full path of the disk.
|
11
|
+
# e.g: /dev/mapper/sgpg for cryptsetup (See Sgpg::Cryptsetup) of just /dev/sdX
|
12
|
+
def initialize(disk)
|
13
|
+
@user = ENV['USER'] || 'root'
|
14
|
+
@disk = disk
|
15
|
+
end
|
16
|
+
|
17
|
+
def open
|
18
|
+
case Helper.auth?
|
19
|
+
when :root
|
20
|
+
open_with
|
21
|
+
when :doas
|
22
|
+
open_with 'doas'
|
23
|
+
when :sudo
|
24
|
+
open_with 'sudo'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def close
|
29
|
+
case Helper.auth?
|
30
|
+
when :root
|
31
|
+
close_with
|
32
|
+
when :doas
|
33
|
+
close_with 'doas'
|
34
|
+
when :sudo
|
35
|
+
close_with 'sudo'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def open_with(prefix = '')
|
42
|
+
prefix == '' ? create_with_ruby : create_with_system(prefix)
|
43
|
+
|
44
|
+
raise "Unable to mount #{@disk}" unless
|
45
|
+
system(prefix, 'mount', '-t', 'ext4', @disk, Sgpg::MOUNTPOINT)
|
46
|
+
end
|
47
|
+
|
48
|
+
def close_with(prefix = '')
|
49
|
+
raise "Unable to umount #{@disk}" unless
|
50
|
+
system(prefix, 'umount', Sgpg::MOUNTPOINT)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def create_wiht_ruby
|
56
|
+
FileUtils.mkdir_p Sgpg::MOUNTPOINT
|
57
|
+
FileUtils.chown @user, @user, Sgpg::MOUNTPOINT, verbose: true
|
58
|
+
FileUtils.chmod 0644, Sgpg::MOUNTPOINT, verbose: true
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_with_system(prefix)
|
62
|
+
system(prefix, 'mkdir', '-p', Sgpg::MOUNTPOINT)
|
63
|
+
system(prefix, 'chown', "#{@user}:#{@user}", Sgpg::MOUNTPOINT)
|
64
|
+
system(prefix, 'chmod', '0644', Sgpg::MOUNTPOINT)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/sgpg/option.rb
ADDED
data/lib/sgpg/version.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Sgpg
|
6
|
+
# Manage the configuration file
|
7
|
+
class YamlConfig
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@file_dir = "#{ENV['HOME']}/.config/sgpg"
|
12
|
+
@filename = 'config.yml'
|
13
|
+
@full_path = "#{@file_dir}/#{@filename}"
|
14
|
+
@config = {
|
15
|
+
disk: '',
|
16
|
+
keyname: '',
|
17
|
+
crypted: false
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def load
|
22
|
+
if !Dir.exist?(@file_dir) || !File.exist?(@full_path)
|
23
|
+
create_dir
|
24
|
+
write_config unless File.exist?(@full_path)
|
25
|
+
else
|
26
|
+
loading
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"Using disk >> #{@config[:disk]}, key >> #{@config[:keyname]}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def save(opts)
|
35
|
+
puts "saving options #{opts}"
|
36
|
+
@config[:disk] = opts[:disk] if opts[:disk]
|
37
|
+
@config[:keyname] = opts[:keyname] if opts[:keyname]
|
38
|
+
@config[:crypted] = opts[:crypted] if opts[:crypted]
|
39
|
+
puts "current #{config}"
|
40
|
+
write_config
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def loading
|
46
|
+
puts "Loading #{@full_path}..."
|
47
|
+
@config = YAML.load_file(@full_path)
|
48
|
+
rescue Psych::SyntaxError => e
|
49
|
+
puts "YAML syntax error: #{e.message}"
|
50
|
+
rescue Errno::ENOENT
|
51
|
+
puts "File not found: #{@full_path}"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def create_dir
|
57
|
+
return if Dir.exist? @file_dir
|
58
|
+
|
59
|
+
puts "Creating #{@file_dir}..."
|
60
|
+
Dir.mkdir @file_dir
|
61
|
+
end
|
62
|
+
|
63
|
+
def write_config
|
64
|
+
in_yaml = YAML.dump(@config)
|
65
|
+
File.write(@full_path, in_yaml)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/sgpg.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'sgpg/version'
|
4
|
+
require_relative 'sgpg/option'
|
5
|
+
require_relative 'sgpg/yaml_config'
|
6
|
+
require_relative 'sgpg/helper'
|
7
|
+
require_relative 'sgpg/cryptsetup'
|
8
|
+
require_relative 'sgpg/mount'
|
9
|
+
require_relative 'sgpg/gpg'
|
10
|
+
require_relative 'sgpg/archive'
|
11
|
+
|
12
|
+
# Manage your gpg key easyly
|
13
|
+
module Sgpg
|
14
|
+
def self.open(disk, is_crypted = false)
|
15
|
+
return if Dir.glob("#{Sgpg::MOUNTPOINT}/*").length >= 1
|
16
|
+
|
17
|
+
puts "Open device #{disk}..."
|
18
|
+
if is_crypted
|
19
|
+
Cryptsetup.new(disk).open
|
20
|
+
Mount.new('/dev/mapper/sgpg').open
|
21
|
+
else
|
22
|
+
Mount.new(disk).open
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.close(disk, is_crypted = false)
|
27
|
+
if is_crypted
|
28
|
+
Mount.new('/dev/mapper/sgpg').close
|
29
|
+
Cryptsetup.new(disk).close
|
30
|
+
else
|
31
|
+
Mount.new(disk).close
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.list_keys(keyname)
|
36
|
+
keys = Dir.glob("#{Sgpg::MOUNTPOINT}/Persistent/#{keyname}*.tar")
|
37
|
+
puts "Listing keys for #{keyname}..."
|
38
|
+
keys = Dir.glob("#{Sgpg::MOUNTPOINT}/Persistent/*.tar") if keys == [] || keys == ''
|
39
|
+
puts keys
|
40
|
+
end
|
41
|
+
|
42
|
+
# argument 'suffix' = master or lesser
|
43
|
+
def self.last_key(opts, suffix = 'master')
|
44
|
+
Sgpg.open(opts[:disk], opts[:crypted])
|
45
|
+
|
46
|
+
keys = Dir.glob("#{Sgpg::KEYDIR}/#{opts[:keyname]}*#{suffix}*.tar").sort
|
47
|
+
raise 'No keys found' unless keys.length >= 1
|
48
|
+
|
49
|
+
keys[0]
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.clear_keys
|
53
|
+
return unless Dir.glob("#{Sgpg::WORKDIR}/*.key").length >= 1
|
54
|
+
|
55
|
+
print "Clearing keys located at #{Sgpg::WORKDIR}? (y/n) "
|
56
|
+
choice = gets.chomp
|
57
|
+
return unless choice.match(/^y|^Y/)
|
58
|
+
|
59
|
+
puts "Clearing #{Sgpg::WORKDIR}..."
|
60
|
+
system("shred -u #{Sgpg::WORKDIR}/*.key")
|
61
|
+
end
|
62
|
+
|
63
|
+
# Main logic here
|
64
|
+
module Main
|
65
|
+
# import and edit a gpg key from an archive (opts[:keypath])
|
66
|
+
def self.edit_key(opts)
|
67
|
+
Sgpg.open(opts[:disk], opts[:crypted])
|
68
|
+
archive = Archive.new(opts[:keypath], opts[:keyname])
|
69
|
+
archive.extract
|
70
|
+
archive.import
|
71
|
+
Sgpg.clear_keys
|
72
|
+
end
|
73
|
+
|
74
|
+
# export your real keys and create an archive (tar)
|
75
|
+
def self.export_secret(opts)
|
76
|
+
archive = Archive.new(opts[:keypath], opts[:keyname])
|
77
|
+
archive.create_master_tar
|
78
|
+
archive.move(Sgpg::KEYDIR)
|
79
|
+
Sgpg.clear_keys
|
80
|
+
end
|
81
|
+
|
82
|
+
# create an unpriviliged gpg key (no change can be made)
|
83
|
+
def self.lesser_keys(opts)
|
84
|
+
archive = Archive.new(opts[:keypath], opts[:keyname])
|
85
|
+
archive.create_lesser_tar
|
86
|
+
archive.move(Sgpg::KEYDIR)
|
87
|
+
Sgpg.clear_keys
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/sgpg.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/sgpg/version'
|
4
|
+
|
5
|
+
# https://guides.rubygems.org/specification-reference/
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'sgpg'
|
8
|
+
s.summary = 'Short gpg, tool for manage your gpg key (backup tarball, unprivileged keys, etc...)'
|
9
|
+
s.version = Sgpg::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
|
12
|
+
s.description = <<-DESCRIPTION
|
13
|
+
Short gpg, tool for manage your gpg key (backup tarball, unprivileged keys, etc...)
|
14
|
+
DESCRIPTION
|
15
|
+
|
16
|
+
s.email = 'szorfein@protonmail.com'
|
17
|
+
s.homepage = 'https://github.com/szorfein/sgpg'
|
18
|
+
s.license = 'GPL-3'
|
19
|
+
s.author = 'szorfein'
|
20
|
+
|
21
|
+
s.metadata = {
|
22
|
+
'bug_tracker_uri' => 'https://github.com/szorfein/sgpg/issues',
|
23
|
+
'changelog_uri' => 'https://github.com/szorfein/sgpg/blob/main/CHANGELOG.md',
|
24
|
+
'source_code_uri' => 'https://github.com/szorfein/sgpg',
|
25
|
+
'wiki_uri' => 'https://github.com/szorfein/sgpg/wiki',
|
26
|
+
'funding_uri' => 'https://patreon.com/szorfein'
|
27
|
+
}
|
28
|
+
|
29
|
+
s.files = Dir.glob('{lib,bin}/**/*', File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
30
|
+
s.files += %w[CHANGELOG.md LICENSE README.md]
|
31
|
+
s.files += %w[sgpg.gemspec]
|
32
|
+
|
33
|
+
s.bindir = 'bin'
|
34
|
+
s.executables << 'sgpg'
|
35
|
+
s.extra_rdoc_files = %w[README.md]
|
36
|
+
|
37
|
+
# s.cert_chain = %w[certs/szorfein.pem]
|
38
|
+
# s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
|
39
|
+
|
40
|
+
s.required_ruby_version = '>=2.6'
|
41
|
+
s.requirements << 'gpg'
|
42
|
+
s.requirements << 'cryptsetup'
|
43
|
+
s.requirements << 'shred'
|
44
|
+
s.requirements << 'tar'
|
45
|
+
end
|
data.tar.gz.sig
ADDED
Binary file
|