sgpg 0.1.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19adec4c32f7a7b0b3f373eb969cb1f94f11b2018c0560fb87fe08273b14589e
4
- data.tar.gz: 6df240ec47463524f39b8d771bce155f35ce32ccc135b6fdd9525c62c76afc08
3
+ metadata.gz: c2df301c36de68352a30454b4024038d9e7efa8816f6db7e332f250d40fdc607
4
+ data.tar.gz: 38f42188aec8bb77a2ab31f84d446427c1112c7a0a2cb829cafc6839ad71cf5a
5
5
  SHA512:
6
- metadata.gz: '095ce5720c3bd485cfc290025c83d9e906ce8fab073a850ad592e63216dcb6b211326904ea72e030324ebebbda87b86292350556c2f952d54d171ab086c86ebb'
7
- data.tar.gz: 7e7632fced693a9f7e162184d91e525b735d5650010bc9a00f5a97b730cdf1af9a5adfac566078b00d9cf27c438d4e7913f71d6c0edf54935622e7379f3ed1b1
6
+ metadata.gz: cc7c9e9530164fbab117cab1b255b59c3d20cb26b6996967f549041eabe4dc6a8c638c2ebea953ed58dcbfd540403d7fe17d0295499d7dc1f78047ddfa4c0ce6
7
+ data.tar.gz: 59dd16d8b4bb1327f683a887377c4ad35d63c6a0dbec57156b19766ccf6470624d18ca676aafb9f75351ff003ae0a153ea84508c70de4a6a4336ba9b618b8f1d
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ ## 1.0.0 - Oct. 2025
2
+
3
+ - New CLI options, `--encrypt`, `--no-encrypt`, `--export-pass`, `--import-pass`.
4
+ - Update the destination to `/mnt/sgpg/`. Use `/mnt/sgpg/Persistent` only if the directory exist (compatible with [Tail Linux](https://tails.net/doc/persistent_storage/index.en.html)).
5
+ - Create a directory `/mnt/sgpg/<key-name>/` for each key.
6
+ - Can save (export/import) passwords from [pass](https://www.passwordstore.org/) by incremental save
7
+
8
+ ### Bug fixes
9
+
10
+ - Correct permission when move archive, we can't list keys with wrong permissions.
11
+ - Don't check for `*.cert` when create archives, only `*.key`
12
+ - Correct the last element returned from array for `--last-lesser` or `--last-master`
13
+
14
+ ### Manual intervention
15
+
16
+ For those using a previous version, they need to manually import the last master key and re export keys:
17
+
18
+ sgpg --path-key /mnt/sgpg/<keymaster>.tar --edit-key
19
+ sgpg --export
20
+
21
+ ## 0.1.0, release 09/10/24
22
+
23
+ - New `.github/workflow` to publish package on GitHub.
24
+ - New command line options
25
+ - `--disk-encrypt` if need to use `cryptsetup` or not.
26
+ - `--export` create master and lesser archive.
27
+
1
28
  ## 0.0.1, release 07/27/24
2
- * Initial push, code freeying !
3
- "
29
+
30
+ - Initial push, code release!
data/README.md CHANGED
@@ -1,31 +1,43 @@
1
- # Sgpg
2
- Short gpg, tool for manage your gpg key (backup tarball, unprivileged keys, etc)
1
+ # sGPG
3
2
 
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 :).
3
+ <div align="center">
4
+ <br/>
5
+
6
+ [![Gem Version](https://badge.fury.io/rb/sgpg.svg)](https://badge.fury.io/rb/sgpg)
7
+
8
+ </div>
9
+
10
+ Short GnuPG, tool for manage your GPG key (backup tarball, unprivileged keys, etc)
8
11
 
9
- So with this tool, 'i,you,we' should use no more than 3 commands max instead of 50...
12
+ Followed my [post](https://szorfein.github.io/gpg/build-secure-gpg-key/) to
13
+ create a secure GnuPG key, I need to update my keys all the 6 month on each PC.
14
+ It's a very annoying task without scripts so I've develop this tool in
15
+ Ruby to gain in time and mental sanity :).
10
16
 
11
- You always need to create a gpg key as well
17
+ To start, you always need to owm/create a GnuPG key as well.
12
18
 
13
19
  gpg --expert --full-generate-key
14
20
 
15
- ## Install sgpg locally
21
+ ## Install sGPG locally
22
+
23
+ gem install --user-install sgpg
16
24
 
17
- gem install sgpg
25
+ You also need to install some dependencies:
18
26
 
19
- You also need to install dependencies: tar, cryptsetup, shred and gpg.
27
+ - Tar
28
+ - Cryptsetup (if you want to encrypt/decrypt the disk)
29
+ - Shred (to remove the master key efficiently)
30
+ - And GnuPG of course.
20
31
 
21
- ## Configure
22
- The config is located at ~/.config/sgpg/config.yml. You can use the command line with `--save`:
32
+ ## Optional configuration
23
33
 
24
- sgpg --disk /dev/sdc2 --disk-encrypt --key szorfein@protonmail.com --save
34
+ The config file is located at `~/.config/sgpg/config.yml`. You can use the command line with `--save`:
35
+
36
+ sgpg --disk /dev/sdc2 --encrypt --key szorfein@protonmail.com --save
25
37
 
26
38
  You can register the disk/by-id or disk/by-uuid if you prefer.
27
39
 
28
- sgpg --disk /dev/disk/by-id/wmn-0xXXXX-part2 --disk-encrypt --save
40
+ sgpg --disk /dev/disk/by-id/wmn-0xXXXX-part2 --encrypt --save
29
41
 
30
42
  ## Usage
31
43
 
@@ -34,17 +46,37 @@ You can register the disk/by-id or disk/by-uuid if you prefer.
34
46
  When subkeys expire:
35
47
 
36
48
  sgpg --last-master --edit-key # update expired keys, change password, etc...
37
- sgpg --export
49
+ sgpg --export # create master and lesser archive
38
50
  sgpg --close # unmount and close disk
39
51
 
40
- Import the last unpriviliged key (laptop and other)
52
+ Import the last unprivileged key (laptop and other)
41
53
 
42
54
  sgpg --last-lesser --edit-key # trust (555)
43
55
  sgpg --close # unmount and close disk
44
56
 
57
+ Manually choose an archive
58
+
59
+ sgpg --open # mount disk
60
+ sgpg --path-key /mnt/sgpg/Persistent/archive.tar --edit-key
61
+
62
+ Export your passwords created with the [pass](https://www.passwordstore.org/) tool:
63
+
64
+ sgpg --open # mount disk
65
+ sgpg --key szorfein@protonmail.com --export-pass
66
+ sgpg --close
67
+
68
+ ## About
69
+
70
+ About GnuPG security in brief and what's this tool help you to manage:
71
+
72
+ - You don't need a passphrase to protect your master key (if your follow all advice)
73
+ - Never store your master key on your computer, store it on an encrypted device.
74
+ - Always use an unprivileged key on your working machine.
75
+ - Create short live keys for Sign, Encrypt and Auth, maximum 6 month (less is better).
76
+ - When importing your master keys, (try to) be offline.
77
+
45
78
  ## Gem push
46
79
 
47
80
  gem login
48
81
  gem build sgpg.gemspec
49
82
  gem push sgpg-0.0.1.gem
50
-
data/bin/sgpg CHANGED
@@ -16,11 +16,15 @@ OptionParser.new do |opts|
16
16
  options[:disk] = dev
17
17
  end
18
18
 
19
- opts.on('--disk-encrypt', 'If we need to use cryptsetup to open the disk.') do
19
+ opts.on('--encrypt', 'If we need to use cryptsetup to open the disk.') do
20
20
  options[:crypted] = true
21
21
  end
22
22
 
23
- opts.on('-k', '--key NAME', 'Use the key name, default use ENV["USER"]') do |name|
23
+ opts.on('--no-encrypt', 'Disable disk encryption.') do
24
+ options[:crypted] = false
25
+ end
26
+
27
+ opts.on('-k', '--key NAME', 'Specify the GPG key to use') do |name|
24
28
  options[:keyname] = name
25
29
  end
26
30
 
@@ -32,11 +36,7 @@ OptionParser.new do |opts|
32
36
  Sgpg.list_keys(options[:keyname])
33
37
  end
34
38
 
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|
39
+ opts.on('-p', '--path-key PATH', 'Use archive PATH') do |path|
40
40
  raise "path #{path} didn't found" unless File.exist? path
41
41
 
42
42
  options[:keypath] = path
@@ -46,15 +46,19 @@ OptionParser.new do |opts|
46
46
  options[:keypath] = Sgpg.last_key(options, 'master')
47
47
  end
48
48
 
49
- opts.on('--last-lesser', 'Use the last archive lesser (unpriviliged)') do
49
+ opts.on('--last-lesser', 'Use the last archive lesser (secure key with no privileges)') do
50
50
  options[:keypath] = Sgpg.last_key(options, 'lesser')
51
51
  end
52
52
 
53
+ opts.on('-o', '--open', "Open and mount device disk at #{Sgpg::MOUNTPOINT}.") do
54
+ Sgpg.open(options[:disk], options[:crypted])
55
+ end
56
+
53
57
  opts.on('-c', '--close', 'Unmount and close disk device.') do
54
58
  Sgpg.close(options[:disk], options[:crypted])
55
59
  end
56
60
 
57
- opts.on('-s', '--save', 'Save current optargs in the config file') do
61
+ opts.on('-s', '--save', 'Save current cli options in the config file') do
58
62
  config_file.save(options)
59
63
  end
60
64
 
@@ -62,11 +66,20 @@ OptionParser.new do |opts|
62
66
  Sgpg::Main.export_secret(options)
63
67
  Sgpg::Main.lesser_keys(options)
64
68
  end
69
+
70
+ opts.on('--export-pass', 'Export your password-store from pass.') do
71
+ Sgpg::Main.incremental_export(options[:keyname])
72
+ end
73
+
74
+ opts.on('--import-pass', 'Import your password-store from pass.') do
75
+ Sgpg::Main.incremental_import(options[:keyname])
76
+ end
77
+
78
+ opts.on('-v', '--version', 'Display the current version.') do
79
+ puts "sgpg v#{Sgpg::VERSION}"
80
+ exit
81
+ end
65
82
  end.parse!
66
83
 
67
84
  raise 'no disk to use' if !options[:disk] || options[:disk] == ''
68
85
  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 CHANGED
@@ -6,14 +6,16 @@ module Sgpg
6
6
  # Interact with program tar from unix
7
7
  class Archive
8
8
  # Code here
9
- def initialize(key, name = ENV['USER'])
9
+ def initialize(key, name = nil)
10
+ raise ArgumentError, "No #{name}..." unless name
11
+
10
12
  @key = key || ''
11
13
  @name = name
12
14
  @date = Time.now.strftime('%Y-%m-%d')
13
15
  puts "create key #{@name}-#{@date}-master.tar"
14
16
  FileUtils.mkdir_p Sgpg::WORKDIR
15
17
  @gpg = Gpg.new(@name)
16
- # make it compatabble with Tails Linux
18
+ # Make it compatible with Tails Linux
17
19
  end
18
20
 
19
21
  def create_master_tar
@@ -57,20 +59,42 @@ module Sgpg
57
59
  mv(tar, pathdir)
58
60
  end
59
61
 
62
+ # Tail Linux create an encrypted partition with a directory named Persistent
63
+ def move_to_disk
64
+ dest = Helper.search_dest
65
+ final_dest = "#{dest}/#{@name}" # we add the key name
66
+
67
+ Helper.mkdir(final_dest)
68
+ Helper.chmod('0777', final_dest)
69
+
70
+ tar = Dir.glob("#{Sgpg::WORKDIR}/*.tar")
71
+ raise 'No archive found.' unless tar.length >= 1
72
+
73
+ mv(tar, final_dest)
74
+ end
75
+
60
76
  private
61
77
 
62
78
  def import_secret(keys)
63
- keys.each { |k| system('gpg', '-a', '--import', k) if k.match(/secret/) }
79
+ keys.each do |k|
80
+ puts "importing secret #{k}..."
81
+ system('gpg', '-a', '--yes', '--import', k) if k.match?(/secret/)
82
+ end
64
83
  end
65
84
 
66
85
  def import_public(keys)
67
- keys.each { |k| system('gpg', '-a', '--import', k) if k.match(/public/) }
86
+ keys.each do |k|
87
+ puts "importing public #{k}..."
88
+ system('gpg', '-a', '--yes', '--import', k) if k.match?(/public/)
89
+ end
68
90
  end
69
91
 
70
- # suffix should be 'master' or 'lesser' (keys without privilege)
92
+ # Suffix should be 'master' or 'lesser' (keys without privilege)
71
93
  def create_tar(suffix = 'master')
72
94
  if suffix == 'master'
73
- system("tar -cf #{@name}-#{@date}-#{suffix}-keys.tar *.key revocation.cert")
95
+ # In theory, you can create the certificate any time as you have the master key
96
+ #system("tar -cf #{@name}-#{@date}-#{suffix}-keys.tar *.key *.cert")
97
+ system("tar -cf #{@name}-#{@date}-#{suffix}-keys.tar *.key")
74
98
  else
75
99
  system("tar -cf #{@name}-#{@date}-#{suffix}-keys.tar *.key")
76
100
  end
@@ -78,13 +102,10 @@ module Sgpg
78
102
 
79
103
  def mv(tar, pathdir)
80
104
  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}/") }
105
+ tar.each do |f|
106
+ file = File.basename(f)
107
+ Helper.mv(f, pathdir)
108
+ Helper.chmod('0644', "#{pathdir}/#{file}")
88
109
  end
89
110
  end
90
111
  end
@@ -3,18 +3,18 @@
3
3
  # lib/cryptsetup.rb
4
4
 
5
5
  module Sgpg
6
- # Manipule program cryptsetup
6
+ # Control program cryptsetup
7
7
  class Cryptsetup
8
8
  class InvalidDisk < StandardError; end
9
9
 
10
10
  def initialize(disk)
11
- raise "no disk #{disk} specified..." unless disk
11
+ raise "No disk #{disk} specified..." unless disk
12
12
 
13
13
  @disk = disk
14
14
  @mapname = 'sgpg'
15
15
  end
16
16
 
17
- # tails linux make persistent volume on second partiton 'disk_name'2
17
+ # Tails Linux make persistent volume on second partition 'disk_name'2
18
18
  def open
19
19
  check_disk
20
20
 
@@ -48,21 +48,21 @@ module Sgpg
48
48
 
49
49
  private
50
50
 
51
- def open_with(prefix = '')
51
+ def open_with(prefix = nil)
52
52
  if prefix
53
- puts "openning disk #{@disk} with #{prefix}..."
53
+ puts "Opening disk #{@disk} with #{prefix}..."
54
54
  else
55
- puts "openning disk #{@disk}..."
55
+ puts "Opening disk #{@disk}..."
56
56
  end
57
57
 
58
- raise "unable to open #{@disk} #{prefix}" unless
58
+ raise "Unable to open #{@disk} #{prefix}" unless
59
59
  system(prefix, 'cryptsetup', 'open', '--type', 'luks', @disk, @mapname)
60
60
  end
61
61
 
62
- def close_with(prefix = '')
63
- puts "closing disk #{@disk}..."
62
+ def close_with(prefix = nil)
63
+ puts "Closing disk #{@disk}..."
64
64
 
65
- raise "closing disk #{@disk} failed" unless
65
+ raise "Closing disk #{@disk} failed" unless
66
66
  system(prefix, 'cryptsetup', 'close', @mapname)
67
67
  end
68
68
  end
data/lib/sgpg/helper.rb CHANGED
@@ -10,5 +10,33 @@ module Sgpg
10
10
  return :doas if File.exist?('/bin/doas') || File.exist?('/sbin/doas')
11
11
  return :sudo if File.exist?('/bin/sudo') || File.exist?('/sbin/sudo')
12
12
  end
13
+
14
+ def self.mv(src, dest)
15
+ case auth?
16
+ when :root then FileUtils.mv(src, dest)
17
+ when :sudo then system('sudo', 'mv', src, dest)
18
+ when :doas then system('doas', 'mv', src, dest)
19
+ end
20
+ end
21
+
22
+ def self.mkdir(path_dir)
23
+ case auth?
24
+ when :root then FileUtils.mkdir(path_dir)
25
+ when :sudo then system('sudo', 'mkdir', '-p', path_dir)
26
+ when :doas then system('doas', 'mkdir', '-p', path_dir)
27
+ end
28
+ end
29
+
30
+ def self.search_dest
31
+ Dir.exist?("#{Sgpg::KEYDIR}/Persistent") ? "#{Sgpg::KEYDIR}/Persistent" : Sgpg::KEYDIR
32
+ end
33
+
34
+ def self.chmod(perm, file_path)
35
+ case auth?
36
+ when :root then FileUtils.chmod perm, file_path, verbose: true
37
+ when :sudo then system('sudo', 'chmod', perm, file_path)
38
+ when :doas then system('doas', 'chmod', perm, file_path)
39
+ end
40
+ end
13
41
  end
14
42
  end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'pathname'
5
+ require 'time'
6
+
7
+ # Exemple: https://peerdh.com/blogs/programming-insights/creating-a-ruby-gem-for-incremental-backup-strategies
8
+ module Sgpg
9
+ # Incremental save
10
+ class Incremental
11
+ attr_accessor :source, :destination, :last_backup_time
12
+
13
+ def initialize(source, destination)
14
+ #raise ArgumentError, 'No dest, missed to mount stockage disk?' unless Dir.exist?(destination)
15
+
16
+ @source = source
17
+ @destination = destination
18
+ @last_backup_time = read_last_backup_time
19
+ @need_full_backup = check_time(@last_backup_time)
20
+ end
21
+
22
+ def check_time(time)
23
+ return false unless time
24
+
25
+ t = time
26
+ t.is_a?(Time)
27
+ end
28
+
29
+ def perform_backup
30
+ files = @last_backup_time ? files_to_backup : full_backup
31
+ puts "Incremental backup #{@need_full_backup}"
32
+
33
+ copy_directory_structure(files)
34
+ copy_files(files)
35
+ write_backup_time
36
+ end
37
+
38
+ private
39
+
40
+ def write_backup_time
41
+ return unless @destination.match?(/sgpg/)
42
+
43
+ pn = Pathname.new(@destination)
44
+ dest = "#{pn.dirname}/last-backup"
45
+ File.write(dest, Time.now)
46
+
47
+ @last_backup_time = Time.now
48
+ puts "last backup #{@last_backup_time}"
49
+ end
50
+
51
+ def read_last_backup_time
52
+ return unless @destination.match?(/sgpg/)
53
+
54
+ pn = Pathname.new(@destination)
55
+ dest = "#{pn.dirname}/last-backup"
56
+ File.exist?(dest) ? Time.parse(File.read(dest)) : nil
57
+ end
58
+
59
+ def full_backup
60
+ Dir.glob(File.join(@source, '**', '*')).select do |file|
61
+ File.file?(file)
62
+ end
63
+ end
64
+
65
+ def files_to_backup
66
+ Dir.glob(File.join(@source, '**', '*')).select do |file|
67
+ File.file?(file) && File.mtime(file) > @last_backup_time
68
+ end
69
+ end
70
+
71
+ # Skip files, only copy directories
72
+ def copy_directory_structure(files)
73
+ files.each do |file|
74
+ new_dir = file.sub(@source, @destination)
75
+ pn = Pathname.new(new_dir)
76
+ puts "add dir #{pn.dirname}"
77
+ FileUtils.mkdir_p(pn.dirname)
78
+ end
79
+ end
80
+
81
+ def copy_files(files)
82
+ files.each do |file|
83
+ #destination_path = File.join(@destination, File.basename(file))
84
+ destination_path = file.sub(@source, @destination)
85
+ puts "cpy #{file} to dest #{destination_path}"
86
+ FileUtils.cp(file, destination_path, preserve: true)
87
+ end
88
+ end
89
+ end
90
+ end
data/lib/sgpg/mount.rb CHANGED
@@ -38,30 +38,30 @@ module Sgpg
38
38
 
39
39
  protected
40
40
 
41
- def open_with(prefix = '')
42
- prefix == '' ? create_with_ruby : create_with_system(prefix)
41
+ def open_with(prefix = nil)
42
+ prefix ? create_with_ruby : create_with_system(prefix)
43
43
 
44
44
  raise "Unable to mount #{@disk}" unless
45
45
  system(prefix, 'mount', '-t', 'ext4', @disk, Sgpg::MOUNTPOINT)
46
46
  end
47
47
 
48
- def close_with(prefix = '')
48
+ def close_with(prefix = nil)
49
49
  raise "Unable to umount #{@disk}" unless
50
50
  system(prefix, 'umount', Sgpg::MOUNTPOINT)
51
51
  end
52
52
 
53
53
  private
54
54
 
55
- def create_wiht_ruby
55
+ def create_with_ruby
56
56
  FileUtils.mkdir_p Sgpg::MOUNTPOINT
57
57
  FileUtils.chown @user, @user, Sgpg::MOUNTPOINT, verbose: true
58
- FileUtils.chmod 0644, Sgpg::MOUNTPOINT, verbose: true
58
+ FileUtils.chmod 0755, Sgpg::MOUNTPOINT, verbose: true
59
59
  end
60
60
 
61
61
  def create_with_system(prefix)
62
62
  system(prefix, 'mkdir', '-p', Sgpg::MOUNTPOINT)
63
63
  system(prefix, 'chown', "#{@user}:#{@user}", Sgpg::MOUNTPOINT)
64
- system(prefix, 'chmod', '0644', Sgpg::MOUNTPOINT)
64
+ system(prefix, 'chmod', '0755', Sgpg::MOUNTPOINT)
65
65
  end
66
66
  end
67
67
  end
data/lib/sgpg/option.rb CHANGED
@@ -4,6 +4,6 @@
4
4
 
5
5
  module Sgpg
6
6
  MOUNTPOINT = '/mnt/sgpg' # Better permission than /media/sgpg
7
- KEYDIR = "#{MOUNTPOINT}/Persistent" # Tails Linux Comptatible
7
+ KEYDIR = "#{MOUNTPOINT}"
8
8
  WORKDIR = '/tmp/sgpg'
9
9
  end
data/lib/sgpg/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sgpg
4
- VERSION = '0.1.0'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -8,12 +8,12 @@ module Sgpg
8
8
  attr_reader :config
9
9
 
10
10
  def initialize
11
- @file_dir = "#{ENV['HOME']}/.config/sgpg"
11
+ @file_dir = ENV['XDG_CONFIG_HOME'] ? "#{ENV['XDG_CONFIG_HOME']}/sgpg" : "#{ENV['HOME']}/.config/sgpg"
12
12
  @filename = 'config.yml'
13
13
  @full_path = "#{@file_dir}/#{@filename}"
14
14
  @config = {
15
- disk: '',
16
- keyname: '',
15
+ disk: nil,
16
+ keyname: nil,
17
17
  crypted: false
18
18
  }
19
19
  end
data/lib/sgpg.rb CHANGED
@@ -8,10 +8,11 @@ require_relative 'sgpg/cryptsetup'
8
8
  require_relative 'sgpg/mount'
9
9
  require_relative 'sgpg/gpg'
10
10
  require_relative 'sgpg/archive'
11
+ require_relative 'sgpg/incremental'
11
12
 
12
- # Manage your gpg key easyly
13
+ # Manage your gpg key
13
14
  module Sgpg
14
- def self.open(disk, is_crypted = false)
15
+ def self.open(disk, is_crypted = nil)
15
16
  return if Dir.glob("#{Sgpg::MOUNTPOINT}/*").length >= 1
16
17
 
17
18
  puts "Open device #{disk}..."
@@ -23,7 +24,7 @@ module Sgpg
23
24
  end
24
25
  end
25
26
 
26
- def self.close(disk, is_crypted = false)
27
+ def self.close(disk, is_crypted = nil)
27
28
  if is_crypted
28
29
  Mount.new('/dev/mapper/sgpg').close
29
30
  Cryptsetup.new(disk).close
@@ -32,10 +33,13 @@ module Sgpg
32
33
  end
33
34
  end
34
35
 
36
+ # https://www.rubyguides.com/2017/07/ruby-sort/
35
37
  def self.list_keys(keyname)
36
- keys = Dir.glob("#{Sgpg::MOUNTPOINT}/Persistent/#{keyname}*.tar")
38
+ dest = Helper.search_dest
39
+ dest += "/#{keyname}"
40
+ keys = Dir.glob("#{dest}/*.tar")
41
+
37
42
  puts "Listing keys for #{keyname}..."
38
- keys = Dir.glob("#{Sgpg::MOUNTPOINT}/Persistent/*.tar") if keys == [] || keys == ''
39
43
  puts keys
40
44
  end
41
45
 
@@ -43,19 +47,18 @@ module Sgpg
43
47
  def self.last_key(opts, suffix = 'master')
44
48
  Sgpg.open(opts[:disk], opts[:crypted])
45
49
 
46
- keys = Dir.glob("#{Sgpg::KEYDIR}/#{opts[:keyname]}*#{suffix}*.tar").sort
50
+ dest = Helper.search_dest
51
+ dest += "/#{opts[:keyname]}"
52
+ keys = Dir.glob("#{dest}/#{opts[:keyname]}*#{suffix}*.tar").sort
53
+
47
54
  raise 'No keys found' unless keys.length >= 1
48
55
 
49
- keys[0]
56
+ keys.last
50
57
  end
51
58
 
52
59
  def self.clear_keys
53
60
  return unless Dir.glob("#{Sgpg::WORKDIR}/*.key").length >= 1
54
61
 
55
- print "Clearing keys located at #{Sgpg::WORKDIR}? (y/n) "
56
- choice = gets.chomp
57
- return unless choice.match(/^y|^Y/)
58
-
59
62
  puts "Clearing #{Sgpg::WORKDIR}..."
60
63
  system("shred -u #{Sgpg::WORKDIR}/*.key")
61
64
  end
@@ -71,20 +74,44 @@ module Sgpg
71
74
  Sgpg.clear_keys
72
75
  end
73
76
 
74
- # export your real keys and create an archive (tar)
77
+ # Export your real keys and create an archive (tar)
75
78
  def self.export_secret(opts)
76
79
  archive = Archive.new(opts[:keypath], opts[:keyname])
77
80
  archive.create_master_tar
78
- archive.move(Sgpg::KEYDIR)
81
+ archive.move_to_disk
79
82
  Sgpg.clear_keys
80
83
  end
81
84
 
82
- # create an unpriviliged gpg key (no change can be made)
85
+ # Create an unprivileged GnuPG key (no change can be made)
83
86
  def self.lesser_keys(opts)
84
87
  archive = Archive.new(opts[:keypath], opts[:keyname])
85
88
  archive.create_lesser_tar
86
- archive.move(Sgpg::KEYDIR)
89
+ archive.move_to_disk
87
90
  Sgpg.clear_keys
88
91
  end
92
+
93
+ # Replace 'path/to/source' and 'path/to/destination' with actual paths on your machine. Run the script:
94
+ # pass store password at ~/.password-store by default
95
+ def self.incremental_export(keyname)
96
+ raise ArgumentError, 'incremental_export: No keyname' unless keyname
97
+
98
+ src = "#{ENV['HOME']}/.password-store"
99
+ dest = Helper.search_dest
100
+ dest += "/#{keyname}/.password-store"
101
+ puts "Exporting passwords from #{src} to #{dest}..."
102
+ backup = Incremental.new(src, dest)
103
+ backup.perform_backup
104
+ end
105
+
106
+ def self.incremental_import(keyname)
107
+ raise ArgumentError, 'incremental_export: No keyname' unless keyname
108
+
109
+ dest = "#{ENV['HOME']}/.password-store"
110
+ src = Helper.search_dest
111
+ src += "/#{keyname}/.password-store"
112
+ puts "Importing passwords from #{src} to #{dest}..."
113
+ backup = Incremental.new(src, dest)
114
+ backup.perform_backup
115
+ end
89
116
  end
90
117
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,18 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sgpg
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
  - szorfein
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain:
11
10
  - |
12
11
  -----BEGIN CERTIFICATE-----
13
- MIIEhTCCAu2gAwIBAgIBATANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDDAhzem9y
12
+ MIIEPDCCAqSgAwIBAgIBAzANBgkqhkiG9w0BAQsFADBEMREwDwYDVQQDDAhzem9y
14
13
  ZmVpbjEaMBgGCgmSJomT8ixkARkWCnByb3Rvbm1haWwxEzARBgoJkiaJk/IsZAEZ
15
- FgNjb20wHhcNMjMxMDIzMTcyMTA4WhcNMjQxMDIyMTcyMTA4WjBEMREwDwYDVQQD
14
+ FgNjb20wHhcNMjUxMDI2MTQyNTU2WhcNMjYxMDI2MTQyNTU2WjBEMREwDwYDVQQD
16
15
  DAhzem9yZmVpbjEaMBgGCgmSJomT8ixkARkWCnByb3Rvbm1haWwxEzARBgoJkiaJ
17
16
  k/IsZAEZFgNjb20wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCqe1yx
18
17
  EG2oM25jeHp08A8zkaDNmbI3MujjrRM/WPEYZX2dVwOxkIS20hQVuxcAsBBA4W/W
@@ -23,20 +22,18 @@ cert_chain:
23
22
  xI2/BnS8zOsS6Te08iLxqZfI/lsG8wcPduekSetRI4VIOZ5QoRK54PiQjrOBhbnD
24
23
  OQBB/XF1C80imZtRtdUqh6bK9WeWI4RYZ2/KwXL1AScEbXkBkkOECWoVrD18WgRm
25
24
  siuX6RkNIelhtb0En7f3bizgPqlO0qPQV+wPi9TSBxdVG12C0OmjCQYMQD0CAwEA
26
- AaOBgTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBTlKnQ3qMUF
27
- zydvZaKwdP+dnj2uajAiBgNVHREEGzAZgRdzem9yZmVpbkBwcm90b25tYWlsLmNv
28
- bTAiBgNVHRIEGzAZgRdzem9yZmVpbkBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0B
29
- AQsFAAOCAYEAFjnBWWfaMeA8hP0Q76WmBCFckGN5I42X5RQkVYRRXIaeXIS1td/t
30
- O1v1iQLo6ABfASMi6We7T16+ita68xwNOmSkMNHHXBr/fdGbHExxFSX7BXNRbwla
31
- SS6Vy0bXKMDJbXcvkrmIolpYhEFm1218FCRCT6ogM1oWAJAfhfF9pMeRxrxjQYFn
32
- ko8XgjIHxb83miOILgdq/lgJ4gfD7PsGfJtLCLiCKCcxIb4TtmKAzRwCDVpb6wqM
33
- 5xJZffAmHI7v8lVer53sPzm3INPu5xFZyfZ/SXYXPKKwln0efH63K5vuXYwEN7NI
34
- SBSRTN03Hb65t86m6/r084SrNnLntQjCSqApzFBt1QwJ5cmiVilODN4V7y2hZpyK
35
- hSk3b2VOotDPiWIm1p/IPXQDfm5x67Z5fJQPAlBTsse4jKyVyW1lZLmERSBuRZ2O
36
- urXgRIzALxd/xazPCnoLSXPzfJSI6Y77S1EBvhPd9RaSO8IyH9RhPDP9mnTvW2Kl
37
- NAUnoL+txK5a
25
+ AaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFOUqdDeoxQXP
26
+ J29lorB0/52ePa5qMA0GCSqGSIb3DQEBCwUAA4IBgQAW22kVqz92sKW7thsKrW2i
27
+ BwVahsopgVLIUqp7sT+nL6Jw1QWCxolDwSToWFo0XuwbNdqCuGRBM+IzhWmCcA0e
28
+ WoHAPGQAhKz5jCWJ9GwgWbttYNrZ/PkyzKlT+15itMVeEEKxcqvfVFkdTXvTtliP
29
+ h75zR66tpFPjOejy+YD0uSPWbR/Nskf4BaMFso7mEr+5nOfzj0+Emy3MikHMm7uo
30
+ qZEazJO4XlmQWI2O7skt/SkE6xiZDQeCADZ4NXxBNzKkxKpozBXSeBKNUi21y9zR
31
+ 3PGUOg6fCZt5H3kSffrvtycOnAu/FRNrQUxKRHLJKez8d7zJH64sBdldm5fZJu1O
32
+ pzUhdmhxa/brsIYFPPsjw0PminqSEmFahOoGyph8lw1IYu6UskIlB+J1BLZxsPkJ
33
+ 6+fmQQAYvIhUQH+pOPELkGGo+bQMpCLb4i97kyzbOjJqAFKsgqgCOtvUC4yUZRNb
34
+ YulAM0cmmcfbzWUxsyAoCp9mY227qQZpGv6dDgv4IbA=
38
35
  -----END CERTIFICATE-----
39
- date: 2024-09-10 00:00:00.000000000 Z
36
+ date: 1980-01-02 00:00:00.000000000 Z
40
37
  dependencies: []
41
38
  description: " Short gpg, tool for manage your gpg key (backup tarball, unprivileged
42
39
  keys, etc...)\n"
@@ -56,6 +53,7 @@ files:
56
53
  - lib/sgpg/cryptsetup.rb
57
54
  - lib/sgpg/gpg.rb
58
55
  - lib/sgpg/helper.rb
56
+ - lib/sgpg/incremental.rb
59
57
  - lib/sgpg/mount.rb
60
58
  - lib/sgpg/option.rb
61
59
  - lib/sgpg/version.rb
@@ -70,7 +68,6 @@ metadata:
70
68
  source_code_uri: https://github.com/szorfein/sgpg
71
69
  wiki_uri: https://github.com/szorfein/sgpg/wiki
72
70
  funding_uri: https://patreon.com/szorfein
73
- post_install_message:
74
71
  rdoc_options: []
75
72
  require_paths:
76
73
  - lib
@@ -89,8 +86,7 @@ requirements:
89
86
  - cryptsetup
90
87
  - shred
91
88
  - tar
92
- rubygems_version: 3.3.25
93
- signing_key:
89
+ rubygems_version: 3.6.9
94
90
  specification_version: 4
95
91
  summary: Short gpg, tool for manage your gpg key (backup tarball, unprivileged keys,
96
92
  etc...)
metadata.gz.sig CHANGED
Binary file