Crypt-FileHandle

 view release on metacpan or  search on metacpan

lib/Crypt/FileHandle.pm  view on Meta::CPAN

	if (! defined $$buf) {
		# offset is ignored if provided scalar is not defined
		$$buf = substr($$rbuf, 0, $len, "");
		$xl = length($$buf);
	}
	else {
		$xl = length(substr($$buf, $off) = substr($$rbuf, 0, $len, ""));
	}

	# increment total number of bytes extracted
	# may differ from requested length if _decrypt_read() not called or EOF
	$self->{$V_TOTAL_BYTES} += $xl;

	return $xl;
}

############################################################

1;

__END__

=head1 NAME

Crypt::FileHandle - encrypted FileHandle

=head1 SYNOPSIS

  use Crypt::CBC;
  use Crypt::FileHandle;

  # example cipher
  $cipher = Crypt::CBC->new(
  	-cipher => 'Cipher::AES',
  	-key    => $key,
  	-header => 'salt'
  );

  # create tied FileHandle
  $fh = Crypt::FileHandle->new($cipher);

  ### treat $fh same as any FileHandle

  # write file
  open($fh, '>', $filename) || die $!;
  print $fh "This is a test string\n";
  close($fh);

  # read file
  open($fh, '<', $filename) || die $!;
  while(<$fh>) {
  	print $_;
  }
  close($fh);

=head1 DESCRIPTION

This package creates a tied FileHandle that automatically encrypts or
decrypts data using the provided cipher. The FileHandle returned from
new() can be treated like a normal FileHandle. All encrypting,
decrypting, and buffering is completely transparent to the caller.

=head1 CIPHER METHODS

This package generally supports ciphers compliant with Crypt::CBC,
including CryptX ciphers. The cipher provided to new() must support
at least the methods listed below, but no other methods are utilized
by this package. Refer to Crypt::CBC for more information on these
methods. Even though it is not recommended, a custom home-made cipher
object can be used if it supports these methods.

=over 4

=item start($string)

Initializes the encryption or decryption process according to the
provided string, either 'encrypting' or 'decrypting'.

=item crypt($data)

Encrypts or decrypts the provided data and returns the resulting
data.

=item finish()

Flushes the internal buffer and returns any remaining data.

=back

=head1 GLOBAL METHODS

This package supports the following global methods. These methods
cannot be called on the tied FileHandle returned from new() and
should only be called via the package name.

=over 4

=item F<new($cipher)>

Returns a new FileHandle object that is "tied" with the provided
cipher object. It utilizes TIEHANDLE to tie a FileHandle object with
a real FileHandle object underneath. The returned FileHandle can be
treated like a normal FileHandle, but all writes and reads will occur
on the real FileHandle which will be encrypted or decrypted
automatically using the methods of the cipher object.

The cipher object provided to new() should NOT be used in any other
capacity, otherwise it may disrupt encryption and decryption
operations.

=item F<verify_cipher($cipher)>

Returns true or false if the provided cipher is supported by
confirming that the necessary methods exist. This method is
automatically called by new() to confirm the provided cipher is
valid.

=item F<readsize()>

=item F<readsize($readsize)>

Returns the global READSIZE. When a file is open for reading, data
is read from the real FileHandle in blocks of READSIZE bytes. Any
decrypted data that is not returned by any of the read methods is
automatically stored in an internal buffer to be utilized during
future read calls.

The global READSIZE can be changed by providing an optional
parameter. However, this is a global value and will affect all
instances of Crypt::FileHandle. Beware of setting the READSIZE too
small, which may prevent reading the entire encrypted file header
during the first read call, causing the decryption to fail. The
default READSIZE is 4096 bytes.

=back

=head1 TIED METHODS

The following methods have been implemented for the tied FileHandle
returned by new(). These methods are automatically called through the
tied FileHandle and should not be called directly.

=over 4

=item F<OPEN()>

Called when open() is called on the tied FileHandle returned from
new(). Opens the real FileHandle using the given parameters, and
automatically calls start() on the provided cipher with 'encrypting'
or 'decrypting' based on whether the real FileHandle was opened for
writing or reading. If the mode is not explicitly provided, it
assumes the file was open for reading. Note that sysopen() is not
supported with a tied FileHandle.

=item F<BINMODE()>

Called when binmode() is called on the tied FileHandle returned from
new(). Calls binmode() with the provided parameters on the real
FileHandle. Note that it should not be necessary to use this method
because binmode() is automatically called on the real FileHandle when
open() is called. This is to ensure portability on all systems since
encrypted files will almost certainly contain binary data.

=item F<PRINT()>

=item F<PRINTF()>

=item F<WRITE()>

Called when print(), printf(), or syswrite() is called on the tied
FileHandle returned from new(). Each method will encrypt the data and
write it to the real FileHandle based on the provided cipher. Note
that syswrite() is always utilized to write to the real FileHandle
regardless of the method called.

The number of encrypted bytes written to the real FileHandle may not
be the same as the number of cleartext bytes processed, especially if
a full block of data has not yet been provided. WRITE() will return
the number of cleartext bytes processed, which keeps the encryption
transparent to the caller.

=item F<READLINE()>

=item F<READ()>

=item F<GETC()>

Called when readline() (or <>), sysread(), or getc() is called on the
tied FileHandle returned from new(). Each method will read data from
the real FileHandle and decrypt it based on the provided cipher. Note
that sysread() is always utilized to read from the real FileHandle
regardless of the method called. Data is always read in blocks of
READSIZE bytes. Any data that is read and decrypted but not returned
is stored in an internal buffer to be utilized by future read calls.

READ() will return the number of cleartext bytes processed and not
the actual number of bytes read from the real FileHandle, which keeps
the decryption transparent to the caller.

=item F<TELL()>

Called when tell() is called on the tied FileHandle returned from
new(). Returns the number of cleartext bytes processed through the
tied FileHandle. It does not return the position of the real
FileHandle, which may differ because of the encryption. The logical
position of the data is returned as if a normal FileHandle was used,
which keeps the encryption and decryption transparent to the caller.

=item F<CLOSE()>

Called when close() is called on the tied FileHandle returned from
new(). It closes the real FileHandle. If the real FileHandle was
opened for writing, it calls finish() on the cipher object to
complete the encryption prior to closing the real FileHandle.

=item F<FILENO()>

Called when fileno() is called on the tied FileHandle returned from
new(). Returns the file number of the real FileHandle. Note that this
method is also utilized when opened() is called on the tied
FileHandle. The file number of the real FileHandle is returned to
ensure a call to opened() accurately returns whether or not the file
is actually open or not.

=item F<EOF()>

Called when eof() is called on the tied FileHandle returned from
new(). Returns true if the read calls have reached an end of file
state or if the real FileHandle is closed. Note that the real
FileHandle may have reached end of file when reading, but data may
still exist in the internal buffer, and thus false is returned since
the logical end of file has not yet been reached.

=back

=head1 WARNINGS

The sysopen() method is not supported with a tied FileHandle.

The syswrite() and sysread() methods are always used to write to and
read from real handles. This package cannot be used with handles that
do not support these methods, such as opening directly to a Perl
scalar.

If the salt or randomiv header options are not used in the Crypt::CBC
cipher provided to new(), it is the caller's responsibility to
initialize the decryption cipher appropriately to include any
necessary salt or iv values. Otherwise using the same cipher to both
encrypt and decrypt will be unsuccessful since the salt or iv values
are not included in the encrypted file. When the salt header option
is used, the necessary values are included in the resulting encrypted
file, and can also be decrypted with OpenSSL as shown in the example
below.

=over 4

openssl enc -d -aes-256-cbc -in <file> -k <key>

=back

Due to cipher block chaining (CBC), random access is currently not
permitted with this package. It would likely be necessary to read or
write the entire contents of the file, or large portions of it, to
enable random access. For this reason, the following restrictions
exist.

=over 4



( run in 0.477 second using v1.01-cache-2.11-cpan-e1769b4cff6 )