class PDF::Reader::StandardSecurityHandlerV5
class creates interface to encrypt dictionary for use in Decrypt
Attributes
encrypt_key[R]
key_length[R]
Public Class Methods
new(opts = {})
click to toggle source
# File lib/pdf/reader/standard_security_handler_v5.rb, line 11 def initialize(opts = {}) @key_length = 256 @O = opts[:O] # hash(32B) + validation salt(8B) + key salt(8B) @U = opts[:U] # hash(32B) + validation salt(8B) + key salt(8B) @OE = opts[:OE] # decryption key, encrypted w/ owner password @UE = opts[:UE] # decryption key, encrypted w/ user password @encrypt_key = build_standard_key(opts[:password] || '') end
supports?(encrypt)
click to toggle source
This handler supports AES-256 encryption defined in PDF 1.7 Extension Level 3
# File lib/pdf/reader/standard_security_handler_v5.rb, line 21 def self.supports?(encrypt) return false if encrypt.nil? filter = encrypt.fetch(:Filter, :Standard) version = encrypt.fetch(:V, 0) revision = encrypt.fetch(:R, 0) algorithm = encrypt.fetch(:CF, {}).fetch(encrypt[:StmF], {}).fetch(:CFM, nil) (filter == :Standard) && (encrypt[:StmF] == encrypt[:StrF]) && ((version == 5) && (revision == 5) && (algorithm == :AESV3)) end
Public Instance Methods
decrypt( buf, ref )
click to toggle source
7.6.2 General Encryption Algorithm
Algorithm 1: Encryption of data using the RC4 or AES algorithms
used to decrypt RC4/AES encrypted PDF streams (buf)
buf - a string to decrypt ref - a PDF::Reader::Reference for the object to decrypt
# File lib/pdf/reader/standard_security_handler_v5.rb, line 41 def decrypt( buf, ref ) cipher = OpenSSL::Cipher.new("AES-#{@key_length}-CBC") cipher.decrypt cipher.key = @encrypt_key.dup cipher.iv = buf[0..15] cipher.update(buf[16..-1]) + cipher.final end
Private Instance Methods
auth_owner_pass(password)
click to toggle source
Algorithm 3.2a - Computing an encryption key
Defined in PDF 1.7 Extension Level 3
if the string is a valid user/owner password, this will return the decryption key
# File lib/pdf/reader/standard_security_handler_v5.rb, line 56 def auth_owner_pass(password) if Digest::SHA256.digest(password + @O[32..39] + @U) == @O[0..31] cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.decrypt cipher.key = Digest::SHA256.digest(password + @O[40..-1] + @U) cipher.iv = "\x00" * 16 cipher.padding = 0 cipher.update(@OE) + cipher.final end end
auth_user_pass(password)
click to toggle source
# File lib/pdf/reader/standard_security_handler_v5.rb, line 67 def auth_user_pass(password) if Digest::SHA256.digest(password + @U[32..39]) == @U[0..31] cipher = OpenSSL::Cipher.new('AES-256-CBC') cipher.decrypt cipher.key = Digest::SHA256.digest(password + @U[40..-1]) cipher.iv = "\x00" * 16 cipher.padding = 0 cipher.update(@UE) + cipher.final end end
build_standard_key(pass)
click to toggle source
# File lib/pdf/reader/standard_security_handler_v5.rb, line 78 def build_standard_key(pass) pass = pass.byteslice(0...127) # UTF-8 encoded password. first 127 bytes encrypt_key = auth_owner_pass(pass) encrypt_key ||= auth_user_pass(pass) raise PDF::Reader::EncryptedPDFError, "Invalid password (#{pass})" if encrypt_key.nil? encrypt_key end