File Coverage

blib/lib/Crypt/PWSafe3.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2011-2015 T.v.Dein .
3             #
4             # Licensed under the terms of the Artistic License 2.0
5             # see: http://www.perlfoundation.org/artistic_license_2_0
6             #
7             # Implements:
8             # http://passwordsafe.svn.sourceforge.net/viewvc/passwordsafe/trunk/pwsafe/pwsafe/docs/formatV3.txt?revision=2139
9              
10             package Crypt::PWSafe3;
11              
12 1     1   21027 use strict;
  1         2  
  1         28  
13              
14 1     1   3 use Config;
  1         1  
  1         25  
15              
16 1     1   352 use Carp::Heavy;
  1         78  
  1         19  
17 1     1   4 use Carp;
  1         1  
  1         48  
18              
19 1     1   422 use Crypt::CBC;
  1         2682  
  1         28  
20 1     1   199 use Crypt::ECB;
  0            
  0            
21             use Crypt::Twofish;
22             use Digest::HMAC;
23             use Digest::SHA;
24             use Crypt::Random qw( makerandom );
25             use Data::UUID;
26             use File::Copy qw(copy move);
27             use File::Temp;
28             use FileHandle;
29             use Data::Dumper;
30             use Exporter ();
31             use vars qw(@ISA @EXPORT);
32              
33             $Crypt::PWSafe3::VERSION = '1.19';
34              
35             use Crypt::PWSafe3::Field;
36             use Crypt::PWSafe3::HeaderField;
37             use Crypt::PWSafe3::Record;
38             use Crypt::PWSafe3::SHA256;
39             use Crypt::PWSafe3::PasswordPolicy;
40              
41             require 5.10.0;
42              
43             #
44             # check which random source to use.
45             # install a wrapper closure around the
46             # one we found.
47             BEGIN {
48             eval {
49             require Bytes::Random::Secure;
50             Bytes::Random::Secure->import("random_bytes");
51             };
52             if ($@) {
53             # well, didn' work, use slow function
54             eval { require Crypt::Random; };# qw( makerandom ); };
55             if ($@) {
56             croak "Could not find either Crypt::Random or Bytes::Random::Secure. Install one of them and retry!";
57             }
58             else {
59             *Crypt::PWSafe3::random = sub {
60             my($this, $len) = @_;
61             my $bits = makerandom(Size => 256, Strength => 1);
62             return substr($bits, 0, $len);
63             };
64             }
65             }
66             else {
67             # good. use the faster one
68             *Crypt::PWSafe3::random = sub {
69             my($this, $len) = @_;
70             return random_bytes($len);
71             };
72             }
73             }
74              
75             my @fields = qw(tag salt iter shaps b1 b2 b3 b4 keyk file program
76             keyl iv hmac header strechedpw password whoami);
77             foreach my $field (@fields) {
78             eval qq(
79             *Crypt::PWSafe3::$field = sub {
80             my(\$this, \$arg) = \@_;
81             if (\$arg) {
82             return \$this->{$field} = \$arg;
83             }
84             else {
85             return \$this->{$field};
86             }
87             }
88             );
89             }
90              
91             sub new {
92             #
93             # new vault object
94             my($this, %param) = @_;
95             my $class = ref($this) || $this;
96             my $self = \%param; # file, password, whoami, program, create
97             bless($self, $class);
98              
99             # sanity checks
100             if (! exists $self->{whoami}) {
101             $self->{whoami} = $ENV{USER};
102             }
103              
104             if (! exists $self->{program}) {
105             $self->{program} = $0;
106             }
107              
108             if (! exists $self->{password}) {
109             croak 'Parameter password is required';
110             }
111              
112             if (! exists $self->{create}) {
113             $self->{create} = 1;
114             }
115              
116             if (! exists $self->{file}) {
117             $self->{file} = '';
118             $self->create();
119             }
120             else {
121             if (! -s $self->{file} || ! -r $self->{file}) {
122             if ($self->{create}) {
123             $self->create();
124             }
125             else {
126             croak "PWSafe3 file $self->{file} does not exist or is not readable";
127             }
128             }
129             else {
130             $self->read();
131             }
132             }
133              
134             $self->{modified} = 0;
135              
136             return $self;
137             }
138              
139             sub stretchpw {
140             #
141             # generate the streched password hash
142             #
143             # algorithm is described here:
144             # [KEYSTRETCH Section 4.1] http://www.schneier.com/paper-low-entropy.pdf
145             my ($this, $passwd) = @_;
146             my $sha = Digest::SHA->new('SHA-256');
147             $sha->reset();
148             $sha->add( ( $passwd, $this->salt) );
149             my $stretched = $sha->digest();
150             foreach (1 .. $this->iter) {
151             $sha->reset();
152             $sha->add( ( $stretched) );
153             $stretched = $sha->digest();
154             }
155             $passwd = $this->random(64);
156             return $stretched;
157             }
158              
159             sub create {
160             #
161             # create an empty vault without writing to disk
162             my($this) = @_;
163              
164             # default header fields
165             $this->tag('PWS3');
166             $this->salt($this->random(32));
167             $this->iter(2048);
168              
169             # the streched pw
170             $this->strechedpw($this->stretchpw($this->password()));
171              
172             # generate hash of the streched pw
173             my $sha = Digest::SHA->new('SHA-256');
174             $sha->reset();
175             $sha->add( ( $this->strechedpw() ) );
176             $this->shaps( $sha->digest() );
177              
178             # encrypt b1 .. b4
179             my $crypt = Crypt::ECB->new;
180             $crypt->cipher('Twofish');
181             $crypt->key( $this->strechedpw() );
182             $this->b1( $crypt->encrypt( $this->random(16) ) );
183             $this->b2( $crypt->encrypt( $this->random(16) ) );
184             $this->b3( $crypt->encrypt( $this->random(16) ) );
185             $this->b4( $crypt->encrypt( $this->random(16) ) );
186              
187             # create key k + l
188             $this->keyk( $crypt->decrypt( $this->b1() ) . $crypt->decrypt( $this->b2() ));
189             $this->keyl( $crypt->decrypt( $this->b3() ) . $crypt->decrypt( $this->b4() ));
190              
191             # create IV
192             $this->iv( $this->random(16) );
193              
194             # create hmac'er and cipher for actual encryption
195             $this->{hmacer} = Digest::HMAC->new($this->keyl, "Crypt::PWSafe3::SHA256");
196             $this->{cipher} = Crypt::CBC->new(
197             -key => $this->keyk,
198             -iv => $this->iv,
199             -cipher => 'Twofish',
200             -header => 'none',
201             -padding => 'null',
202             -literal_key => 1,
203             -keysize => 32,
204             -blocksize => 16
205             );
206              
207             # empty for now
208             $this->hmac( $this->{hmacer}->digest() );
209             }
210              
211             sub read {
212             #
213             # read and decrypt an existing vault file
214             my($this) = @_;
215              
216             my $file = $this->file();
217             my $fd = FileHandle->new($file, 'r') or croak "Could not open $file for reading: $!";
218             $fd->binmode();
219             $this->{fd} = $fd;
220              
221             $this->tag( $this->readbytes(4) );
222             if ($this->tag ne 'PWS3') {
223             croak "Not a PasswordSave V3 file!";
224             }
225              
226             $this->salt( $this->readbytes(32) );
227             $this->iter( unpack("L<", $this->readbytes(4) ) );
228              
229             $this->strechedpw($this->stretchpw($this->password()));
230              
231             my $sha = Digest::SHA->new(256);
232             $sha->reset();
233             $sha->add( ( $this->strechedpw() ) );
234             $this->shaps( $sha->digest() );
235              
236             my $fileshaps = $this->readbytes(32);
237             if ($fileshaps ne $this->shaps) {
238             croak "Wrong password!";
239             }
240              
241             $this->b1( $this->readbytes(16) );
242             $this->b2( $this->readbytes(16) );
243             $this->b3( $this->readbytes(16) );
244             $this->b4( $this->readbytes(16) );
245              
246             my $crypt = Crypt::ECB->new;
247             $crypt->cipher('Twofish') || die $crypt->errstring;
248             $crypt->key( $this->strechedpw() );
249              
250             $this->keyk($crypt->decrypt($this->b1) . $crypt->decrypt($this->b2));
251             $this->keyl($crypt->decrypt($this->b3) . $crypt->decrypt($this->b4));
252              
253             $this->iv( $this->readbytes(16) );
254              
255             # create hmac'er and cipher for actual encryption
256             $this->{hmacer} = Digest::HMAC->new($this->keyl, "Crypt::PWSafe3::SHA256");
257             $this->{cipher} = Crypt::CBC->new(
258             -key => $this->keyk,
259             -iv => $this->iv,
260             -cipher => 'Twofish',
261             -header => 'none',
262             -padding => 'null',
263             -literal_key => 1,
264             -keysize => 32,
265             -blocksize => 16
266             );
267              
268             # read db header fields
269             $this->{header} = {};
270             while (1) {
271             my $field = $this->readfield('header');
272             if (! $field) {
273             last;
274             }
275             if ($field->type == 0xff) {
276             last;
277             }
278             $this->addheader($field);
279             $this->hmacer($field->raw);
280             }
281              
282             # read db records
283             my $record = Crypt::PWSafe3::Record->new();
284             $this->{record} = {};
285             while (1) {
286             my $field = $this->readfield();
287             if (! $field) {
288             last;
289             }
290             if ($field->type == 0xff) {
291             $this->addrecord($record);
292             $record = Crypt::PWSafe3::Record->new();
293             }
294             else {
295             $record->addfield($field);
296             $this->hmacer($field->raw);
297             }
298             }
299              
300             # read and check file hmac
301             $this->hmac( $this->readbytes(32) );
302             my $calcmac = $this->{hmacer}->digest();
303             if ($calcmac ne $this->hmac) {
304             croak "File integrity check failed, invalid HMAC";
305             }
306              
307             $this->{fd}->close() or croak "Could not close $file: $!";
308             }
309              
310             sub untaint {
311             #
312             # untaint path's
313             my ($this, $path) = @_;
314             if($path =~ /([\w\-\/\\\.:]+\z)/) {
315             return $1;
316             }
317             else {
318             # fail, return unchanged
319             return $path;
320             }
321             }
322              
323             sub save {
324             #
325             # write data to the vault file
326             my($this, %param) = @_;
327             my($file, $passwd);
328              
329             if (! exists $param{file}) {
330             $file = $this->file;
331             }
332             else {
333             $file = $param{file}
334             }
335             if (! exists $param{passwd}) {
336             $passwd = $this->password;
337             }
338             else {
339             $passwd = $param{passwd}
340             }
341              
342             if (! $this->{modified}) {
343             return;
344             }
345              
346             my $lastsave = Crypt::PWSafe3::HeaderField->new(type => 0x04, value => time);
347             my $whatsaved = Crypt::PWSafe3::HeaderField->new(type => 0x06, value => $this->{program});
348             my $whosaved = Crypt::PWSafe3::HeaderField->new(type => 0x05, value => $this->{whoami});
349             $this->addheader($lastsave);
350             $this->addheader($whatsaved);
351             $this->addheader($whosaved);
352              
353             my $fd = File::Temp->new(TEMPLATE => '.vaultXXXXXXXX', TMPDIR => 1, EXLOCK => 0) or croak "Could not open tmpfile: $!\n";
354             my $tmpfile = "$fd";
355              
356             $this->{fd} = $fd;
357              
358             $this->writebytes($this->tag);
359             $this->writebytes($this->salt);
360             $this->writebytes(pack("L<", $this->iter));
361              
362             $this->strechedpw($this->stretchpw($passwd));
363              
364             # line 472
365             my $sha = Digest::SHA->new(256);
366             $sha->reset();
367             $sha->add( ( $this->strechedpw() ) );
368             $this->shaps( $sha->digest() );
369              
370             $this->writebytes($this->shaps);
371             $this->writebytes($this->b1);
372             $this->writebytes($this->b2);
373             $this->writebytes($this->b3);
374             $this->writebytes($this->b4);
375              
376             my $crypt = Crypt::ECB->new;
377             $crypt->cipher('Twofish');
378             $crypt->key( $this->strechedpw() );
379              
380             $this->keyk($crypt->decrypt($this->b1) . $crypt->decrypt($this->b2));
381             $this->keyl($crypt->decrypt($this->b3) . $crypt->decrypt($this->b4));
382              
383             $this->writebytes($this->iv);
384              
385             $this->{hmacer} = Digest::HMAC->new($this->keyl, "Crypt::PWSafe3::SHA256");
386             $this->{cipher} = Crypt::CBC->new(
387             -key => $this->keyk,
388             -iv => $this->iv,
389             -cipher => 'Twofish',
390             -header => 'none',
391             -padding => 'null',
392             -literal_key => 1,
393             -keysize => 32,
394             -blocksize => 16
395             );
396              
397             my $eof = Crypt::PWSafe3::HeaderField->new(type => 0xff, value => '');
398              
399             foreach my $type (keys %{$this->{header}}) {
400             $this->writefield($this->{header}->{$type});
401             $this->hmacer($this->{header}->{$type}->{raw});
402             }
403             $this->writefield($eof);
404             $this->hmacer($eof->{raw});
405              
406             $eof = Crypt::PWSafe3::Field->new(type => 0xff, value => '');
407              
408             foreach my $uuid (keys %{$this->{record}}) {
409             my $record = $this->{record}->{$uuid};
410             foreach my $type (keys %{$record->{field}}) {
411             $this->writefield($record->{field}->{$type});
412             $this->hmacer($record->{field}->{$type}->{raw});
413             }
414             $this->writefield($eof);
415             $this->hmacer($eof->{raw});
416             }
417              
418             $this->writefield(Crypt::PWSafe3::Field->new(type => 'none', raw => 0));
419              
420             $this->hmac( $this->{hmacer}->digest() );
421             $this->writebytes($this->hmac);
422             if ($Config{d_fsync}) {
423             $this->{fd}->sync() or croak "Could not fsync: $!";
424             }
425             $this->{fd}->close() or croak "Could not close tmpfile: $!";
426              
427             # now try to read it in again to check if it
428             # is valid what we created
429             eval {
430             my $vault = Crypt::PWSafe3->new(file => $tmpfile, create => 0, password => $passwd);
431             };
432             if ($@) {
433             unlink $tmpfile;
434             croak "File integrity check failed ($@)";
435             }
436             else {
437             # well, seems to be ok :)
438             move($tmpfile, $file) or croak "Could not move $tmpfile to $file: $!";
439             }
440             }
441              
442             sub writefield {
443             #
444             # write a field to vault file
445             my($this, $field) = @_;
446              
447             if ($field->type eq 'none') {
448             $this->writebytes("PWS3-EOFPWS3-EOF");
449             return;
450             }
451              
452             my $len = pack("L<", $field->len);
453             my $type = pack("C", $field->type);
454             my $raw = $field->raw;
455              
456             # Assemble TLV block and pad to 16-byte boundary
457             my $data = $len . $type . $raw;
458              
459             if (length($data) % 16 != 0) {
460             # too small or too large, padding required
461             my $padcount = 16 - (length($data) % 16);
462             $data .= $this->random($padcount);
463             }
464              
465             if (length($data) > 16) {
466             my $crypt;
467             while (1) {
468             my $part = substr($data, 0, 16);
469             $crypt .= $this->encrypt($part);
470             if (length($data) <= 16) {
471             last;
472             }
473             else {
474             $data = substr($data, 16);
475             }
476             }
477             $this->writebytes($crypt);
478             }
479             else {
480             $this->writebytes($this->encrypt($data));
481             }
482             }
483              
484             sub getrecord {
485             #
486             # return the given record
487             my($this, $uuid) = @_;
488             if (exists $this->{record}->{$uuid}) {
489             return $this->{record}->{$uuid};
490             }
491             else {
492             return 0;
493             }
494             }
495              
496             sub getrecords {
497             #
498             # return all records we've got as a copy
499             my ($this) = @_;
500             return map { $this->{record}->{$_} } keys %{$this->{record}};
501             }
502              
503             sub looprecord {
504             #
505             # return a list of uuid's of all records
506             my ($this) = @_;
507             return keys %{$this->{record}};
508             }
509              
510             sub modifyrecord {
511             #
512             # modify a record identified by the given uuid
513             my($this, $uuid, %fields) = @_;
514              
515             if (! exists $this->{record}->{$uuid}) {
516             croak "No record with uuid $uuid found!";
517             }
518              
519             foreach my $field (keys %fields) {
520             $this->{record}->{$uuid}->modifyfield($field, $fields{$field});
521             }
522              
523             # mark vault as modified
524             $this->markmodified();
525             }
526              
527             sub deleterecord {
528             #
529             # delete a record identified by the given uuid, if present
530             # returns 1 if record was actually removed, 0 if it was not present
531             my($this, $uuid) = @_;
532              
533             if (! exists $this->{record}->{$uuid}) {
534             return 0;
535             }
536              
537             delete $this->{record}->{$uuid};
538              
539             # mark vault as modified
540             $this->markmodified();
541              
542             return 1;
543             }
544              
545              
546             sub markmodified {
547             #
548             # mark the vault as modified by setting the appropriate header fields
549             my($this) = @_;
550             my $lastmod = Crypt::PWSafe3::HeaderField->new(
551             name => "lastsavetime",
552             value => time
553             );
554             my $who = Crypt::PWSafe3::HeaderField->new(
555             name => "wholastsaved",
556             value => $this->{whoami}
557             );
558             $this->addheader($lastmod);
559             $this->addheader($who);
560             $this->{modified} = 1;
561             }
562              
563             sub newrecord {
564             #
565             # add a new record to an existing vault
566             my($this, %fields) = @_;
567             my $record = Crypt::PWSafe3::Record->new();
568             foreach my $field (keys %fields) {
569             $record->modifyfield($field, $fields{$field});
570             }
571             $this->markmodified();
572             $this->addrecord($record);
573             return $record->uuid;
574             }
575              
576             sub addrecord {
577             #
578             # add a record object to record hash
579             my($this, $record) = @_;
580             $this->{record}->{ $record->uuid } = $record;
581             }
582              
583             sub addheader {
584             #
585             # add a header field to header hash
586             my($this, $field) = @_;
587             $this->{header}->{ $field->name } = $field;
588             }
589              
590              
591             sub readfield {
592             #
593             # read and return a field object of the vault
594             my($this, $header) = @_;
595             my $data = $this->readbytes(16);
596             if (! $data or length($data) < 16) {
597             croak "EOF encountered when parsing record field";
598             }
599             if ($data eq "PWS3-EOFPWS3-EOF") {
600             return 0;
601             }
602              
603             $data = $this->decrypt($data);
604              
605             my $len = unpack("L<", substr($data, 0, 4));
606             my $type = unpack("C", substr($data, 4, 1));
607             my $raw = substr($data, 5);
608              
609             if ($len > 11) {
610             my $step = int(($len+4) / 16);
611             for (1 .. $step) {
612             my $data = $this->readbytes(16);
613             if (! $data or length($data) < 16) {
614             croak "EOF encountered when parsing record field";
615             }
616             $raw .= $this->decrypt($data);
617             }
618             }
619             $raw = substr($raw, 0, $len);
620             if ($header) {
621             return Crypt::PWSafe3::HeaderField->new(type => $type, raw => $raw);
622             }
623             else {
624             return Crypt::PWSafe3::Field->new(type => $type, raw => $raw);
625             }
626             }
627              
628             sub decrypt {
629             #
630             # helper, decrypt a string
631             my ($this, $data) = @_;
632             my $clear = $this->{cipher}->decrypt($data);
633             $this->{cipher}->iv($data);
634             return $clear;
635             }
636              
637             sub encrypt {
638             #
639             # helper, encrypt a string
640             my ($this, $data) = @_;
641             my $raw = $this->{cipher}->encrypt($data);
642             if (length($raw) > 16) {
643             # we use only the last 16byte block as next iv
644             # if data is more than 1 blocks then Crypt::CBC
645             # has already updated the iv for the inner blocks
646             $raw = substr($raw, -16, 16);
647             }
648             $this->{cipher}->iv($raw);
649             return $raw;
650             }
651              
652             sub hmacer {
653             #
654             # helper, hmac generator
655             my($this, $data) = @_;
656              
657             $this->{hmacer}->add($data);
658             }
659              
660             sub readbytes {
661             #
662             # helper, reads number of bytes
663             my ($this, $size) = @_;
664             my $buffer;
665             my ($package, $filename, $line) = caller;
666              
667             my $got = $this->{fd}->sysread($buffer, $size);
668             if ($got == $size) {
669             $this->{sum} += $got;
670             return $buffer;
671             }
672             else {
673             return 0;
674             }
675             }
676              
677             sub writebytes {
678             #
679             # helper, reads number of bytes
680             my ($this, $bytes) = @_;
681             my $got = $this->{fd}->syswrite($bytes);
682             if ($got) {
683             return $got;
684             }
685             else {
686             croak "Could not write to $this->{file}: $!";
687             }
688             }
689              
690              
691             sub getheader {
692             #
693             # return a header object
694             my($this, $name) = @_;
695             if (exists $this->{header}->{$name}) {
696             return $this->{header}->{$name};
697             }
698             else {
699             croak "Unknown header $name";
700             }
701             }
702              
703              
704              
705              
706             =head1 NAME
707              
708             Crypt::PWSafe3 - Read and write Passwordsafe v3 files
709              
710             =head1 SYNOPSIS
711              
712             use Crypt::PWSafe3;
713             my $vault = Crypt::PWSafe3->new(file => 'filename.psafe3', password => 'somesecret');
714            
715             # fetch all database records
716             my @records = $vault->getrecords();
717             foreach my $record (@records) {
718             print $record->uuid;
719             print $record->title;
720             print $record->passwd;
721             # see Crypt::PWSafe3::Record for more details on accessing records
722             }
723              
724             # same as above but don't detach records from vault
725             foreach my $uuid ($vault->looprecord) {
726             # either change a record
727             $vault->modifyrecord($uuid, passwd => 'p1');
728              
729             # or just access it directly
730             print $vault->{record}->{$uuid}->title;
731             }
732              
733             # add a new record
734             $vault->newrecord(user => 'u1', passwd => 'p1', title => 't1');
735              
736             # modify an existing record
737             $vault->modifyrecord($uuid, passwd => 'p1');
738              
739             # replace a record (aka edit it)
740             my $record = $vault->getrecord($uuid);
741             $record->title('t2');
742             $record->passwd('foobar');
743             $vault->addrecord($record);
744              
745             # mark the vault as modified (not required if
746             # changes were done with ::modifyrecord()
747             $vault->markmodified();
748              
749             # save the vault
750             $vault->save();
751              
752             # save it under another name using another password
753             $vault->save(file => 'another.pwsafe3', passwd => 'blah');
754              
755             # access database headers
756             print $vault->getheader('wholastsaved')->value();
757             print scalar localtime($vault->getheader('lastsavetime')->value());
758              
759             # add/replace a database header
760             my $h = Crypt::PWSafe3::HeaderField->new(name => 'savedonhost', value => 'localhost');
761             $vault->addheader($h);
762              
763             =head1 DESCRIPTION
764              
765             Crypt::PWSafe3 provides read and write access to password
766             database files created by Password Safe V3 (and up) available at
767             http://passwordsafe.sf.net.
768              
769             =head1 METHODS
770              
771             =head2 B
772              
773             The new() method creates a new Crypt::PWSafe3 object. Any parameters
774             must be given as hash parameters.
775              
776             my $vault = Crypt::PWSafe3->new(
777             file => 'vault.psafe3',
778             password => 'secret',
779             whoami => 'user1',
780             program => 'mypwtool v1',
781             create => 0, # or 1
782             );
783              
784             Mandatory parameters:
785              
786             =over
787              
788             =item B
789              
790             Specifies the password safe (v3) file. If it exists
791             it will be read in. Otherwise it will be created
792             if you call B.
793              
794             =item B
795              
796             The password required to decrypt the password safe file.
797              
798             =back
799              
800             Optional parameters:
801              
802             =over
803              
804             =item B
805              
806             Specifies the user who saves the password safe file.
807             If omitted the environment variable USER will be used
808             when calling B.
809              
810             =item B
811              
812             Specifies which program saved the password safe file.
813             If omitted, the content of the perl variable $0 will
814             be used, which contains the name of the current running
815             script.
816              
817             =item B
818              
819             If set to 0, B will fail if the file doesn't exist,
820             otherwise it will try to create it. Enabled by default.
821              
822             =back
823              
824             The optional parameters will become header fields of
825             the password safe file. You can manually set/override
826             more headers. See section L for
827             more details.
828              
829             =head2 B
830              
831             Returns a list of all records found in the password
832             safe file. Each element is an B
833             object.
834              
835             A record object is identified by its B value,
836             which is a unique identifier. You can access the uuid by:
837              
838             $record->uuid
839              
840             Accessing other record properties works the same. For
841             more details, refer to L.
842              
843             Please note that record objects accessed this way are
844             copies. If you change such a record object and save the
845             database, nothing will in fact change. In this case you
846             need to put the changed record back into the record
847             list of the Crypt::PWSafe3 object by:
848              
849             $vault->addrecord($record):
850              
851             See section L for more details on this.
852              
853              
854             =head2 B
855              
856             Returns a list of UUIDs of all known records. You can
857             use this list to iterate over the records without
858             copying them and optionally changing them in place.
859              
860             Example:
861              
862             foreach my $uuid ($vault->looprecord) {
863             # either change a record
864             $vault->modifyrecord($uuid, passwd => 'p1');
865              
866             # or just access it directly
867             print $vault->{record}->{$uuid}->title;
868             }
869              
870              
871             =head2 B
872              
873             Modifies the record identified by the given UUID using
874             the values of the supplied parameter hash.
875              
876             Example:
877              
878             $vault->modifyrecord($uuid, passwd => 'p1');
879              
880             The parameter hash may contain any valid record field
881             type with according values. Refer to L
882             for details about available fields.
883              
884             =head2 B
885              
886             Create a new record. The UUID of the record will be generated
887             automatically. Refer to L
888             for details about available fields.
889              
890             =head2 B
891              
892             Add a record to the vault. The record must be an
893             L object.
894              
895             =head2 B
896              
897             Delete the record identified by the given UUID.
898              
899             =head2 B
900              
901             Save the current password safe vault back to disk.
902              
903             If not otherwise specified, use the same file and
904             password as we used to open it initially. If the
905             file doesn't exist it will be created.
906              
907             You may specify another filename and password here
908             by using a parameter hash.
909              
910             Example:
911              
912             $vault->save(file => 'anotherfile.psafe3', passwd => 'foo');
913              
914             Please note, that the vault will be written to a
915             temporary file first, then this temporary file
916             will be read in and if that works, it will be
917             moved over the destination file. This way the original
918             file persists if the written database gets corrupted
919             by some unknown reason (a bug for instance).
920              
921              
922             =head2 B
923              
924             Returns a raw B object.
925             Refer to L for details
926             how to access it.
927              
928             =head2 B
929              
930             Adds a header field to the password safe database. The
931             object parameter must be an B
932             object.
933              
934             If the header already exists it will be replaced.
935              
936             Refer to L for details
937             how to create new ones
938             .
939              
940             =head1 AUTHOR
941              
942             T.v.Dein
943              
944             =head1 BUGS
945              
946             Report bugs to
947             http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Crypt-PWSafe3.
948              
949              
950             =head1 SEE ALSO
951              
952             Subclasses:
953              
954             L
955             L
956             L
957              
958             Password Safe Homepage:
959             L
960              
961             Another (read-only) perl module:
962             L
963              
964             A python port of Password Safe:
965             L
966             Many thanks to Christoph Sommer, his python library
967             inspired me a lot and in fact most of the concepts
968             in this module are his ideas ported to perl.
969              
970             =head1 COPYRIGHT
971              
972             Copyright (c) 2011-2015 by T.v.Dein .
973              
974             =head1 LICENSE
975              
976             This program is free software; you can redistribute it
977             and/or modify it under the same terms of the Artistic
978             License 2.0, see: L
979              
980             =head1 VERSION
981              
982             Crypt::PWSafe3 Version 1.19.
983              
984             =cut
985              
986              
987              
988              
989             1;
990