1 package File
::KDBX
::Cipher
::Stream
;
2 # ABSTRACT: A cipher stream encrypter/decrypter
7 use Crypt
::Digest
qw(digest_data);
8 use File
::KDBX
::Constants
qw(:cipher :random_stream);
13 use parent
'File::KDBX::Cipher';
15 our $VERSION = '999.999'; # VERSION
21 if (my $uuid = $args{uuid
}) {
22 if ($uuid eq CIPHER_UUID_CHACHA20
&& length($args{iv
}) == 16) {
24 my $buf = substr($self->{iv
}, 0, 4, '');
25 $self->{counter
} = unpack('L<', $buf);
27 elsif ($uuid eq CIPHER_UUID_SALSA20
) {
28 # only need eight bytes...
29 $self->{iv
} = substr($args{iv
}, 8);
32 elsif (my $id = $args{stream_id
}) {
33 my $key_ref = ref $args{key
} ? $args{key
} : \
$args{key
};
34 if ($id == STREAM_ID_CHACHA20
) {
35 ($self->{key
}, $self->{iv
}) = unpack('a32 a12', digest_data
('SHA512', $$key_ref));
37 elsif ($id == STREAM_ID_SALSA20
) {
38 ($self->{key
}, $self->{iv
}) = (digest_data
('SHA256', $$key_ref), STREAM_SALSA20_IV
);
47 my $stream = $self->_stream;
48 return join('', map { $stream->crypt(ref $_ ? $$_ : $_) } grep { defined } @_);
53 return $self->_stream->keystream(@_);
58 my $dup = File
::KDBX
::Cipher-
>new(
59 stream_id
=> $self->stream_id,
63 $dup->{key
} = $self->key;
64 $dup->{iv
} = $self->iv;
65 # FIXME - probably turn this into a proper clone method
72 $self->{stream
} //= do {
74 my $pkg = 'Crypt::Stream::'.$self->algorithm;
75 my $counter = $self->counter;
77 if (defined (my $offset = $self->offset)) {
78 $counter = int($offset / 64);
81 my $s = $pkg->new($self->key, $self->iv, $counter);
82 # seek to correct position within block
83 $s->keystream($pos) if $pos;
87 throw
'Failed to initialize stream cipher library',
89 algorithm
=> $self->algorithm,
90 key_length
=> length($self->key),
91 iv_length
=> length($self->iv),
92 iv
=> unpack('H*', $self->iv),
93 key
=> unpack('H*', $self->key);
99 sub encrypt
{ goto &crypt }
100 sub decrypt
{ goto &crypt }
102 sub finish
{ delete $_[0]->{stream
}; '' }
104 sub counter
{ $_[0]->{counter
} // 0 }
105 sub offset
{ $_[0]->{offset
} }
109 Get the stream cipher algorithm
. Can be one of C
<Salsa20
> and C
<ChaCha
>.
113 sub algorithm
{ $_[0]->{algorithm
} or throw
'Stream cipher algorithm is not set' }
114 sub key_size
{ { Salsa20
=> 32, ChaCha
=> 32 }->{$_[0]->{algorithm
} || ''} // 0 }
115 sub iv_size
{ { Salsa20
=> 8, ChaCha
=> 12 }->{$_[0]->{algorithm
} || ''} // -1 }
123 use File::KDBX::Cipher::Stream;
125 my $cipher = File::KDBX::Cipher::Stream->new(algorithm => $algorithm, key => $key, iv => $iv);
129 A subclass of L<File::KDBX::Cipher> for encrypting and decrypting data using a stream cipher.