Skip to content

Commit

Permalink
optional libsodium (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
jshawl committed Feb 19, 2024
1 parent feb2e51 commit 172b477
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Make `libsodium` dependency optional for consumers who want to verify signatures _only_

## [0.2.1] - 2024-02-19

### Added
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ A ruby implemenation of [Minisign](http://jedisct1.github.io/minisign/).
gem install minisign
```

**Note**: This gem has a conditional dependency on [`libsodium`](https://doc.libsodium.org/) for the functionality related to key derivation and signature creation.
Signature verification _does not_ need `libsodium`.

### Read a public key

```rb
Expand Down
5 changes: 5 additions & 0 deletions bin/minisign
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ rescue OptionParser::InvalidOption
exit 1
end

if (options[:G] || options[:R] || options[:C] || options[:S]) && !RbNaCl.const_defined?(:PasswordHash)
warn 'Error: libsodium is not installed!'
exit 1
end

Minisign::CLI.generate(options) if options[:G]
Minisign::CLI.recreate(options) if options[:R]
Minisign::CLI.change_password(options) if options[:C]
Expand Down
8 changes: 7 additions & 1 deletion lib/minisign.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

require 'ed25519'
require 'base64'
require 'rbnacl'
require 'openssl'
begin
require 'rbnacl'
rescue LoadError
# errors handled when invoked (see Minisign::NaCl)
end

require 'minisign/cli'
require 'minisign/utils'
require 'minisign/public_key'
require 'minisign/signature'
require 'minisign/private_key'
require 'minisign/key_pair'
require 'minisign/nacl'
require 'minisign/error'
3 changes: 3 additions & 0 deletions lib/minisign/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ class PasswordMissingError < StandardError

class PasswordIncorrectError < StandardError
end

class LibSodiumDependencyError < StandardError
end
end
30 changes: 30 additions & 0 deletions lib/minisign/nacl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module Minisign
# A module that invokes RbNaCl with user-focused actionable error messages.
module NaCl
def self.assert_libsodium_dependency_met!
return if RbNaCl.const_defined?(:PasswordHash)

raise Minisign::LibSodiumDependencyError, 'libsodium is not installed!'
end

module Hash
# see RbNaCl::Hash::Blake2b
module Blake2b
def self.digest(*args)
NaCl.assert_libsodium_dependency_met!
RbNaCl::Hash::Blake2b.digest(*args)
end
end
end

# see RbNaCl::PasswordHash
module PasswordHash
def self.scrypt(*args)
NaCl.assert_libsodium_dependency_met!
RbNaCl::PasswordHash.scrypt(*args)
end
end
end
end
6 changes: 3 additions & 3 deletions lib/minisign/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ module Minisign
# Helpers used in multiple classes
module Utils
def blake2b256(message)
RbNaCl::Hash::Blake2b.digest(message, { digest_size: 32 })
Minisign::NaCl::Hash::Blake2b.digest(message, { digest_size: 32 })
end

def blake2b512(message)
RbNaCl::Hash::Blake2b.digest(message, { digest_size: 64 })
OpenSSL::Digest.new('blake2b512').digest(message)
end

# @return [Array<32 bit unsigned ints>]
Expand All @@ -25,7 +25,7 @@ def hex(bytes)

# @return [String] the <kdf_output> used to xor the ed25519 keys
def derive_key(password, kdf_salt, kdf_opslimit, kdf_memlimit)
RbNaCl::PasswordHash.scrypt(
Minisign::NaCl::PasswordHash.scrypt(
password,
kdf_salt,
kdf_opslimit,
Expand Down
13 changes: 13 additions & 0 deletions spec/minisign/nacl_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

describe Minisign::NaCl do
it 'raises LibSodiumDependencyError if libsodium not installed' do
hash = RbNaCl.send(:remove_const, :Hash)
password_hash = RbNaCl.send(:remove_const, :PasswordHash)
expect do
Minisign::NaCl::Hash::Blake2b.digest('message', { digest_size: 32 })
end.to raise_error(Minisign::LibSodiumDependencyError)
RbNaCl.const_set(:Hash, hash)
RbNaCl.const_set(:PasswordHash, password_hash)
end
end

0 comments on commit 172b477

Please sign in to comment.