Skip to content

Commit

Permalink
keygen spec
Browse files Browse the repository at this point in the history
  • Loading branch information
jshawl committed Feb 11, 2024
1 parent 132a5af commit e9d9750
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 15 deletions.
43 changes: 28 additions & 15 deletions bin/minisign
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'io/console'
require 'minisign'
require 'optparse'

USAGE = <<~ENDUSAGE
Usage:
minisign -G [-f] [-p pubkey_file] [-s seckey_file] [-W]
ENDUSAGE
Signal.trap('INT') { exit }

HELP = <<~ENDHELP
-G generate a new key pair
-f force. Combined with -G, overwrite a previous key pair
-p <pubkey_file> public key file (default: ./minisign.pub)
-s <seckey_file> secret key file (default: ~/.minisign/minisign.key)
-W do not encrypt/decrypt the secret key with a password
ENDHELP
options = {}
op = OptionParser.new do |opts|
opts.on('-G') do |g|
options[:G] = g
end
opts.on('-f') do |f|
options[:f] = f
end
opts.on('-sSECRET_KEY') do |s|
options[:s] = s
end
opts.on('-pPUBLIC_KEY') do |p|
options[:p] = p
end
end

if ARGV.empty?
puts USAGE
puts HELP
begin
op.parse!
raise OptionParser::InvalidOption if options.keys.empty?
rescue OptionParser::InvalidOption
Minisign::CLI.usage
puts ''
Minisign::CLI.help
exit 1
end

Minisign::CLI.generate(options) if options[:G]
1 change: 1 addition & 0 deletions lib/minisign.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'base64'
require 'rbnacl'

require 'minisign/cli'
require 'minisign/utils'
require 'minisign/public_key'
require 'minisign/signature'
Expand Down
58 changes: 58 additions & 0 deletions lib/minisign/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

require 'io/console'

module Minisign
# The command line interface
module CLI
# lol
def self.help
puts '-G generate a new key pair'
puts '-f force. Combined with -G, overwrite a previous key pair'
puts '-p <pubkey_file> public key file (default: ./minisign.pub)'
puts '-s <seckey_file> secret key file (default: ~/.minisign/minisign.key)'
puts '-W do not encrypt/decrypt the secret key with a password'
end

def self.usage
puts 'Usage:'
puts 'minisign -G [-f] [-p pubkey_file] [-s seckey_file] [-W]'
end

def self.prevent_overwrite!(file)
return unless File.exist? file

puts 'Key generation aborted:'
puts "#{file} already exists."
puts ''
puts 'If you really want to overwrite the existing key pair, add the -f switch to'
puts 'force this operation.'
exit 1
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def self.generate(options)
secret_key = options[:s] || "#{Dir.home}/.minisign/minisign.key"
public_key = options[:p] || './minisign.pub'
prevent_overwrite!(public_key) unless options[:f]
prevent_overwrite!(secret_key) unless options[:f]

if options[:W]
keypair = Minisign::KeyPair.new
File.write(secret_key, keypair.private_key)
File.write(public_key, keypair.public_key)
else
print 'Password: '
password = $stdin.noecho(&:gets).chomp
print "\nDeriving a key from the password in order to encrypt the secret key..."
keypair = Minisign::KeyPair.new(password)
File.write(secret_key, keypair.private_key)
File.write(public_key, keypair.public_key)
print " done\n"
end
end
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
end
end
Empty file added minisign.pub
Empty file.
40 changes: 40 additions & 0 deletions spec/minisign/cli_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

describe Minisign::CLI do
describe '.generate' do
before do
@options = {
p: 'test/minisign.pub',
s: 'test/minisign.key'
}
end
it 'does not overwrite existing keys' do
expect do
Minisign::CLI.generate(@options)
end.to raise_error(SystemExit)
end
it 'does not prompt for a password if -W' do
keyname = SecureRandom.uuid
SecureRandom.uuid
options = {
p: "test/generated/cli/#{keyname}.pub",
s: "test/generated/cli/#{keyname}.key",
W: true
}
expect($stdin).not_to receive(:gets)
Minisign::CLI.generate(options)
end
it 'writes the key files' do
keyname = SecureRandom.uuid
password = SecureRandom.uuid
options = {
p: "test/generated/cli/#{keyname}.pub",
s: "test/generated/cli/#{keyname}.key"
}
allow($stdin).to receive(:gets).and_return(password)
Minisign::CLI.generate(options)
expect(File.exist?(options[:p])).to eq(true)
expect(File.exist?(options[:p])).to eq(true)
end
end
end

0 comments on commit e9d9750

Please sign in to comment.