Class: Kdbx

Inherits:
Object
  • Object
show all
Defined in:
lib/kdbx.rb,
lib/kdbx/crypto.rb,
lib/kdbx/version.rb,
lib/kdbx/exception.rb,
lib/kdbx/attributes.rb

Defined Under Namespace

Classes: FormatError, Header, KdbxError, KeyError, ParseError

Constant Summary collapse

VERSION =
"0.2.1"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**options) ⇒ Kdbx

Returns a new instance of Kdbx.



16
17
18
19
20
21
# File 'lib/kdbx.rb', line 16

def initialize(**options)
  @password = @keyfile = nil
  @header, @content = Header.new, String.new
  self.password = options[:password] if options.has_key? :password
  self.keyfile  = options[:keyfile]  if options.has_key? :keyfile
end

Instance Attribute Details

#contentObject

Returns the value of attribute content.



84
85
86
# File 'lib/kdbx/attributes.rb', line 84

def content
  @content
end

#headerObject

Returns the value of attribute header.



38
39
40
# File 'lib/kdbx/attributes.rb', line 38

def header
  @header
end

#keyfileObject

Returns the value of attribute keyfile.



10
11
12
# File 'lib/kdbx/attributes.rb', line 10

def keyfile
  @keyfile
end

#passwordObject

Returns the value of attribute password.



5
6
7
# File 'lib/kdbx/attributes.rb', line 5

def password
  @password
end

Class Method Details

.open(filename, **options) ⇒ Object



7
8
9
10
11
12
13
14
# File 'lib/kdbx.rb', line 7

def self.open(filename, **options)
  new(**options).tap do |kdbx|
    File.open filename, "rb" do |file|
      kdbx.header = Header.load file
      kdbx.decrypt_content file.read
    end
  end
end

Instance Method Details

#compressionflagsObject



40
41
42
# File 'lib/kdbx/attributes.rb', line 40

def compressionflags
  @header[3].unpack("L").first
end

#compressionflags=(flag) ⇒ Object



44
45
46
# File 'lib/kdbx/attributes.rb', line 44

def compressionflags=(flag)
  @header[3] = [flag].pack("L")
end

#credentialObject



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/kdbx/attributes.rb', line 15

def credential
  cred = password || String.new
  return cred if keyfile == nil
  data = IO.read keyfile
  if !data.valid_encoding?
    return cred + sha256(data)
  end
  if data.bytesize == 32
    return cred + data
  end
  if data =~ /\A\h{64}\z/
    data = [data].pack("H*")
    return cred + data
  end
  begin
    xpath = "/KeyFile/Key/Data"
    tnd = REXML::Document.new(data).get_text(xpath)
    cred + Base64.decode64(tnd.to_s)
  rescue REXML::ParseException
    cred + sha256(data)
  end
end

#decrypt_content(data) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/kdbx/crypto.rb', line 15

def decrypt_content(data)
  data = decrypt data.to_s
  if data.start_with? streamstartbytes
    size = streamstartbytes.bytesize
    data = data.byteslice size..-1
  else
    fail KeyError, "wrong password or keyfile"
  end
  data = decode data
  data = gunzip data if compressionflags == 1
  data = reverse data if innerrandomstreamid == 2
  @content = data
end

#encrypt_contentObject



8
9
10
11
12
13
# File 'lib/kdbx/crypto.rb', line 8

def encrypt_content
  data = @content.to_s
  data = obfuscate data if innerrandomstreamid == 2
  data = gzip data if compressionflags == 1
  encrypt streamstartbytes + encode(data)
end

#encryptionivObject



64
65
66
# File 'lib/kdbx/attributes.rb', line 64

def encryptioniv
  @header[7]
end

#innerrandomstreamidObject



76
77
78
# File 'lib/kdbx/attributes.rb', line 76

def innerrandomstreamid
  @header[10].unpack("L").first
end

#innerrandomstreamid=(id) ⇒ Object



80
81
82
# File 'lib/kdbx/attributes.rb', line 80

def innerrandomstreamid=(id)
  @header[10] = [id].pack("L")
end

#inspectObject



86
87
88
# File 'lib/kdbx/attributes.rb', line 86

def inspect
  super
end

#masterseedObject



48
49
50
# File 'lib/kdbx/attributes.rb', line 48

def masterseed
  @header[4]
end

#protectedstreamkeyObject



68
69
70
# File 'lib/kdbx/attributes.rb', line 68

def protectedstreamkey
  @header[8]
end

#save(filename) ⇒ Object



23
24
25
26
27
28
29
# File 'lib/kdbx.rb', line 23

def save(filename)
  secure_write filename do |file|
    file.write header.dump
    file.write encrypt_content
  end
  true
end

#streamstartbytesObject



72
73
74
# File 'lib/kdbx/attributes.rb', line 72

def streamstartbytes
  @header[9]
end

#transformroundsObject



56
57
58
# File 'lib/kdbx/attributes.rb', line 56

def transformrounds
  @header[6].unpack("Q").first
end

#transformrounds=(num) ⇒ Object



60
61
62
# File 'lib/kdbx/attributes.rb', line 60

def transformrounds=(num)
  @header[6] = [num].pack("Q")
end

#transformseedObject



52
53
54
# File 'lib/kdbx/attributes.rb', line 52

def transformseed
  @header[5]
end