lib/lockbox.rb in lockbox-0.2.0 vs lib/lockbox.rb in lockbox-0.2.1
- old
+ new
@@ -20,10 +20,11 @@
end
class Lockbox
class Error < StandardError; end
class DecryptionError < Error; end
+ class PaddingError < Error; end
class << self
attr_accessor :default_options
attr_writer :master_key
end
@@ -135,9 +136,58 @@
key
end
def self.to_hex(str)
str.unpack("H*").first
+ end
+
+ PAD_FIRST_BYTE = "\x80".b
+ PAD_ZERO_BYTE = "\x00".b
+
+ # ISO/IEC 7816-4
+ # same as Libsodium
+ # https://libsodium.gitbook.io/doc/padding
+ # apply prior to encryption
+ # note: current implementation does not
+ # try to minimize side channels
+ def self.pad(str, size: 16)
+ raise ArgumentError, "Invalid size" if size < 1
+
+ str = str.dup.force_encoding(Encoding::BINARY)
+
+ pad_length = size - 1
+ pad_length -= str.bytesize % size
+
+ str << PAD_FIRST_BYTE
+ pad_length.times do
+ str << PAD_ZERO_BYTE
+ end
+
+ str
+ end
+
+ # note: current implementation does not
+ # try to minimize side channels
+ def self.unpad(str, size: 16)
+ raise ArgumentError, "Invalid size" if size < 1
+
+ if str.encoding != Encoding::BINARY
+ str = str.dup.force_encoding(Encoding::BINARY)
+ end
+
+ i = 1
+ while i <= size
+ case str[-i]
+ when PAD_ZERO_BYTE
+ i += 1
+ when PAD_FIRST_BYTE
+ return str[0..-(i + 1)]
+ else
+ break
+ end
+ end
+
+ raise Lockbox::PaddingError, "Invalid padding"
end
private
def check_string(str, name)