Re: How to decrypt a file encrypted with vi -x or shell crypt
by PodMaster (Abbot) on Aug 27, 2004 at 10:37 UTC
|
| [reply] |
|
|
From that vim doc page:
The encryption in Vim has not been tested for robustness.
In fact it has, and it was found wanting. There is an efficient known-plaintext attack against PKZIP encryption.
| [reply] |
Re: How to decrypt a file encrypted with vi -x or shell crypt
by tachyon (Chancellor) on Aug 27, 2004 at 15:11 UTC
|
This Inline C widget will do it. It modifies the passed SV C style if it is suitable for decryption, or ignores it if the magic header is missing.
use Inline C;
my $password = "hello";
my $file = "c:/enc.txt";
open F, $file or die $!;
my $data = do{ local $/; <F> };
close F;
print "Before:\n$data\n";
decode( $data, $password );
print "After:\n$data\n";
__END__
__C__
typedef unsigned int ULG;
void decode( SV* str, char *passwd )
{
ULG s,t,v,crc_32_tab[256],keys[3],temp;
STRLEN rawlen;
int decrypted = 0;
char *file, *data;
char *magic = "VimCrypt~01!\0";
#define ROTOR(a) { \
keys[0] = CRC32(keys[0], a); keys[1] += keys[0] & 0xff; \
keys[1] = keys[1] * 134775813L + 1; \
keys[2] = CRC32(keys[2], (int)(keys[1] >> 24)); \
}
#define CRC32(c, b) (crc_32_tab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
file = (char*)SvPV(str, rawlen);
if ( rawlen == 0 ) return; /* we got a null string */
while ( *magic != '\0' ) {
if ( *(magic++) != *(file++) ) return; /* did not find magic h
+eader */
}
for (t=0; t<256; t++) {
v = t;
for (s=0; s<8; s++) v = (v >> 1) ^ ((v & 1) * (ULG)0xedb88320L
+);
crc_32_tab[t] = v;
}
keys[0] = 305419896L; keys[1] = 591751049L; keys[2] = 878082192L;
while (*passwd != '\0') ROTOR(*(passwd++));
data = file;
while( *file != '\0' ) {
temp = 0xffff & (keys[2] | 2);
*file ^= (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
ROTOR(*(file++));
decrypted++;
}
sv_setpvn( str, data, decrypted ); /* modify the passed SV with de
+crypt */
}
| [reply] [d/l] |
|
|
Can this be done as a Perl subroutine rather than an Inline C widget ? Are there advantages in doing it via Inline C ?
Cheers
| [reply] |
|
|
Can this be done as a Perl subroutine rather than an Inline C widget ?
Yes
Are there advantages in doing it via Inline C ?
Yes. The actual Vim code is C so all I did was rip the required code out of Vim and drop it into Inline C. Actually I could not resist cleaning it up a bit but that's another story. Add the fact that C is much faster than doing it in Perl, it is now done in C/XS and I have no desire to port it to Perl just so it can be slower.
Porting is fairly easy, but not trivial. The thing that makes it non trivial is that most encryption code utilises the natural rollover of integer types. Things get a bit odd in Perl in a DWIM sort of way which is not identical to C - as a result you need to know how to fix those issues.
use Inline 'C';
use constant UNSIGNED_MAX => 2**32-1;
printf "Perl: %u\t%s\n", UNSIGNED_MAX, UNSIGNED_MAX;
printf "Perl: %u\t%s\n", (UNSIGNED_MAX+1),(UNSIGNED_MAX+1);
printf "Perl: %u\t%s\n", (UNSIGNED_MAX+2),(UNSIGNED_MAX+2);
func( UNSIGNED_MAX );
__END__
__C__
int func( unsigned int arg ) {
printf( "C: %u\n", arg );
printf( "C: %u\n", arg+1 );
printf( "C: %u\n", arg+2 );
return 0;
}
This shows you the main issue:
Perl: 4294967295 4294967296
Perl: 4294967295 4294967297
Perl: 4294967295 4294967298
C: 4294967295
C: 0
C: 1
As you can see C and Perl produce different results at the rollover point.
| [reply] [d/l] [select] |
Re: How to decrypt a file encrypted with vi -x or shell crypt
by bronto (Priest) on Aug 27, 2004 at 10:18 UTC
|
If vi encrypted the file using crypt, I strongly doubt that your friend could open and read it back a second time... :-)
So, he'd better off searching for vi's encrypting algorithm specification and work on it...
Ciao! --bronto
The very nature of Perl to be like natural language--inconsistant and full of dwim and special cases--makes it impossible to know it all without simply memorizing the documentation (which is not complete or totally correct anyway).
--John M. Dlugosz
| [reply] [d/l] |
|
|
There's crypt(1) and there's crypt(3). I am referring to crypt(1) i.e. the shell command, viz:
User Commands crypt(1)
NAME
crypt - encode or decode a file
SYNOPSIS
crypt [ password ]
DESCRIPTION
crypt encrypts and decrypts the contents of a file. crypt
reads from the standard input and writes on the standard
output. The password is a key that selects a particular
transformation. If no password is given, crypt demands a
key from the terminal and turns off printing while the key
is being typed in. crypt encrypts and decrypts with the same
key:
example% crypt key<clear.file> encrypted.file
example% crypt key<encrypted.file | pr
will print the contents of clear.file.
Files encrypted by crypt are compatible with those treated
by the editors ed(1), ex(1), and vi(1) in encryption mode.
The security of encrypted files depends on three factors:
the fundamental method must be hard to solve; direct search
of the key space must be infeasible; "sneak paths" by which
keys or cleartext can become visible must be minimized.
crypt implements a one-rotor machine designed along the
lines of the German Enigma, but with a 256-element rotor.
Methods of attack on such machines are widely known, thus
crypt provides minimal security.
The transformation of a key into the internal settings of
the machine is deliberately designed to be expensive, that
is, to take a substantial fraction of a second to compute.
However, if keys are restricted to (say) three lower-case
letters, then encrypted files can be read by expending only
a substantial fraction of five minutes of machine time.
Since the key is an argument to the crypt command, it is
potentially visible to users executing ps(1) or a derivative
command. To minimize this possibility, crypt takes care to
destroy any record of the key immediately upon entry. No
doubt the choice of keys and key security are the most
vulnerable aspect of crypt.
FILES
/dev/tty
for typed key
-- I'm Not Just Another Perl Hacker
| [reply] |
|
|
First, you should always say on which OS you are running: there is no crypt on my Linux box, but there is one (with the same man page as yours) on Solaris
Second, you say:
For the time being, I have advised him to backtick the shell's crypt command. I know that this is insecure by way of making the password visible to ps, but this will allow him to develop the rest of the script.
but, wait! The man page also says:
Since the key is an argument to the crypt command, it is
potentially visible to users executing ps(1) or a derivative
command. To minimize this possibility, crypt takes care to
destroy any record of the key immediately upon entry. No
doubt the choice of keys and key security are the most
vulnerable aspect of crypt.
so the problem with ps is limited by the program itself. What you should care of instead is that the algorithm is very easy to break, even with brute force attacks:
crypt implements a one-rotor machine designed along the
lines of the German Enigma, but with a 256-element rotor.
Methods of attack on such machines are widely known, thus
crypt provides minimal security.
Therefore, if the contents of the file are really "sensitive", you really should discard vi - x and look for another option alltogether. There are a bunch of modules on CPAN that let you work with pgp: just choose the one that best fits your needs.
Ciao! --bronto
The very nature of Perl to be like natural language--inconsistant and full of dwim and special cases--makes it impossible to know it all without simply memorizing the documentation (which is not complete or totally correct anyway).
--John M. Dlugosz
| [reply] [d/l] [select] |
Re: How to decrypt a file encrypted with vi -x or shell crypt
by sgifford (Prior) on Aug 27, 2004 at 17:14 UTC
|
You can probably use Expect to give the password to crypt(1) in a secure way. I'd recommend doing that rather than re-implementing crypt(1) in Perl, since it avoids duplication of code.
As others have mentioned, on many systems the encryption provided by crypt(1) is very weak, and will really only stop casual observers from seeing the information in it. For better security, use something like Crypt::Rijndael, although that won't be compatible with vi.
| [reply] |
Re: How to decrypt a file encrypted with vi -x or shell crypt
by iburrell (Chaplain) on Aug 27, 2004 at 17:08 UTC
|
You don't actually need the key to read the files. The Enigma variant used by the old Unix crypt program is so weak that it can be easily broken. The program I have seen to do this is Crypt Breaker's Workbench, available from ftp://ftp.funet.fi/pub/crypt/analysis/cbw.tar.gz.
| [reply] |
Re: How to decrypt a file encrypted with vi -x or shell crypt
by Skeeve (Parson) on Aug 27, 2004 at 10:39 UTC
|
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] |