Created
October 9, 2013 21:26
-
-
Save hoehrmann/6908712 to your computer and use it in GitHub Desktop.
Compute a TrueCrypt password from a TrueCrypt password and associated keyfiles.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!perl -w | |
use Modern::Perl; | |
use String::CRC32; | |
use MIME::Base64; | |
use autodie; | |
##################################################################### | |
# Apply keyfiles to TrueCrypt passwords -- TrueCrypt allows users to | |
# specify one or more keyfiles that are applied to user passwords to | |
# make password recovery more difficult. Oddly, many of the popular | |
# TrueCrypt password recovery programs do not support keyfiles. This | |
# tool computes the derived password offline to close that gap. Note | |
# that derived passwords usually contain bytes outside the range of | |
# printable ASCII, and TrueCrypt does not really support passwords | |
# with non-ASCII characters in them, and password recovery tools are | |
# often unable to handle newlines in passwords. At least on Windows | |
# though, with the proper escaping applied the bytes pass through ok, | |
# see the code below. The derived password is printed out with a pre- | |
# fix `base64:` followed by the encoded bytes to be binary-safe. | |
##################################################################### | |
die "Usage: $0 password /path/to/keyfile1 ...\n" unless @ARGV > 1; | |
my ($p, @files) = @ARGV; | |
sub apply_keyfiles_to_password { | |
my ($p, @files) = @_; | |
my $P = $p; | |
my $kpl = 64; | |
my @KP = (0) x ($kpl); | |
if ($kpl > length($P)) { | |
$P .= ("\x00") x ($kpl - length($P)); | |
} | |
for my $keyfile (@files) { | |
my $pool_pos = 0; | |
my $bytes = do { | |
open my $f, '<', $keyfile; | |
binmode $f; | |
# TrueCrypt will read no more than 1 MB of a keyfile | |
local $/ = \1048576; | |
<$f>; | |
}; | |
my $crc = crc32(''); | |
for my $byte (split //, $bytes) { | |
$crc = crc32($byte, $crc); | |
my @digest = split //, pack('N', ~$crc); | |
for my $crc_byte (@digest) { | |
$KP[ $pool_pos++ % $kpl ] += ord($crc_byte); | |
} | |
} | |
} | |
my $pwd = do { | |
my @P = map { ord } split //, $P; | |
for my $ix (0 .. $kpl - 1) { | |
$P[$ix] += $KP[$ix]; | |
} | |
join '', map { chr($_ % (2**8)) } @P; | |
}; | |
} | |
my $pwd = apply_keyfiles_to_password($p, @files); | |
print "base64:" . do { encode_base64($pwd) =~ s/\s+//r }; | |
__END__ | |
use Win32; | |
use Win32::Process; | |
use Win32::ShellQuote qw//; | |
my $quoted_pwd = Win32::ShellQuote::quote_native($pwd); | |
Win32::Process::Create( | |
my $ProcessObj, | |
"TrueCrypt.exe", | |
"/v example.truecrypt /p $quoted_pwd /s /q /l x:", | |
0, | |
NORMAL_PRIORITY_CLASS, | |
"." | |
) or die; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment