Class/Module Index [+]

Quicksearch

Origami::Encryption::Standard::Dictionary

Class defining a standard encryption dictionary.

Constants

O
OE
Perms
U
UE

Public Instance Methods

compute_owner_encryption_key(ownerpassword) click to toggle source

Computes the key that will be used to encrypt/decrypt the document contents with owner password. Revision 5 and above.

# File lib/origami/encryption.rb, line 1157
def compute_owner_encryption_key(ownerpassword)
  if self.R >= 5
    passwd = password_to_utf8(ownerpassword)

    oks = self.O[40, 8]

    if self.R == 5
      okey = Digest::SHA256.digest(passwd + oks + self.U)
    else
      okey = compute_hardened_hash(passwd, oks, self.U)
    end

    iv = ::Array.new(AES::BLOCKSIZE, 0).pack("C*")
    AES.new(okey, nil, false).decrypt(iv + self.OE.value)
  end
end
compute_user_encryption_key(userpassword, fileid) click to toggle source

Computes the key that will be used to encrypt/decrypt the document contents with user password.

# File lib/origami/encryption.rb, line 1114
def compute_user_encryption_key(userpassword, fileid)
 
  if self.R < 5
    padded = pad_password(userpassword)
    padded.force_encoding('binary') if RUBY_VERSION > '1.8'

    padded << self.O
    padded << [ self.P ].pack("i")
    
    padded << fileid
    
    encrypt_metadata = self.EncryptMetadata != false
    padded << [ -1 ].pack("i") if self.R >= 4 and not encrypt_metadata

    key = Digest::MD5.digest(padded)

    50.times { key = Digest::MD5.digest(key[0, self.Length / 8]) } if self.R >= 3

    if self.R == 2
      key[0, 5]
    elsif self.R >= 3
      key[0, self.Length / 8]
    end
  else
    passwd = password_to_utf8(userpassword)
    
    uks = self.U[40, 8]
    
    if self.R == 5
      ukey = Digest::SHA256.digest(passwd + uks)
    else
      ukey = compute_hardened_hash(passwd, uks)
    end
    
    iv = ::Array.new(AES::BLOCKSIZE, 0).pack("C*")
    AES.new(ukey, nil, false).decrypt(iv + self.UE.value)
  end
end
is_owner_password?(pass, salt) click to toggle source

Checks owner password. For version 2,3 and 4, salt is the document ID. For version 5, salt is (Owner Key Salt + U)

# File lib/origami/encryption.rb, line 1248
def is_owner_password?(pass, salt)

  if self.R < 5
    user_password = retrieve_user_password(pass)
    is_user_password?(user_password, salt)
  elsif self.R == 5
    ovs = self.O[32, 8]
    Digest::SHA256.digest(password_to_utf8(pass) + ovs + self.U) == self.O[0, 32]
  elsif self.R == 6
    ovs = self.O[32, 8]
    compute_hardened_hash(password_to_utf8(pass), ovs, self.U[0,48]) == self.O[0, 32]
  end
end
is_user_password?(pass, salt) click to toggle source

Checks user password. For version 2,3 and 4, salt is the document ID. For version 5 and 6, salt is the User Key Salt.

# File lib/origami/encryption.rb, line 1229
def is_user_password?(pass, salt)
  if self.R == 2 
    compute_user_password(pass, salt) == self.U
  elsif self.R == 3 or self.R == 4
    compute_user_password(pass, salt)[0, 16] == self.U[0, 16]
  elsif self.R == 5
    uvs = self.U[32, 8]
    Digest::SHA256.digest(password_to_utf8(pass) + uvs) == self.U[0, 32]
  elsif self.R == 6
    uvs = self.U[32, 8]
    compute_hardened_hash(password_to_utf8(pass), uvs) == self.U[0, 32]
  end
end
retrieve_user_password(ownerpassword) click to toggle source

Retrieve user password from owner password. Cannot be used with revision 5.

# File lib/origami/encryption.rb, line 1266
def retrieve_user_password(ownerpassword)
  key = compute_owner_key(ownerpassword)

  if self.R == 2
    ARC4.decrypt(key, self.O)
  elsif self.R == 3 or self.R == 4
    user_password = ARC4.decrypt(xor(key, 19), self.O)
    19.times { |i| user_password = ARC4.decrypt(xor(key, 18-i), user_password) }
    
    user_password 
  end
end
set_passwords(ownerpassword, userpassword, salt = nil) click to toggle source

Set up document passwords.

# File lib/origami/encryption.rb, line 1177
def set_passwords(ownerpassword, userpassword, salt = nil)
  if self.R < 5
    key = compute_owner_key(ownerpassword)
    upadded = pad_password(userpassword)
    
    owner_key = ARC4.encrypt(key, upadded)
    19.times { |i| owner_key = ARC4.encrypt(xor(key,i+1), owner_key) } if self.R >= 3
  
    self.O = owner_key
    self.U = compute_user_password(userpassword, salt)
  
  else
    upass = password_to_utf8(userpassword)
    opass = password_to_utf8(ownerpassword)

    uvs, uks, ovs, oks = ::Array.new(4) { Encryption.rand_bytes(8) }
    file_key = Encryption.strong_rand_bytes(32)
    iv = ::Array.new(AES::BLOCKSIZE, 0).pack("C*")
    
    if self.R == 5
      self.U = Digest::SHA256.digest(upass + uvs) + uvs + uks
      self.O = Digest::SHA256.digest(opass + ovs + self.U) + ovs + oks
      ukey = Digest::SHA256.digest(upass + uks)
      okey = Digest::SHA256.digest(opass + oks + self.U)
    else
      self.U = compute_hardened_hash(upass, uvs) + uvs + uks
      self.O = compute_hardened_hash(opass, ovs, self.U) + ovs + oks
      ukey = compute_hardened_hash(upass, uks)
      okey = compute_hardened_hash(opass, oks, self.U)
    end

    self.UE = AES.new(ukey, iv, false).encrypt(file_key)[iv.size, 32]
    self.OE = AES.new(okey, iv, false).encrypt(file_key)[iv.size, 32]

    perms = 
      [ self.P ].pack("V") +                              # 0-3
      [ -1 ].pack("V") +                                  # 4-7
      (self.EncryptMetadata == true ? "T" : "F") +        # 8
      "adb" +                                             # 9-11
      [ 0 ].pack("V")                                     # 12-15

    self.Perms = AES.new(file_key, iv, false).encrypt(perms)[iv.size, 16]

    file_key
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.