Class: Pdfrb::Encryption::StandardSecurityHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/encryption/standard_security_handler.rb

Constant Summary collapse

PAD =
String.new("\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08" \
"\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A",
encoding: Encoding::BINARY).freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(trailer_dict) ⇒ StandardSecurityHandler

Returns a new instance of StandardSecurityHandler.



14
15
16
17
18
19
20
21
22
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 14

def initialize(trailer_dict)
  @encrypt = trailer_dict[:Encrypt]
  @id = trailer_dict[:ID]
  @version = (@encrypt[:V] || 0).to_i
  @revision = (@encrypt[:R] || 3).to_i
  @key_length = (@encrypt[:Length] || 40).to_i / 8
  @permissions = (@encrypt[:P] || -1).to_i
  @key = nil
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



12
13
14
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 12

def key
  @key
end

#key_lengthObject (readonly)

Returns the value of attribute key_length.



12
13
14
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 12

def key_length
  @key_length
end

#permissionsObject (readonly)

Returns the value of attribute permissions.



12
13
14
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 12

def permissions
  @permissions
end

#revisionObject (readonly)

Returns the value of attribute revision.



12
13
14
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 12

def revision
  @revision
end

#versionObject (readonly)

Returns the value of attribute version.



12
13
14
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 12

def version
  @version
end

Instance Method Details

#compute_encryption_key(password) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 30

def compute_encryption_key(password)
  padded = pad_password(password)
  owner_hash = @encrypt[:O] || String.new("", encoding: Encoding::BINARY)
  perms = [@permissions].pack("V")
  id_first = id_bytes

  md5 = Digest::MD5.new
  md5.update(padded)
  md5.update(owner_hash)
  md5.update(perms)
  md5.update(id_first)

  if @revision >= 4
    md5.update(@encrypt[:UE] || "")
    md5.update(@encrypt[:Perms] ? [@encrypt[:Perms]].pack("N") : "")
  end

  hash = md5.digest

  if @revision >= 3
    50.times { hash = Digest::MD5.digest(hash[0, @key_length]) }
  end

  hash[0, @key_length]
end

#compute_object_key(oid, gen) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 56

def compute_object_key(oid, gen)
  md5 = Digest::MD5.new
  md5.update(@key)
  md5.update([oid].pack("V"))
  md5.update([gen].pack("v"))

  if @version >= 4
    md5.update("\xAA")
  end

  md5.digest[0, [@key_length + 5, 16].min]
end

#decrypt_data(data, oid, gen) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 86

def decrypt_data(data, oid, gen)
  return data unless @key

  obj_key = compute_object_key(oid, gen)

  if @version >= 4
    decrypt_aes_cbc(data, obj_key)
  else
    decrypt_rc4(data, obj_key)
  end
end

#encrypt_data(data, oid, gen) ⇒ Object Also known as: encrypt



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 69

def encrypt_data(data, oid, gen)
  return data unless @key

  obj_key = compute_object_key(oid, gen)

  if @version >= 4
    encrypt_aes_cbc(data, obj_key)
  else
    encrypt_rc4(data, obj_key)
  end
end

#verify_user_password?(password) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
# File 'lib/pdfrb/encryption/standard_security_handler.rb', line 24

def verify_user_password?(password)
  computed = compute_encryption_key(password)
  @key = computed
  verify_user_password_hash?(computed)
end