Method: Origami::PDF#decrypt
- Defined in:
- lib/origami/encryption.rb
#decrypt(passwd = "") ⇒ Object
Decrypts the current document (only RC4 40..128 bits).
- passwd
-
The password to decrypt the document.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/origami/encryption.rb', line 55 def decrypt(passwd = "") raise EncryptionError, "PDF is not encrypted" unless self.encrypted? encrypt_dict = trailer_key(:Encrypt) handler = Encryption::Standard::Dictionary.new(encrypt_dict.dup) unless handler.Filter == :Standard raise EncryptionNotSupportedError, "Unknown security handler : '#{handler.Filter.to_s}'" end crypt_filters = { Identity: Encryption::Identity } case handler.V.to_i when 1,2 crypt_filters = Hash.new(Encryption::RC4) string_filter = stream_filter = nil when 4,5 crypt_filters = { Identity: Encryption::Identity } if handler[:CF].is_a?(Dictionary) handler[:CF].each_pair do |name, cf| next unless cf.is_a?(Dictionary) crypt_filters[name.value] = if cf[:CFM] == :V2 then Encryption::RC4 elsif cf[:CFM] == :AESV2 then Encryption::AES elsif cf[:CFM] == :None then Encryption::Identity elsif cf[:CFM] == :AESV3 and handler.V.to_i == 5 then Encryption::AES else raise EncryptionNotSupportedError, "Unsupported encryption version : #{handler.V}" end end end string_filter = handler.StrF.is_a?(Name) ? handler.StrF.value : :Identity stream_filter = handler.StmF.is_a?(Name) ? handler.StmF.value : :Identity unless crypt_filters.key?(string_filter) raise EncryptionError, "Invalid StrF value in encryption dictionary" end unless crypt_filters.key?(stream_filter) raise EncryptionError, "Invalid StmF value in encryption dictionary" end else raise EncryptionNotSupportedError, "Unsupported encryption version : #{handler.V}" end doc_id = trailer_key(:ID) unless doc_id.is_a?(Array) raise EncryptionError, "Document ID was not found or is invalid" unless handler.V.to_i == 5 else doc_id = doc_id.first end if handler.is_user_password?(passwd, doc_id) encryption_key = handler.compute_user_encryption_key(passwd, doc_id) elsif handler.is_owner_password?(passwd, doc_id) if handler.V.to_i < 5 user_passwd = handler.retrieve_user_password(passwd) encryption_key = handler.compute_user_encryption_key(user_passwd, doc_id) else encryption_key = handler.compute_owner_encryption_key(passwd) end else raise EncryptionInvalidPasswordError end = (handler.EncryptMetadata != false) self.extend(Encryption::EncryptedDocument) self.encryption_handler = handler self.crypt_filters = crypt_filters self.encryption_key = encryption_key self.stm_filter, self.str_filter = stream_filter, string_filter # # Should be fixed to exclude only the active XRefStream # = self.Catalog.Metadata self.indirect_objects.each do |indobj| encrypted_objects = [] case indobj when String,Stream then encrypted_objects << indobj when Dictionary,Array then encrypted_objects |= indobj.strings_cache end encrypted_objects.each do |obj| case obj when String next if obj.equal?(encrypt_dict[:U]) or obj.equal?(encrypt_dict[:O]) or obj.equal?(encrypt_dict[:UE]) or obj.equal?(encrypt_dict[:OE]) or obj.equal?(encrypt_dict[:Perms]) or (obj.parent.is_a?(Signature::DigitalSignature) and obj.equal?(obj.parent[:Contents])) obj.extend(Encryption::EncryptedString) unless obj.is_a?(Encryption::EncryptedString) obj.decrypt! when Stream next if obj.is_a?(XRefStream) or (not and obj.equal?()) obj.extend(Encryption::EncryptedStream) unless obj.is_a?(Encryption::EncryptedStream) end end end self end |