ffi-libsodium 0.1.10 → 0.2.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 +4 -4
- data/README.md +1 -1
- data/lib/crypto/aead/chacha20_poly1305.rb +17 -12
- data/lib/crypto/auth.rb +3 -2
- data/lib/crypto/box.rb +30 -34
- data/lib/crypto/generic_hash.rb +13 -33
- data/lib/crypto/one_time_auth.rb +3 -4
- data/lib/crypto/pw_hash/scrypt_salsa208_sha256.rb +13 -24
- data/lib/crypto/scalar_mult.rb +3 -2
- data/lib/crypto/secret_box.rb +27 -26
- data/lib/crypto/short_hash.rb +2 -1
- data/lib/crypto/sign.rb +8 -13
- data/lib/crypto/sign/ed25519.rb +2 -0
- data/lib/libsodium.rb +4 -1
- data/lib/random_bytes.rb +2 -0
- data/lib/sodium.rb +4 -35
- data/lib/sodium/buffer.rb +3 -5
- data/lib/sodium/errors.rb +3 -3
- data/lib/sodium/mprotect.rb +30 -0
- data/lib/sodium/secret_buffer.rb +19 -16
- data/lib/sodium/utils.rb +29 -54
- data/lib/sodium/version.rb +1 -1
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 95a7d9bb37cc560f3dfbb7a72a6bcf31ffdf63d6
         | 
| 4 | 
            +
              data.tar.gz: 636823f16c86f508ff3180c56edb357a6b8afa2c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e101ac68e41004c5b1dab8594baf37a6bd3c68fa6bb4981fdc556ef7d6d9cfac3e5aadaaec9c4ff11c524570fcf49500459aca5eed2486c8af7835235a0a5b61
         | 
| 7 | 
            +
              data.tar.gz: 9c3e394cdf2941d370ad3c690c0bf17a335ba4cc9aba9aea5fa61b88bdff986369493be2348aa3d6663fff6e6e98c3aa6901d5fbefd5b59a5d3893f5bc696fa1
         | 
    
        data/README.md
    CHANGED
    
    | @@ -11,7 +11,7 @@ bundle update | |
| 11 11 | 
             
            require 'bundler/setup'
         | 
| 12 12 | 
             
            require 'libsodium'
         | 
| 13 13 |  | 
| 14 | 
            -
            password = 'test123'
         | 
| 14 | 
            +
            password = Crypto.generichash('test123')
         | 
| 15 15 |  | 
| 16 16 | 
             
            salt = Crypto::PwHash::ScryptSalsa208SHA256.salt
         | 
| 17 17 | 
             
            key = Crypto::PwHash.scryptsalsa208sha256(Crypto::Auth::KEYBYTES, password, salt)
         | 
| @@ -46,7 +46,6 @@ module Crypto | |
| 46 46 | 
             
                    check_length(key, KEYBYTES, :SecretKey)
         | 
| 47 47 |  | 
| 48 48 | 
             
                    ciphertext = Sodium::Buffer.new(:uchar, message_len + ABYTES)
         | 
| 49 | 
            -
                    ciphertext.primitive = PRIMITIVE
         | 
| 50 49 | 
             
                    key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 51 50 | 
             
                    crypto_aead_chacha20poly1305_encrypt(ciphertext, nil, message, message_len, additional_data, get_size(additional_data), nil, nonce, key)
         | 
| 52 51 |  | 
| @@ -56,22 +55,28 @@ module Crypto | |
| 56 55 | 
             
                  end
         | 
| 57 56 |  | 
| 58 57 | 
             
                  def decrypt(ciphertext, additional_data, nonce, key)
         | 
| 59 | 
            -
                     | 
| 58 | 
            +
                    ciphertext_len = get_size(ciphertext)
         | 
| 59 | 
            +
                    if (decrypted_len = ciphertext_len - ABYTES) > 0
         | 
| 60 | 
            +
                      check_length(nonce, NPUBBYTES, :Nonce)
         | 
| 61 | 
            +
                      check_length(key, KEYBYTES, :SecretKey)
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                      decrypted = Sodium::Buffer.new(:uchar, decrypted_len)
         | 
| 64 | 
            +
                      key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 65 | 
            +
                      if crypto_aead_chacha20poly1305_decrypt(decrypted, nil, nil, ciphertext, ciphertext_len, additional_data, get_size(additional_data), nonce, key) == 0
         | 
| 66 | 
            +
                        decrypted
         | 
| 67 | 
            +
                      else
         | 
| 68 | 
            +
                        raise Sodium::CryptoError, "Message forged", caller
         | 
| 69 | 
            +
                      end
         | 
| 70 | 
            +
                    else
         | 
| 60 71 | 
             
                      fail Sodium::LengthError, "Ciphertext is too short", caller
         | 
| 61 72 | 
             
                    end
         | 
| 62 | 
            -
                    check_length(nonce, NPUBBYTES, :Nonce)
         | 
| 63 | 
            -
                    check_length(key, KEYBYTES, :SecretKey)
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                    decrypted = Sodium::Buffer.new(:uchar, ciphertext_len - ABYTES)
         | 
| 66 | 
            -
                    key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 67 | 
            -
                    unless crypto_aead_chacha20poly1305_decrypt(decrypted, nil, nil, ciphertext, ciphertext_len, additional_data, get_size(additional_data), nonce, key).zero?
         | 
| 68 | 
            -
                      raise Sodium::CryptoError, "Message forged", caller
         | 
| 69 | 
            -
                    end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                    decrypted
         | 
| 72 73 | 
             
                  ensure
         | 
| 73 74 | 
             
                    key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 74 75 | 
             
                  end
         | 
| 75 76 | 
             
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                Chacha20Poly1305.freeze
         | 
| 76 79 | 
             
              end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              AEAD.freeze
         | 
| 77 82 | 
             
            end
         | 
    
        data/lib/crypto/auth.rb
    CHANGED
    
    | @@ -27,7 +27,6 @@ module Crypto | |
| 27 27 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 28 28 |  | 
| 29 29 | 
             
                  mac = Sodium::Buffer.new(:uchar, BYTES)
         | 
| 30 | 
            -
                  mac.primitive = PRIMITIVE
         | 
| 31 30 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 32 31 | 
             
                  crypto_auth(mac, message, get_size(message), key)
         | 
| 33 32 |  | 
| @@ -41,12 +40,14 @@ module Crypto | |
| 41 40 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 42 41 |  | 
| 43 42 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 44 | 
            -
                  crypto_auth_verify(mac, message, get_size(message), key) | 
| 43 | 
            +
                  crypto_auth_verify(mac, message, get_size(message), key) == 0
         | 
| 45 44 | 
             
                ensure
         | 
| 46 45 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 47 46 | 
             
                end
         | 
| 48 47 | 
             
              end
         | 
| 49 48 |  | 
| 49 | 
            +
              Auth.freeze
         | 
| 50 | 
            +
             | 
| 50 51 | 
             
              module_function
         | 
| 51 52 |  | 
| 52 53 | 
             
              def auth(*args)
         | 
    
        data/lib/crypto/box.rb
    CHANGED
    
    | @@ -40,9 +40,7 @@ module Crypto | |
| 40 40 |  | 
| 41 41 | 
             
                def keypair
         | 
| 42 42 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 43 | 
            -
                  public_key.primitive = PRIMITIVE
         | 
| 44 43 | 
             
                  secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
         | 
| 45 | 
            -
                  secret_key.primitive = PRIMITIVE
         | 
| 46 44 | 
             
                  crypto_box_keypair(public_key, secret_key)
         | 
| 47 45 |  | 
| 48 46 | 
             
                  [public_key, secret_key]
         | 
| @@ -52,9 +50,7 @@ module Crypto | |
| 52 50 | 
             
                  check_length(seed, SEEDBYTES, :Seed)
         | 
| 53 51 |  | 
| 54 52 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 55 | 
            -
                  public_key.primitive = PRIMITIVE
         | 
| 56 53 | 
             
                  secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
         | 
| 57 | 
            -
                  secret_key.primitive = PRIMITIVE
         | 
| 58 54 | 
             
                  seed.readonly if seed.is_a?(Sodium::SecretBuffer)
         | 
| 59 55 | 
             
                  crypto_box_seed_keypair(public_key, secret_key, seed)
         | 
| 60 56 |  | 
| @@ -65,8 +61,7 @@ module Crypto | |
| 65 61 |  | 
| 66 62 | 
             
                def memory_locked_keypair
         | 
| 67 63 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 68 | 
            -
                   | 
| 69 | 
            -
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
         | 
| 64 | 
            +
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
         | 
| 70 65 | 
             
                  crypto_box_keypair(public_key, secret_key)
         | 
| 71 66 | 
             
                  secret_key.noaccess
         | 
| 72 67 |  | 
| @@ -77,8 +72,7 @@ module Crypto | |
| 77 72 | 
             
                  check_length(seed, SEEDBYTES, :Seed)
         | 
| 78 73 |  | 
| 79 74 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 80 | 
            -
                   | 
| 81 | 
            -
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
         | 
| 75 | 
            +
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
         | 
| 82 76 | 
             
                  seed.readonly if seed.is_a?(Sodium::SecretBuffer)
         | 
| 83 77 | 
             
                  crypto_box_seed_keypair(public_key, secret_key, seed)
         | 
| 84 78 | 
             
                  secret_key.noaccess
         | 
| @@ -95,7 +89,6 @@ module Crypto | |
| 95 89 | 
             
                  check_length(secret_key, SECRETKEYBYTES, :SecretKey)
         | 
| 96 90 |  | 
| 97 91 | 
             
                  ciphertext = Sodium::Buffer.new(:uchar, message_len + MACBYTES)
         | 
| 98 | 
            -
                  ciphertext.primitive = PRIMITIVE
         | 
| 99 92 | 
             
                  secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 100 93 | 
             
                  crypto_box_easy(ciphertext, message, message_len, nonce, public_key, secret_key)
         | 
| 101 94 |  | 
| @@ -112,22 +105,22 @@ module Crypto | |
| 112 105 |  | 
| 113 106 | 
             
                  decrypted = Sodium::Buffer.new(:uchar, ciphertext_len - MACBYTES)
         | 
| 114 107 | 
             
                  secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 115 | 
            -
                   | 
| 108 | 
            +
                  if crypto_box_open_easy(decrypted, ciphertext, ciphertext_len, nonce, public_key, secret_key) == 0
         | 
| 109 | 
            +
                    decrypted
         | 
| 110 | 
            +
                  else
         | 
| 116 111 | 
             
                    raise Sodium::CryptoError, "Message forged", caller
         | 
| 117 112 | 
             
                  end
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                  decrypted
         | 
| 120 113 | 
             
                ensure
         | 
| 121 114 | 
             
                  secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 122 115 | 
             
                end
         | 
| 123 116 |  | 
| 124 117 | 
             
                def easy_in_place(data, nonce, public_key, secret_key)
         | 
| 125 | 
            -
                  message =  | 
| 118 | 
            +
                  message = String(data)
         | 
| 126 119 | 
             
                  check_length(nonce, NONCEBYTES, :Nonce)
         | 
| 127 120 | 
             
                  check_length(public_key, PUBLICKEYBYTES, :PublicKey)
         | 
| 128 121 | 
             
                  check_length(secret_key, SECRETKEYBYTES, :SecretKey)
         | 
| 129 122 |  | 
| 130 | 
            -
                  message_len =  | 
| 123 | 
            +
                  message_len = message.bytesize
         | 
| 131 124 | 
             
                  message << zeros(MACBYTES)
         | 
| 132 125 | 
             
                  secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 133 126 | 
             
                  crypto_box_easy(message, message, message_len, nonce, public_key, secret_key)
         | 
| @@ -137,33 +130,36 @@ module Crypto | |
| 137 130 | 
             
                  secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 138 131 | 
             
                end
         | 
| 139 132 |  | 
| 140 | 
            -
                def open_easy_in_place(data, nonce, public_key, secret_key,  | 
| 141 | 
            -
                  ciphertext =  | 
| 142 | 
            -
                   | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 133 | 
            +
                def open_easy_in_place(data, nonce, public_key, secret_key, encoding = false)
         | 
| 134 | 
            +
                  ciphertext = String(data)
         | 
| 135 | 
            +
                  ciphertext_len = ciphertext.bytesize
         | 
| 136 | 
            +
                  if (message_len = ciphertext_len - MACBYTES) > 0
         | 
| 137 | 
            +
                    check_length(nonce, NONCEBYTES, :Nonce)
         | 
| 138 | 
            +
                    check_length(public_key, PUBLICKEYBYTES, :PublicKey)
         | 
| 139 | 
            +
                    check_length(secret_key, SECRETKEYBYTES, :SecretKey)
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                    secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 142 | 
            +
                    if crypto_box_open_easy(ciphertext, ciphertext, ciphertext_len, nonce, public_key, secret_key) == 0
         | 
| 143 | 
            +
                      if encoding
         | 
| 144 | 
            +
                        ciphertext.slice!(message_len..-1).force_encoding(encoding)
         | 
| 145 | 
            +
                      else
         | 
| 146 | 
            +
                        ciphertext.slice!(message_len..-1)
         | 
| 147 | 
            +
                      end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                      ciphertext
         | 
| 150 | 
            +
                    else
         | 
| 151 | 
            +
                      raise Sodium::CryptoError, "Message forged", caller
         | 
| 152 | 
            +
                    end
         | 
| 157 153 | 
             
                  else
         | 
| 158 | 
            -
                     | 
| 154 | 
            +
                    fail Sodium::LengthError, "Ciphertext is too short", caller
         | 
| 159 155 | 
             
                  end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                  ciphertext
         | 
| 162 156 | 
             
                ensure
         | 
| 163 157 | 
             
                  secret_key.noaccess if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 164 158 | 
             
                end
         | 
| 165 159 | 
             
              end
         | 
| 166 160 |  | 
| 161 | 
            +
              Box.freeze
         | 
| 162 | 
            +
             | 
| 167 163 | 
             
              module_function
         | 
| 168 164 |  | 
| 169 165 | 
             
              def box(*args)
         | 
    
        data/lib/crypto/generic_hash.rb
    CHANGED
    
    | @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            require 'ffi'
         | 
| 2 2 | 
             
            require_relative '../sodium/utils'
         | 
| 3 | 
            -
            require_relative '../sodium/errors'
         | 
| 4 3 | 
             
            require_relative '../sodium/buffer'
         | 
| 5 4 | 
             
            require_relative '../sodium/secret_buffer'
         | 
| 5 | 
            +
            require_relative '../sodium/errors'
         | 
| 6 6 |  | 
| 7 7 | 
             
            module Crypto
         | 
| 8 8 | 
             
              module GenericHash
         | 
| @@ -46,28 +46,19 @@ module Crypto | |
| 46 46 | 
             
                module_function
         | 
| 47 47 |  | 
| 48 48 | 
             
                def generichash(message, hash_size = BYTES, key = nil)
         | 
| 49 | 
            -
                  if hash_size > BYTES_MAX ||hash_size < BYTES_MIN
         | 
| 50 | 
            -
                    fail Sodium::LengthError, "Hash size must be between #{BYTES_MIN} and #{BYTES_MAX} bytes, got size=#{hash_size} bytes", caller
         | 
| 51 | 
            -
                  end
         | 
| 52 | 
            -
             | 
| 53 49 | 
             
                  if key
         | 
| 54 50 | 
             
                    key_len = get_size(key)
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                    if key_len > KEYBYTES_MAX ||key_len < KEYBYTES_MIN
         | 
| 57 | 
            -
                      fail Sodium::LengthError, "Key length must be between #{KEYBYTES_MIN} and #{KEYBYTES_MAX} bytes, got length=#{key_len} bytes", caller
         | 
| 58 | 
            -
                    end
         | 
| 59 51 | 
             
                  else
         | 
| 60 52 | 
             
                    key_len = 0
         | 
| 61 53 | 
             
                  end
         | 
| 62 54 |  | 
| 63 55 | 
             
                  blake2b = Sodium::Buffer.new(:uchar, hash_size)
         | 
| 64 | 
            -
                  blake2b.primitive = PRIMITIVE
         | 
| 65 56 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 66 | 
            -
                   | 
| 57 | 
            +
                  if crypto_generichash(blake2b, hash_size, message, get_size(message), key, key_len) == 0
         | 
| 58 | 
            +
                    blake2b
         | 
| 59 | 
            +
                  else
         | 
| 67 60 | 
             
                    raise Sodium::CryptoError
         | 
| 68 61 | 
             
                  end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  blake2b
         | 
| 71 62 | 
             
                ensure
         | 
| 72 63 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 73 64 | 
             
                end
         | 
| @@ -75,47 +66,36 @@ module Crypto | |
| 75 66 | 
             
                def init(key = nil, hash_size = BYTES)
         | 
| 76 67 | 
             
                  if key
         | 
| 77 68 | 
             
                    key_len = get_size(key)
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                    if key_len > KEYBYTES_MAX ||key_len < KEYBYTES_MIN
         | 
| 80 | 
            -
                      fail Sodium::LengthError, "Key length must be between #{KEYBYTES_MIN} and #{KEYBYTES_MAX} bytes, got length=#{key_len} bytes", caller
         | 
| 81 | 
            -
                    end
         | 
| 82 69 | 
             
                  else
         | 
| 83 70 | 
             
                    key_len = 0
         | 
| 84 71 | 
             
                  end
         | 
| 85 72 |  | 
| 86 | 
            -
                  if hash_size > BYTES_MAX ||hash_size < BYTES_MIN
         | 
| 87 | 
            -
                    fail Sodium::LengthError, "Hash size must be between #{BYTES_MIN} and #{BYTES_MAX} bytes, got size=#{hash_size} bytes", caller
         | 
| 88 | 
            -
                  end
         | 
| 89 | 
            -
             | 
| 90 73 | 
             
                  state = State.new
         | 
| 91 | 
            -
                  blake2b = Sodium::Buffer.new(:uchar, hash_size)
         | 
| 92 | 
            -
                  blake2b.primitive = PRIMITIVE
         | 
| 93 74 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 75 | 
            +
                  if crypto_generichash_init(state, key, key_len, hash_size) == 0
         | 
| 76 | 
            +
                    [state, Sodium::Buffer.new(:uchar, hash_size)]
         | 
| 77 | 
            +
                  else
         | 
| 96 78 | 
             
                    raise Sodium::CryptoError
         | 
| 97 79 | 
             
                  end
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                  [state, blake2b]
         | 
| 100 80 | 
             
                ensure
         | 
| 101 81 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 102 82 | 
             
                end
         | 
| 103 83 |  | 
| 104 84 | 
             
                def update(state, message)
         | 
| 105 | 
            -
                   | 
| 106 | 
            -
                    raise Sodium::CryptoError
         | 
| 107 | 
            -
                  end
         | 
| 85 | 
            +
                  crypto_generichash_update(state, message, get_size(message))
         | 
| 108 86 | 
             
                end
         | 
| 109 87 |  | 
| 110 88 | 
             
                def final(state, blake2b)
         | 
| 111 | 
            -
                   | 
| 89 | 
            +
                  if crypto_generichash_final(state, blake2b, blake2b.size) == 0
         | 
| 90 | 
            +
                    blake2b
         | 
| 91 | 
            +
                  else
         | 
| 112 92 | 
             
                    raise Sodium::CryptoError
         | 
| 113 93 | 
             
                  end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                  blake2b
         | 
| 116 94 | 
             
                end
         | 
| 117 95 | 
             
              end
         | 
| 118 96 |  | 
| 97 | 
            +
              GenericHash.freeze
         | 
| 98 | 
            +
             | 
| 119 99 | 
             
              module_function
         | 
| 120 100 |  | 
| 121 101 | 
             
              def generichash(*args)
         | 
    
        data/lib/crypto/one_time_auth.rb
    CHANGED
    
    | @@ -36,7 +36,6 @@ module Crypto | |
| 36 36 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 37 37 |  | 
| 38 38 | 
             
                  out = Sodium::Buffer.new(:uchar, BYTES)
         | 
| 39 | 
            -
                  out.primitive = PRIMITIVE
         | 
| 40 39 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 41 40 | 
             
                  crypto_onetimeauth(out, message, get_size(message), key)
         | 
| 42 41 |  | 
| @@ -50,7 +49,7 @@ module Crypto | |
| 50 49 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 51 50 |  | 
| 52 51 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 53 | 
            -
                  crypto_onetimeauth_verify(out, message, get_size(message), key) | 
| 52 | 
            +
                  crypto_onetimeauth_verify(out, message, get_size(message), key) == 0
         | 
| 54 53 | 
             
                ensure
         | 
| 55 54 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 56 55 | 
             
                end
         | 
| @@ -73,13 +72,13 @@ module Crypto | |
| 73 72 |  | 
| 74 73 | 
             
                def final(state)
         | 
| 75 74 | 
             
                  out = Sodium::Buffer.new(:uchar, BYTES)
         | 
| 76 | 
            -
                  out.primitive = PRIMITIVE
         | 
| 77 75 | 
             
                  crypto_onetimeauth_final(state, out)
         | 
| 78 | 
            -
             | 
| 79 76 | 
             
                  out
         | 
| 80 77 | 
             
                end
         | 
| 81 78 | 
             
              end
         | 
| 82 79 |  | 
| 80 | 
            +
              OneTimeAuth.freeze
         | 
| 81 | 
            +
             | 
| 83 82 | 
             
              module_function
         | 
| 84 83 |  | 
| 85 84 | 
             
              def onetimeauth(*args)
         | 
| @@ -49,51 +49,40 @@ module Crypto | |
| 49 49 | 
             
                  end
         | 
| 50 50 |  | 
| 51 51 | 
             
                  def scryptsalsa208sha256(outlen, passwd, salt, opslimit = OPSLIMIT_INTERACTIVE, memlimit = MEMLIMIT_INTERACTIVE)
         | 
| 52 | 
            -
                    out = nil
         | 
| 53 52 | 
             
                    check_length(salt, SALTBYTES, :Salt)
         | 
| 54 | 
            -
                    if opslimit < OPSLIMIT_INTERACTIVE
         | 
| 55 | 
            -
                      fail Sodium::LengthError, "Opslimit must be at least #{OPSLIMIT_INTERACTIVE}, got #{opslimit}", caller
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
                    if memlimit < MEMLIMIT_INTERACTIVE
         | 
| 58 | 
            -
                      fail Sodium::LengthError, "Memlimit must be at least #{MEMLIMIT_INTERACTIVE}, got #{memlimit}", caller
         | 
| 59 | 
            -
                    end
         | 
| 60 53 |  | 
| 61 | 
            -
                    out = Sodium::SecretBuffer.new(outlen | 
| 62 | 
            -
                     | 
| 54 | 
            +
                    out = Sodium::SecretBuffer.new(outlen)
         | 
| 55 | 
            +
                    if crypto_pwhash_scryptsalsa208sha256(out, outlen, passwd, get_size(passwd), salt, opslimit, memlimit) == 0
         | 
| 56 | 
            +
                      out.noaccess
         | 
| 57 | 
            +
                      out
         | 
| 58 | 
            +
                    else
         | 
| 63 59 | 
             
                      raise NoMemoryError, "Failed to allocate memory max size=#{memlimit} bytes", caller
         | 
| 64 60 | 
             
                    end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                    out
         | 
| 67 | 
            -
                  ensure
         | 
| 68 | 
            -
                    out.noaccess if out
         | 
| 69 61 | 
             
                  end
         | 
| 70 62 |  | 
| 71 63 | 
             
                  def str(passwd, opslimit = OPSLIMIT_INTERACTIVE, memlimit = MEMLIMIT_INTERACTIVE)
         | 
| 72 | 
            -
                    if opslimit < OPSLIMIT_INTERACTIVE
         | 
| 73 | 
            -
                      fail Sodium::LengthError, "Opslimit must be at least #{OPSLIMIT_INTERACTIVE}, got #{opslimit}", caller
         | 
| 74 | 
            -
                    end
         | 
| 75 | 
            -
                    if memlimit < MEMLIMIT_INTERACTIVE
         | 
| 76 | 
            -
                      fail Sodium::LengthError, "Memlimit must be at least #{MEMLIMIT_INTERACTIVE}, got #{memlimit}", caller
         | 
| 77 | 
            -
                    end
         | 
| 78 | 
            -
             | 
| 79 64 | 
             
                    hashed_password = FFI::MemoryPointer.new(:char, STRBYTES)
         | 
| 80 | 
            -
                     | 
| 65 | 
            +
                    if crypto_pwhash_scryptsalsa208sha256_str(hashed_password, passwd, get_size(passwd), opslimit, memlimit) == 0
         | 
| 66 | 
            +
                      hashed_password.get_string(0)
         | 
| 67 | 
            +
                    else
         | 
| 81 68 | 
             
                      raise NoMemoryError, "Failed to allocate memory max size=#{memlimit} bytes", caller
         | 
| 82 69 | 
             
                    end
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    hashed_password.get_string(0)
         | 
| 85 70 | 
             
                  end
         | 
| 86 71 |  | 
| 87 72 | 
             
                  def str_verify(str, passwd)
         | 
| 88 73 | 
             
                    check_length(str, STRBYTES - 1, :Str)
         | 
| 89 | 
            -
                    crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd, get_size(passwd)) | 
| 74 | 
            +
                    crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd, get_size(passwd)) == 0
         | 
| 90 75 | 
             
                  end
         | 
| 91 76 | 
             
                end
         | 
| 92 77 |  | 
| 78 | 
            +
                ScryptSalsa208SHA256.freeze
         | 
| 79 | 
            +
             | 
| 93 80 | 
             
                module_function
         | 
| 94 81 |  | 
| 95 82 | 
             
                def scryptsalsa208sha256(*args)
         | 
| 96 83 | 
             
                  ScryptSalsa208SHA256.scryptsalsa208sha256(*args)
         | 
| 97 84 | 
             
                end
         | 
| 98 85 | 
             
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              PwHash.freeze
         | 
| 99 88 | 
             
            end
         | 
    
        data/lib/crypto/scalar_mult.rb
    CHANGED
    
    | @@ -27,7 +27,6 @@ module Crypto | |
| 27 27 | 
             
                  check_length(secret_key, SCALARBYTES, :SecretKey)
         | 
| 28 28 |  | 
| 29 29 | 
             
                  public_key = Sodium::Buffer.new(:uchar, BYTES)
         | 
| 30 | 
            -
                  public_key.primitive = PRIMITIVE
         | 
| 31 30 | 
             
                  secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 32 31 | 
             
                  crypto_scalarmult_base(public_key, secret_key)
         | 
| 33 32 |  | 
| @@ -40,7 +39,7 @@ module Crypto | |
| 40 39 | 
             
                  check_length(secret_key, SCALARBYTES, :SecretKey)
         | 
| 41 40 | 
             
                  check_length(public_key, BYTES, :PublicKey)
         | 
| 42 41 |  | 
| 43 | 
            -
                  shared_secret = Sodium::SecretBuffer.new(BYTES | 
| 42 | 
            +
                  shared_secret = Sodium::SecretBuffer.new(BYTES)
         | 
| 44 43 | 
             
                  secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 45 44 | 
             
                  crypto_scalarmult(shared_secret, secret_key, public_key)
         | 
| 46 45 | 
             
                  shared_secret.noaccess
         | 
| @@ -51,6 +50,8 @@ module Crypto | |
| 51 50 | 
             
                end
         | 
| 52 51 | 
             
              end
         | 
| 53 52 |  | 
| 53 | 
            +
              ScalarMult.freeze
         | 
| 54 | 
            +
             | 
| 54 55 | 
             
              module_function
         | 
| 55 56 |  | 
| 56 57 | 
             
              def scalarmut(*args)
         | 
    
        data/lib/crypto/secret_box.rb
    CHANGED
    
    | @@ -37,7 +37,6 @@ module Crypto | |
| 37 37 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 38 38 |  | 
| 39 39 | 
             
                  ciphertext = Sodium::Buffer.new(:uchar, message_len + MACBYTES)
         | 
| 40 | 
            -
                  ciphertext.primitive = PRIMITIVE
         | 
| 41 40 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 42 41 | 
             
                  crypto_secretbox_easy(ciphertext, message, message_len, nonce, key)
         | 
| 43 42 |  | 
| @@ -53,22 +52,21 @@ module Crypto | |
| 53 52 |  | 
| 54 53 | 
             
                  decrypted = Sodium::Buffer.new(:uchar, ciphertext_len - MACBYTES)
         | 
| 55 54 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 55 | 
            +
                  if crypto_secretbox_open_easy(decrypted, ciphertext, ciphertext_len, nonce, key) == 0
         | 
| 56 | 
            +
                    decrypted
         | 
| 57 | 
            +
                  else
         | 
| 58 58 | 
             
                    raise Sodium::CryptoError, "Message forged", caller
         | 
| 59 59 | 
             
                  end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                  decrypted
         | 
| 62 60 | 
             
                ensure
         | 
| 63 61 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 64 62 | 
             
                end
         | 
| 65 63 |  | 
| 66 64 | 
             
                def easy_in_place(data, nonce, key)
         | 
| 67 | 
            -
                  message =  | 
| 65 | 
            +
                  message = String(data)
         | 
| 68 66 | 
             
                  check_length(nonce, NONCEBYTES, :Nonce)
         | 
| 69 67 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 70 68 |  | 
| 71 | 
            -
                  message_len =  | 
| 69 | 
            +
                  message_len = message.bytesize
         | 
| 72 70 | 
             
                  message << zeros(MACBYTES)
         | 
| 73 71 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 74 72 | 
             
                  crypto_secretbox_easy(message, message, message_len, nonce, key)
         | 
| @@ -78,32 +76,35 @@ module Crypto | |
| 78 76 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 79 77 | 
             
                end
         | 
| 80 78 |  | 
| 81 | 
            -
                def open_easy_in_place(data, nonce, key,  | 
| 82 | 
            -
                  ciphertext =  | 
| 83 | 
            -
                   | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 79 | 
            +
                def open_easy_in_place(data, nonce, key, encoding = false)
         | 
| 80 | 
            +
                  ciphertext = String(data)
         | 
| 81 | 
            +
                  ciphertext_len = ciphertext.bytesize
         | 
| 82 | 
            +
                  if (message_len = ciphertext_len - MACBYTES) > 0
         | 
| 83 | 
            +
                    check_length(nonce, NONCEBYTES, :Nonce)
         | 
| 84 | 
            +
                    check_length(key, KEYBYTES, :SecretKey)
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 87 | 
            +
                    if crypto_secretbox_open_easy(ciphertext, ciphertext, ciphertext_len, nonce, key) == 0
         | 
| 88 | 
            +
                      if encoding
         | 
| 89 | 
            +
                        ciphertext.slice!(message_len..-1).force_encoding(encoding)
         | 
| 90 | 
            +
                      else
         | 
| 91 | 
            +
                        ciphertext.slice!(message_len..-1)
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                      ciphertext
         | 
| 95 | 
            +
                    else
         | 
| 96 | 
            +
                      raise Sodium::CryptoError, "Message forged", caller
         | 
| 97 | 
            +
                    end
         | 
| 97 98 | 
             
                  else
         | 
| 98 | 
            -
                     | 
| 99 | 
            +
                    fail Sodium::LengthError, "Ciphertext is too short", caller
         | 
| 99 100 | 
             
                  end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                  ciphertext
         | 
| 102 101 | 
             
                ensure
         | 
| 103 102 | 
             
                  key.noaccess if key.is_a?(Sodium::SecretBuffer)
         | 
| 104 103 | 
             
                end
         | 
| 105 104 | 
             
              end
         | 
| 106 105 |  | 
| 106 | 
            +
              SecretBox.freeze
         | 
| 107 | 
            +
             | 
| 107 108 | 
             
              module_function
         | 
| 108 109 |  | 
| 109 110 | 
             
              def secretbox(*args)
         | 
    
        data/lib/crypto/short_hash.rb
    CHANGED
    
    | @@ -26,7 +26,6 @@ module Crypto | |
| 26 26 | 
             
                  check_length(key, KEYBYTES, :SecretKey)
         | 
| 27 27 |  | 
| 28 28 | 
             
                  siphash = Sodium::Buffer.new(:uchar, BYTES)
         | 
| 29 | 
            -
                  siphash.primitive = PRIMITIVE
         | 
| 30 29 | 
             
                  key.readonly if key.is_a?(Sodium::SecretBuffer)
         | 
| 31 30 | 
             
                  crypto_shorthash(siphash, short_data, get_size(short_data), key)
         | 
| 32 31 |  | 
| @@ -36,6 +35,8 @@ module Crypto | |
| 36 35 | 
             
                end
         | 
| 37 36 | 
             
              end
         | 
| 38 37 |  | 
| 38 | 
            +
              ShortHash.freeze
         | 
| 39 | 
            +
             | 
| 39 40 | 
             
              module_function
         | 
| 40 41 |  | 
| 41 42 | 
             
              def shorthash(*args)
         | 
    
        data/lib/crypto/sign.rb
    CHANGED
    
    | @@ -33,9 +33,7 @@ module Crypto | |
| 33 33 |  | 
| 34 34 | 
             
                def keypair
         | 
| 35 35 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 36 | 
            -
                  public_key.primitive = PRIMITIVE
         | 
| 37 36 | 
             
                  secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
         | 
| 38 | 
            -
                  secret_key.primitive = PRIMITIVE
         | 
| 39 37 | 
             
                  crypto_sign_keypair(public_key, secret_key)
         | 
| 40 38 |  | 
| 41 39 | 
             
                  [public_key, secret_key]
         | 
| @@ -45,9 +43,7 @@ module Crypto | |
| 45 43 | 
             
                  check_length(seed, SEEDBYTES, :Seed)
         | 
| 46 44 |  | 
| 47 45 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 48 | 
            -
                  public_key.primitive = PRIMITIVE
         | 
| 49 46 | 
             
                  secret_key = Sodium::Buffer.new(:uchar, SECRETKEYBYTES)
         | 
| 50 | 
            -
                  secret_key.primitive = PRIMITIVE
         | 
| 51 47 | 
             
                  seed.readonly if seed.is_a?(Sodium::SecretBuffer)
         | 
| 52 48 | 
             
                  crypto_sign_seed_keypair(public_key, secret_key, seed)
         | 
| 53 49 |  | 
| @@ -58,8 +54,7 @@ module Crypto | |
| 58 54 |  | 
| 59 55 | 
             
                def memory_locked_keypair
         | 
| 60 56 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 61 | 
            -
                   | 
| 62 | 
            -
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
         | 
| 57 | 
            +
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
         | 
| 63 58 | 
             
                  crypto_sign_keypair(public_key, secret_key)
         | 
| 64 59 | 
             
                  secret_key.noaccess
         | 
| 65 60 |  | 
| @@ -70,8 +65,7 @@ module Crypto | |
| 70 65 | 
             
                  check_length(seed, SEEDBYTES, :Seed)
         | 
| 71 66 |  | 
| 72 67 | 
             
                  public_key = Sodium::Buffer.new(:uchar, PUBLICKEYBYTES)
         | 
| 73 | 
            -
                   | 
| 74 | 
            -
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES, PRIMITIVE)
         | 
| 68 | 
            +
                  secret_key = Sodium::SecretBuffer.new(SECRETKEYBYTES)
         | 
| 75 69 | 
             
                  seed.readonly if seed.is_a?(Sodium::SecretBuffer)
         | 
| 76 70 | 
             
                  crypto_sign_seed_keypair(public_key, secret_key, seed)
         | 
| 77 71 | 
             
                  secret_key.noaccess
         | 
| @@ -86,7 +80,6 @@ module Crypto | |
| 86 80 | 
             
                  check_length(secret_key, SECRETKEYBYTES, :SecretKey)
         | 
| 87 81 |  | 
| 88 82 | 
             
                  sealed_message = Sodium::Buffer.new(:uchar, message_len + BYTES)
         | 
| 89 | 
            -
                  sealed_message.primitive = PRIMITIVE
         | 
| 90 83 | 
             
                  secret_key.readonly if secret_key.is_a?(Sodium::SecretBuffer)
         | 
| 91 84 | 
             
                  crypto_sign(sealed_message, nil, message, message_len, secret_key)
         | 
| 92 85 |  | 
| @@ -100,15 +93,17 @@ module Crypto | |
| 100 93 | 
             
                  check_length(public_key, PUBLICKEYBYTES, :PublicKey)
         | 
| 101 94 |  | 
| 102 95 | 
             
                  unsealed_message = Sodium::Buffer.new(:uchar, sealed_message_len - BYTES)
         | 
| 103 | 
            -
                  unsealed_message_len = FFI::MemoryPointer.new(: | 
| 104 | 
            -
                   | 
| 96 | 
            +
                  unsealed_message_len = FFI::MemoryPointer.new(:ulong_long)
         | 
| 97 | 
            +
                  if crypto_sign_open(unsealed_message, unsealed_message_len, sealed_message, sealed_message_len, public_key) == 0
         | 
| 98 | 
            +
                    unsealed_message
         | 
| 99 | 
            +
                  else
         | 
| 105 100 | 
             
                    raise Sodium::CryptoError, "Incorrect signature", caller
         | 
| 106 101 | 
             
                  end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                  unsealed_message
         | 
| 109 102 | 
             
                end
         | 
| 110 103 | 
             
              end
         | 
| 111 104 |  | 
| 105 | 
            +
              Sign.freeze
         | 
| 106 | 
            +
             | 
| 112 107 | 
             
              module_function
         | 
| 113 108 |  | 
| 114 109 | 
             
              def sign(*args)
         | 
    
        data/lib/crypto/sign/ed25519.rb
    CHANGED
    
    
    
        data/lib/libsodium.rb
    CHANGED
    
    | @@ -2,19 +2,22 @@ | |
| 2 2 | 
             
            require_relative 'sodium'
         | 
| 3 3 | 
             
            require_relative 'sodium/utils'
         | 
| 4 4 | 
             
            require_relative 'sodium/buffer'
         | 
| 5 | 
            +
            require_relative 'sodium/mprotect'
         | 
| 5 6 | 
             
            require_relative 'sodium/secret_buffer'
         | 
| 7 | 
            +
            Sodium.freeze
         | 
| 6 8 | 
             
            require_relative 'random_bytes'
         | 
| 7 9 | 
             
            require_relative 'crypto/secret_box'
         | 
| 8 10 | 
             
            require_relative 'crypto/auth'
         | 
| 9 11 | 
             
            require_relative 'crypto/aead/chacha20_poly1305'
         | 
| 10 12 | 
             
            require_relative 'crypto/box'
         | 
| 13 | 
            +
            require_relative 'crypto/sign/ed25519'
         | 
| 11 14 | 
             
            require_relative 'crypto/sign'
         | 
| 12 15 | 
             
            require_relative 'crypto/generic_hash'
         | 
| 13 16 | 
             
            require_relative 'crypto/short_hash'
         | 
| 14 17 | 
             
            require_relative 'crypto/pw_hash/scrypt_salsa208_sha256'
         | 
| 15 18 | 
             
            require_relative 'crypto/one_time_auth'
         | 
| 16 19 | 
             
            require_relative 'crypto/scalar_mult'
         | 
| 17 | 
            -
             | 
| 20 | 
            +
            Crypto.freeze
         | 
| 18 21 |  | 
| 19 22 | 
             
            Thread.exclusive do
         | 
| 20 23 | 
             
              if Sodium.init == -1
         | 
    
        data/lib/random_bytes.rb
    CHANGED
    
    
    
        data/lib/sodium.rb
    CHANGED
    
    | @@ -16,53 +16,22 @@ module Sodium | |
| 16 16 | 
             
              attach_function :sodium_munlock,            [:pointer, :size_t],  :int
         | 
| 17 17 | 
             
              attach_function :sodium_malloc,             [:size_t],            :pointer
         | 
| 18 18 | 
             
              attach_function :sodium_allocarray,         [:size_t, :size_t],   :pointer
         | 
| 19 | 
            -
              attach_function :sodium_mprotect_noaccess,  [:pointer],           :int
         | 
| 20 | 
            -
              attach_function :sodium_mprotect_readonly,  [:pointer],           :int
         | 
| 21 | 
            -
              attach_function :sodium_mprotect_readwrite, [:pointer],           :int
         | 
| 22 19 |  | 
| 23 20 | 
             
              module_function
         | 
| 24 21 |  | 
| 25 22 | 
             
              def mlock(addr, len)
         | 
| 26 | 
            -
                 | 
| 27 | 
            -
                  raise MemoryError, "Could not lock length=#{len} bytes memory at address=#{addr.address}", caller
         | 
| 28 | 
            -
                end
         | 
| 23 | 
            +
                sodium_mlock(addr, len) == 0 || raise(MemoryError, "Could not lock length=#{len} bytes memory at address=#{addr.address}", caller)
         | 
| 29 24 | 
             
              end
         | 
| 30 25 |  | 
| 31 26 | 
             
              def munlock(addr, len)
         | 
| 32 | 
            -
                 | 
| 33 | 
            -
                  raise MemoryError, "Could not unlock length=#{len} bytes memory at address=#{addr.address}", caller
         | 
| 34 | 
            -
                end
         | 
| 27 | 
            +
                sodium_munlock(addr, len) == 0 || raise(MemoryError, "Could not unlock length=#{len} bytes memory at address=#{addr.address}", caller)
         | 
| 35 28 | 
             
              end
         | 
| 36 29 |  | 
| 37 30 | 
             
              def malloc(size)
         | 
| 38 | 
            -
                 | 
| 39 | 
            -
                  raise NoMemoryError, "Failed to allocate memory size=#{size} bytes", caller
         | 
| 40 | 
            -
                end
         | 
| 41 | 
            -
                mem
         | 
| 31 | 
            +
                sodium_malloc(size) || raise(NoMemoryError, "Failed to allocate memory size=#{size} bytes", caller)
         | 
| 42 32 | 
             
              end
         | 
| 43 33 |  | 
| 44 34 | 
             
              def allocarray(count, size)
         | 
| 45 | 
            -
                 | 
| 46 | 
            -
                  raise NoMemoryError, "Failed to allocate memory size=#{count * size} bytes", caller
         | 
| 47 | 
            -
                end
         | 
| 48 | 
            -
                mem
         | 
| 49 | 
            -
              end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
              def noaccess(ptr)
         | 
| 52 | 
            -
                unless sodium_mprotect_noaccess(ptr).zero?
         | 
| 53 | 
            -
                  raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
              end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
              def readonly(ptr)
         | 
| 58 | 
            -
                unless sodium_mprotect_readonly(ptr).zero?
         | 
| 59 | 
            -
                  raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
              end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
              def readwrite(ptr)
         | 
| 64 | 
            -
                unless sodium_mprotect_readwrite(ptr).zero?
         | 
| 65 | 
            -
                  raise MemoryError, "Memory at address=#{ptr.address} is not secured with #{self}.malloc", caller
         | 
| 66 | 
            -
                end
         | 
| 35 | 
            +
                sodium_allocarray(count, size) || raise(NoMemoryError, "Failed to allocate memory size=#{count * size} bytes", caller)
         | 
| 67 36 | 
             
              end
         | 
| 68 37 | 
             
            end
         | 
    
        data/lib/sodium/buffer.rb
    CHANGED
    
    
    
        data/lib/sodium/errors.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            module Sodium
         | 
| 2 | 
            -
               | 
| 3 | 
            -
               | 
| 4 | 
            -
               | 
| 2 | 
            +
              CryptoError = Class.new(StandardError).freeze
         | 
| 3 | 
            +
              LengthError = Class.new(ArgumentError).freeze
         | 
| 4 | 
            +
              MemoryError = Class.new(StandardError).freeze
         | 
| 5 5 | 
             
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            require 'ffi'
         | 
| 2 | 
            +
            require_relative 'errors'
         | 
| 3 | 
            +
            require_relative 'utils'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Sodium
         | 
| 6 | 
            +
              module Mprotect
         | 
| 7 | 
            +
                extend FFI::Library
         | 
| 8 | 
            +
                ffi_lib :libsodium
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attach_function :sodium_mprotect_noaccess,  [:pointer], :int
         | 
| 11 | 
            +
                attach_function :sodium_mprotect_readonly,  [:pointer], :int
         | 
| 12 | 
            +
                attach_function :sodium_mprotect_readwrite, [:pointer], :int
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                module_function
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def noaccess(ptr)
         | 
| 17 | 
            +
                  sodium_mprotect_noaccess(ptr) == 0 || raise(MemoryError, "Memory at address=#{ptr.address} is not secured with Sodium.malloc", caller)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def readonly(ptr)
         | 
| 21 | 
            +
                  sodium_mprotect_readonly(ptr) == 0 || raise(MemoryError, "Memory at address=#{ptr.address} is not secured with Sodium.malloc", caller)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def readwrite(ptr)
         | 
| 25 | 
            +
                  sodium_mprotect_readwrite(ptr) == 0 || raise(MemoryError, "Memory at address=#{ptr.address} is not secured with Sodium.malloc", caller)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              Mprotect.freeze
         | 
| 30 | 
            +
            end
         | 
    
        data/lib/sodium/secret_buffer.rb
    CHANGED
    
    | @@ -1,58 +1,61 @@ | |
| 1 1 | 
             
            require 'forwardable'
         | 
| 2 | 
            -
            require_relative 'utils'
         | 
| 3 2 | 
             
            require_relative '../sodium'
         | 
| 3 | 
            +
            require_relative 'mprotect'
         | 
| 4 4 | 
             
            require 'ffi'
         | 
| 5 5 |  | 
| 6 6 | 
             
            module Sodium
         | 
| 7 7 | 
             
              class SecretBuffer
         | 
| 8 8 | 
             
                extend Forwardable
         | 
| 9 9 |  | 
| 10 | 
            -
                attr_reader :size, : | 
| 11 | 
            -
                def_delegators  | 
| 10 | 
            +
                attr_reader :size, :to_ptr
         | 
| 11 | 
            +
                def_delegators :@to_ptr, :address, :to_i
         | 
| 12 12 |  | 
| 13 | 
            -
                def initialize(size | 
| 14 | 
            -
                  @size =  | 
| 15 | 
            -
                  @ | 
| 16 | 
            -
                  @to_ptr = Sodium.malloc(self.size)
         | 
| 13 | 
            +
                def initialize(size)
         | 
| 14 | 
            +
                  @size = Integer(size)
         | 
| 15 | 
            +
                  @to_ptr = Sodium.malloc(@size)
         | 
| 17 16 | 
             
                  setup_finalizer
         | 
| 18 17 | 
             
                end
         | 
| 19 18 |  | 
| 20 19 | 
             
                def free
         | 
| 21 20 | 
             
                  remove_finalizer
         | 
| 22 | 
            -
                   | 
| 23 | 
            -
                  Sodium.free(to_ptr)
         | 
| 24 | 
            -
                   | 
| 21 | 
            +
                  Sodium::Mprotect.readonly(@to_ptr)
         | 
| 22 | 
            +
                  Sodium.free(@to_ptr)
         | 
| 23 | 
            +
                  remove_instance_variable(:@size)
         | 
| 24 | 
            +
                  remove_instance_variable(:@to_ptr)
         | 
| 25 | 
            +
                  true
         | 
| 25 26 | 
             
                end
         | 
| 26 27 |  | 
| 27 28 | 
             
                def noaccess
         | 
| 28 | 
            -
                  Sodium.noaccess(to_ptr)
         | 
| 29 | 
            +
                  Sodium::Mprotect.noaccess(@to_ptr)
         | 
| 29 30 | 
             
                end
         | 
| 30 31 |  | 
| 31 32 | 
             
                def readonly
         | 
| 32 | 
            -
                  Sodium.readonly(to_ptr)
         | 
| 33 | 
            +
                  Sodium::Mprotect.readonly(@to_ptr)
         | 
| 33 34 | 
             
                end
         | 
| 34 35 |  | 
| 35 36 | 
             
                def readwrite
         | 
| 36 | 
            -
                  Sodium.readwrite(to_ptr)
         | 
| 37 | 
            +
                  Sodium::Mprotect.readwrite(@to_ptr)
         | 
| 37 38 | 
             
                end
         | 
| 38 39 |  | 
| 39 40 | 
             
                private
         | 
| 40 41 |  | 
| 41 42 | 
             
                def setup_finalizer
         | 
| 42 | 
            -
                  ObjectSpace.define_finalizer(to_ptr, self.class.free(to_ptr.address))
         | 
| 43 | 
            +
                  ObjectSpace.define_finalizer(@to_ptr, self.class.free(@to_ptr.address))
         | 
| 43 44 | 
             
                end
         | 
| 44 45 |  | 
| 45 46 | 
             
                def remove_finalizer
         | 
| 46 | 
            -
                  ObjectSpace.undefine_finalizer to_ptr
         | 
| 47 | 
            +
                  ObjectSpace.undefine_finalizer @to_ptr
         | 
| 47 48 | 
             
                end
         | 
| 48 49 |  | 
| 49 50 | 
             
                def self.free(address)
         | 
| 50 51 | 
             
                  ->(obj_id) do
         | 
| 51 52 | 
             
                    ptr = FFI::Pointer.new(address)
         | 
| 52 | 
            -
                    Sodium. | 
| 53 | 
            +
                    Sodium::Mprotect.readonly(ptr)
         | 
| 53 54 | 
             
                    Sodium.free(ptr)
         | 
| 54 55 | 
             
                    true
         | 
| 55 56 | 
             
                  end
         | 
| 56 57 | 
             
                end
         | 
| 57 58 | 
             
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              SecretBuffer.freeze
         | 
| 58 61 | 
             
            end
         | 
    
        data/lib/sodium/utils.rb
    CHANGED
    
    | @@ -1,68 +1,41 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 1 | 
            +
            require 'ffi'
         | 
| 2 | 
            +
            require_relative 'secret_buffer'
         | 
| 3 | 
            +
            require_relative 'errors'
         | 
| 3 4 |  | 
| 4 5 | 
             
            module Sodium
         | 
| 5 6 | 
             
              module Utils
         | 
| 6 7 |  | 
| 7 8 | 
             
                module_function
         | 
| 8 9 |  | 
| 9 | 
            -
                def  | 
| 10 | 
            -
                   | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
                    end
         | 
| 18 | 
            -
                  else
         | 
| 19 | 
            -
                    fail ArgumentError, "#{description} must be of type String or FFI::Pointer and be length=#{length} bytes long", caller
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  true
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                def get_pointer(ptr)
         | 
| 26 | 
            -
                  if ptr.is_a?(FFI::Pointer)
         | 
| 27 | 
            -
                    ptr
         | 
| 28 | 
            -
                  elsif ptr.respond_to?(:to_ptr)
         | 
| 29 | 
            -
                    ptr.to_ptr
         | 
| 30 | 
            -
                  else
         | 
| 31 | 
            -
                    fail ArgumentError, "#{ptr.class} is not a FFI::Pointer", caller
         | 
| 32 | 
            -
                  end
         | 
| 33 | 
            -
                end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                def get_string(string)
         | 
| 36 | 
            -
                  if string.is_a?(String)
         | 
| 37 | 
            -
                    string
         | 
| 38 | 
            -
                  elsif string.respond_to?(:to_str)
         | 
| 39 | 
            -
                    string.to_str
         | 
| 40 | 
            -
                  elsif string.respond_to?(:get_string)
         | 
| 41 | 
            -
                    string.get_string(0)
         | 
| 42 | 
            -
                  else
         | 
| 43 | 
            -
                    fail ArgumentError, "#{string.class} is not a String", caller
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                def get_int(int)
         | 
| 48 | 
            -
                  if int.is_a?(Fixnum)
         | 
| 49 | 
            -
                    int
         | 
| 50 | 
            -
                  elsif int.respond_to?(:to_int)
         | 
| 51 | 
            -
                    int.to_int
         | 
| 10 | 
            +
                def get_size(data)
         | 
| 11 | 
            +
                  case data
         | 
| 12 | 
            +
                  when FFI::Pointer, SecretBuffer
         | 
| 13 | 
            +
                    data.size
         | 
| 14 | 
            +
                  when String
         | 
| 15 | 
            +
                    data.bytesize
         | 
| 16 | 
            +
                  when NilClass
         | 
| 17 | 
            +
                    0
         | 
| 52 18 | 
             
                  else
         | 
| 53 | 
            -
                    fail  | 
| 19 | 
            +
                    fail TypeError, "#{data.class} must be of type FFI::Pointer, Sodium::SecretBufffer, String or NilClass", caller
         | 
| 54 20 | 
             
                  end
         | 
| 55 21 | 
             
                end
         | 
| 56 22 |  | 
| 57 | 
            -
                def  | 
| 58 | 
            -
                   | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 23 | 
            +
                def check_length(data, length, description)
         | 
| 24 | 
            +
                  case data
         | 
| 25 | 
            +
                  when FFI::Pointer, SecretBuffer
         | 
| 26 | 
            +
                    if data.size == length
         | 
| 27 | 
            +
                      true
         | 
| 28 | 
            +
                    else
         | 
| 29 | 
            +
                      fail LengthError, "Expected a length=#{length} bytes #{description}, got size=#{data.size} bytes", caller
         | 
| 30 | 
            +
                    end
         | 
| 31 | 
            +
                  when String
         | 
| 32 | 
            +
                    if data.bytesize == length
         | 
| 33 | 
            +
                      true
         | 
| 34 | 
            +
                    else
         | 
| 35 | 
            +
                      fail LengthError, "Expected a length=#{length} bytes #{description}, got size=#{data.bytesize} bytes", caller
         | 
| 36 | 
            +
                    end
         | 
| 64 37 | 
             
                  else
         | 
| 65 | 
            -
                    fail  | 
| 38 | 
            +
                    fail TypeError, "#{data.class} must be of type FFI::Pointer, Sodium::SecretBufffer or String", caller
         | 
| 66 39 | 
             
                  end
         | 
| 67 40 | 
             
                end
         | 
| 68 41 |  | 
| @@ -82,4 +55,6 @@ module Sodium | |
| 82 55 | 
             
                  [hex].pack(HEXY)
         | 
| 83 56 | 
             
                end
         | 
| 84 57 | 
             
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              Utils.freeze
         | 
| 85 60 | 
             
            end
         | 
    
        data/lib/sodium/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: ffi-libsodium
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Hendrik Beskow
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014-12- | 
| 11 | 
            +
            date: 2014-12-15 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: ffi
         | 
| @@ -62,6 +62,7 @@ files: | |
| 62 62 | 
             
            - lib/sodium.rb
         | 
| 63 63 | 
             
            - lib/sodium/buffer.rb
         | 
| 64 64 | 
             
            - lib/sodium/errors.rb
         | 
| 65 | 
            +
            - lib/sodium/mprotect.rb
         | 
| 65 66 | 
             
            - lib/sodium/secret_buffer.rb
         | 
| 66 67 | 
             
            - lib/sodium/utils.rb
         | 
| 67 68 | 
             
            - lib/sodium/version.rb
         |