--- a/bin/imager.check Fri Jul 29 16:06:55 2011 +0200
+++ b/bin/imager.check Sun Jul 31 15:03:06 2011 +0200
@@ -133,6 +133,9 @@
# we don't need uncompressed files if an compressed version
# exists
unlink $_ and return if -f "$_.gz";
+ unlink "$_.x" and return if -f "$_.x.gz";
+
+ # FIXME: do we need a compressed version?
# cut away the first part of the filename and
# some optional extension
@@ -201,7 +204,10 @@
next
if -f "$dir/data/$k"
- or -f "$dir/data/$k.gz";
+ or -f "$dir/data/$k.gz"
+ or -f "$dir/data/$k.x"
+ or -f "$dir/data/$k.x.gz"
+ or -f "$dir/data/$k.gz.x";
say "missing $k @$i";
@invalid{@$i} = ();
}
--- a/bin/imager.restore Fri Jul 29 16:06:55 2011 +0200
+++ b/bin/imager.restore Sun Jul 31 15:03:06 2011 +0200
@@ -16,12 +16,17 @@
use autodie qw(:all);
use Pod::Usage;
use Getopt::Long;
+use Hash::Util qw(lock_keys);
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
use constant KiB => 1024;
use constant MiB => 1024 * KiB;
use constant GiB => 1024 * MiB;
use constant ME => basename $0;
+use constant CIPHER => "aes-128-cbc";
+
+my %o = (pass => "stdin");
+lock_keys(%o);
sub find_data_dir;
@@ -29,8 +34,9 @@
Getopt::Long::Configure(qw(Bundling));
GetOptions(
- "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) },
- "m|man" => sub {
+ "p|pass=s" => \$o{pass},
+ "h|help" => sub { pod2usage(-verbose => 1, -exit => 0) },
+ "m|man" => sub {
pod2usage(
-verbose => 2,
-exit => 0,
@@ -66,7 +72,7 @@
if (-f "$data/$path") {
open($in => "$data/$path");
binmode($in);
- local $/ = \$blocksize;
+ local $/ = undef;
$buffer = <$in>;
}
elsif (-f "$data/$path.gz") {
@@ -75,6 +81,26 @@
gunzip($in => \$buffer)
or die $GunzipError;
}
+ elsif (-f "$data/$path.x") {
+ open($in, "openssl @{[CIPHER]} -d -pass $o{pass} -in '$data/$path.x'|");
+ binmode($in);
+ local $/ = undef;
+ $buffer = <$in>;
+ }
+ elsif (-f "$data/$path.x.gz") {
+ warn "$data/$path.x.gz: depreciated!\n";
+ open($in,
+ "gzip -d -c $data/$path.x.gz | openssl bf -d -pass $o{pass}|");
+ binmode($in);
+ local $/ = undef;
+ $buffer = <$in>;
+ }
+ elsif (-f "$data/$path.gz.x") {
+ open($in, "openssl bf -d -pass $o{pass} -in $data/$path.gz.x|");
+ binmode($in);
+ gunzip($in => \$buffer)
+ or die $GunzipError;
+ }
else {
die ME . ": Can't open $data/$path: $!\n";
}
@@ -100,7 +126,7 @@
=head1 SYNOPSIS
- imager.restore {idx} {destination}
+ imager.restore [options] {idx} {destination}
=head1 DESCRIPTION
@@ -108,5 +134,22 @@
cats them as one data stream. The destination can be any block device,
a file name or even B<-> (STDOUT).
+=head1 OPTIONS
+
+=over
+
+=item B<-p> I<pass> | B<--pass=>I<pass>
+
+In case you expect encrypted data, this option takes the argument for
+B<openssl>'s C<-pass> option. See L<openssl(3)> for mor information.
+(default: stdin)
+
+=item B<-h>|B<--help>
+
+=item B<-m>|B<--man>
+
+The standard help options.
+
+=back
=cut
--- a/bin/imager.save Fri Jul 29 16:06:55 2011 +0200
+++ b/bin/imager.save Sun Jul 31 15:03:06 2011 +0200
@@ -20,6 +20,7 @@
use constant GiB => 1024 * MiB;
use constant NOW => time();
use constant DATETIME => strftime("%Y-%m-%dT%H:%M:%SZ" => gmtime(NOW));
+use constant CIPHER => "aes-128-cbc";
sub get_devsize;
sub get_devname;
@@ -31,6 +32,7 @@
compress => undef,
verbose => undef,
blocksize => 4 * MiB,
+ pass => undef,
);
lock_keys(%o);
@@ -47,6 +49,7 @@
);
},
"z|compress:i" => sub { $o{compress} = $_[1] ? $_[1] : Z_BEST_SPEED },
+ "p|pass=s" => \$o{pass},
"b|blocksize=s" => sub {
given ($_[1]) {
when (/(\d+)G/i) { $o{blocksize} = $1 * GiB };
@@ -137,17 +140,27 @@
my ($file, $ext, $cs);
$file = $cs = md5_hex($buffer);
$file =~ s/(?<fn>(?<prefix>...).*)/$+{prefix}\/$+{fn}/g;
- $ext = $o{compress} ? ".gz" : "";
+ $ext = "";
+ $ext .= $o{compress} ? ".gz" : "";
+ $ext .= $o{pass} ? ".x" : "";
# the extension we do not put into the index
my $log = sprintf "%12d %s %s" => ($. - 1), $cs, $file;
- if (not(-e "$data/$file" or -e "$data/$file.gz")) {
- mkpath dirname("$data/$file.gz");
- my $out = File::Temp->new(
+ if (not(-e "$data/$file"
+ or -e "$data/$file.gz"
+ or -e "$data/$file.x"
+ or -e "$data/$file.gz.x"
+ or -e "$data/$file.x.gz")) {
+ mkpath dirname("$data/$file");
+ my $out = File::Temp->new(
TEMPLATE => ".XXXXXXX",
DIR => dirname("$data/$file")
);
+
+ if ($o{pass}) {
+ open($out, "|openssl @{[CIPHER]} -pass $o{pass} -out $out");
+ }
binmode($out);
if ($o{compress}) {
gzip(
@@ -227,14 +240,18 @@
=over
+=item B<-b> I<blocksize>|B<--blocksize>=I<blocksize>
+
+The blocksize used. (may be suffixed with K, M, G). (default: 4 MiB)
+
+=item B<-p> I<pass> | B<--pass>=I<pass>
+
+Use symmetric encryption for writing the data blocks.
+
=item B<-z> [I<level>]|B<--compress>[=I<level>]
Use compression when writing the blocks to disk. (default: off)
-=item B<-b> I<blocksize>|B<--blocksize>=I<blocksize>
-
-The blocksize used. (may be suffixed with K, M, G). (default: 4 MiB)
-
=item B<-h>|B<--help>
=item B<-m>|B<--man>
@@ -243,4 +260,12 @@
=back
+=head1 PERFORMANCE
+
+Some experiments have shown that if compression and encryption is used,
+about 1/3 of the time is consumed by the encryption, and 2/3 are used
+for compression. The compression is done before(!) encrypting the file,
+since otherwise there is almost no benefit in compressing an encrypted
+file!
+
=cut
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scratch/x.pl Sun Jul 31 15:03:06 2011 +0200
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+use 5.010;
+use strict;
+use warnings;
+use Crypt::CBC;
+use autodie qw(:all);
+use Benchmark qw(:all);
+use IO::Compress::Gzip qw(gzip $GzipError);
+use File::Temp;
+
+my $tmp = File::Temp->new();
+warn "<< $tmp >>\n";
+
+my $cipher0 = Crypt::CBC->new(
+ -key => "x",
+ -keysize => 16,
+ -cipher => 'Blowfish',
+) or die;
+$ENV{X} = "x";
+
+@ARGV = qw(/boot/vmlinuz-2.6.32-5-amd64);
+my $text = join "" => <>;
+
+say length $text;
+
+cmpthese(30 => {
+ 'openssl' => sub { openssl($text) },
+ 'perlssl' => sub { perlssl($text) },
+ }
+);
+
+cmpthese(30 => {
+ 'gzip' => sub { bingzip($text) },
+ 'perlzip' => sub { perlzip($text) },
+ }
+);
+
+sub openssl {
+ open(my $out, "|openssl bf -pass env:X -out $tmp") or die;
+ print $out $_[0];
+ close $out;
+ die $? if $?;
+}
+
+sub perlssl {
+ open(my $out, ">$tmp");
+ print $out $cipher0->encrypt($_[0]);
+ close $out;
+}
+
+sub perlzip {
+ open(my $out, ">$tmp");
+ gzip($_[0] => $out);
+}
+
+sub bingzip {
+ open(my $out, "|gzip -1 >$tmp");
+ print $out $_[0];
+ close $out;
+ die $? if $?
+}