lib/hexapdf/encryption/security_handler.rb in hexapdf-0.5.0 vs lib/hexapdf/encryption/security_handler.rb in hexapdf-0.6.0
- old
+ new
@@ -130,10 +130,36 @@
# encryption_dictionary_class::
# Returns the class that is used for the encryption dictionary. Should be derived from the
# EncryptionDictionary class.
class SecurityHandler
+ # Provides additional encryption specific information for HexaPDF::StreamData objects.
+ class EncryptedStreamData < StreamData
+
+ # The encryption key.
+ attr_reader :key
+
+ # The encryption algorithm.
+ attr_reader :algorithm
+
+ # Creates a new encrypted stream data object by utilizing the given stream data object as
+ # template. The arguments +key+ and +algorithm+ are used for decrypting purposes.
+ def initialize(obj, key, algorithm)
+ obj.instance_variables.each {|v| instance_variable_set(v, obj.instance_variable_get(v))}
+ @key = key
+ @algorithm = algorithm
+ end
+
+ alias :undecrypted_fiber :fiber
+
+ # Returns a fiber like HexaPDF::StreamData#fiber, but one wrapped in a decrypting fiber.
+ def fiber(*args)
+ @algorithm.decryption_fiber(@key, super(*args))
+ end
+
+ end
+
# :call-seq:
# SecurityHandler.set_up_encryption(document, handler_name, **options) -> handler
#
# Sets up and returns the security handler with the specified name for the document and
# modifies then document's encryption dictionary accordingly.
@@ -141,12 +167,12 @@
# The +encryption_opts+ can contain any encryption options for the specific security handler
# and the common encryption options.
#
# See: #set_up_encryption (for the common encryption options).
def self.set_up_encryption(document, handler_name, **options)
- handler = GlobalConfiguration.constantize('encryption.filter_map', handler_name) do
- GlobalConfiguration.constantize('encryption.sub_filter_map', handler_name) do
+ handler = document.config.constantize('encryption.filter_map', handler_name) do
+ document.config.constantize('encryption.sub_filter_map', handler_name) do
raise HexaPDF::EncryptionError, "Could not find the specified security handler"
end
end
handler = handler.new(document)
@@ -168,12 +194,12 @@
def self.set_up_decryption(document, **options)
dict = document.trailer[:Encrypt]
if dict.nil?
raise HexaPDF::EncryptionError, "No /Encrypt dictionary found"
end
- handler = HexaPDF::GlobalConfiguration.constantize('encryption.filter_map', dict[:Filter]) do
- HexaPDF::GlobalConfiguration.constantize('encryption.sub_filter_map', dict[:SubFilter]) do
+ handler = document.config.constantize('encryption.filter_map', dict[:Filter]) do
+ document.config.constantize('encryption.sub_filter_map', dict[:SubFilter]) do
raise HexaPDF::EncryptionError, "Could not find a suitable security handler"
end
end
handler = handler.new(document)
@@ -235,12 +261,11 @@
if obj.kind_of?(HexaPDF::Stream)
unless string_algorithm == stream_algorithm
key = object_key(obj.oid, obj.gen, stream_algorithm)
end
- obj.raw_stream.filter.unshift(:Encryption)
- obj.raw_stream.decode_parms.unshift(key: key, algorithm: stream_algorithm)
+ obj.data.stream = EncryptedStreamData.new(obj.raw_stream, key, stream_algorithm)
end
obj
end
@@ -257,11 +282,18 @@
# Returns a Fiber that encrypts the contents of the given stream object.
def encrypt_stream(obj)
return obj.stream_encoder if obj.type == :XRef
key = object_key(obj.oid, obj.gen, stream_algorithm)
- obj.stream_encoder(:Encryption, key: key, algorithm: stream_algorithm)
+ source = obj.stream_source
+ result = obj.stream_encoder(source)
+ if result == source && obj.raw_stream.kind_of?(EncryptedStreamData) &&
+ obj.raw_stream.key == key && obj.raw_stream.algorithm == stream_algorithm
+ obj.raw_stream.undecrypted_fiber
+ else
+ stream_algorithm.encryption_fiber(key, result)
+ end
end
# Computes the encryption key and sets up the algorithms for encrypting the document based on
# the given options, and returns the corresponding encryption dictionary.
#
@@ -418,15 +450,15 @@
}
end
# Returns the class that is used for ARC4 encryption.
def arc4_algorithm
- @arc4_algorithm ||= HexaPDF::GlobalConfiguration.constantize('encryption.arc4')
+ @arc4_algorithm ||= document.config.constantize('encryption.arc4')
end
# Returns the class that is used for AES encryption.
def aes_algorithm
- @aes_algorithm ||= HexaPDF::GlobalConfiguration.constantize('encryption.aes')
+ @aes_algorithm ||= document.config.constantize('encryption.aes')
end
# Returns the class that is used for the identity algorithm which passes back the data as is
# without encrypting or decrypting it.
def identity_algorithm