sgpg 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|