in reply to password protect Word, PDF, etc documents

Well, you need a program to encrypt your doc, using a method that allow the decrypt. I made some test for fun with encrypters some time ago.

I'm sending a script that you can use in your docs. This use a key of numbers to move the bits to another position, bit by bit. The code was fully on Perl, can be slow in big files, since an encrypter normally is writed in C.

When you encrypt a doc NEVER lose the key number!!! Or you can decrypt it anymore! You can change some flags of the program, like the block size, and the key number will only work with the same flags used in the main encrypter.

This program was based in the idea (move bits) of ABC1 (A Bit Cypher program) published in IBM AlphaWorks. And I put the name James Bond, don't laughs! ;-P

This script is only for educational purpose, don't use it for malicious ways. And you can find better things on the Internet too...

"The creativity is the expression of the liberty".

To run just type: perl bond.pl
and fallow the promp, or use the -h flag for help.
SOURCE follows...
#!/usr/bin/perl ################################## # JAMES BOND ENCRYPTER/DECRYPTER # ################################## # By: Graciliano Monteiro Passos # # E-mail: gm@...spam_sux.... # # URL: www.virtuasites.com.br # # # # Created 3/22/2002 03:33H # # # # Copyright 2002 Virtua Sites. # # All rights reserved. # ################################## $|=1; ###################################################################### +######## # Based in the ABC1 (A Bit Cypher program) idea. Published in IBM alph +aWorks # ###################################################################### +######## # $file = '3.bmp' ; # $james_do = 'enc' ; #$data_key = '123' ; # $block_sz = 1024 ; #$data = 'data test' ; ######## # ARGS # ######## if ($#ARGV >= 0) { $james_do = $ARGV[0] || 'enc' ; $file = $ARGV[1] ; $data_key = $ARGV[2] || int(100000 + rand(999999)) ; $block_sz = $ARGV[3] || 1024 ; if ($james_do =~ /^-e/i ) { $james_do = 'enc' ;} elsif ($james_do =~ /^-d/i ) { $james_do = 'dec' ;} elsif ($james_do =~ /^-(p|h)/i ) { ;} else {$james_do = '-h' ;} } elsif ($data eq '') { $james_do = '-p' ;} ######## # HELP # ######## if ($james_do =~ /^-h/i) { print qq` _____________________________________________________________ JAMES BOND CRYTER 1.1 Based in the ABC1 (A Bit Cypher program) idea. Published in IBM alphaWorks _____________________________________________________________ Usage: -e %file %key %block_size >> Encrypt. -d %file %key %block_size >> Decrypt. Examples: 1> bond.pl -e data.txt 123abc 2> bond.pl -d data.txt.enc 123abc Detail: - The key can use letters. They ill be converted to the char number. - %block_size option (def: 1024) is the amount of bytes of each block to crypt. If you use a number not equal than 1024, you need to input the size in the decoder too! By: Graciliano M. P. URL: http://www.virtuasites.com Copyright 2002 Virtua Sites. All rights reserved. Have a nice day! :) _____________________________________________________________ `; exit ; } ########## # PROMPT # ########## if ($james_do =~ /^-p/i) { my ($prompt_do , $prompt_file , $prompt_key , $prompt_size, $prompt_ru +n); print qq` _____________________________________________________________ JAMES BOND CRYTER 1.1 `; $prompt_do = &prompt('encrypt/decrypt?','e',e,d); if ($prompt_do =~ /^d/i) { $prompt_do = 'dec' ;} else { $prompt_do = 'enc' ;} $prompt_file = &prompt('File',''); $prompt_file =~ s/\s//g ; if (! -e $prompt_file) { print " ** Can't find file $prompt_file\n" ; exit; } $prompt_key = &prompt('Key',int(100000 + rand(999999999))); $prompt_key =~ s/\s//g ; $prompt_size = &prompt('Block size','1024'); if ($prompt_size !~ /^\d+$/) { $prompt_size = 1024 ;} $prompt_run = &prompt('Run','y','y','n') ; print "_____________________________________________________________\n +\n" ; if ( $prompt_run =~ /^y/i ) { $file = $prompt_file ; $james_do = $prompt_do ; $data_key = $prompt_key ; $block_sz = $prompt_size ; } else { exit ;} } ########## # PROMPT # ########## sub prompt { my ( $msg , $def , @opt) = @_ ; my $prompt ; my $p_msg = " $msg " ; if ($#opt >= 0) { $p_msg .= "<". join (",", @opt) ; } if ($def ne '') { if ($#opt >= 0) { $p_msg .= ">" ;} $p_msg .= "<$def" ; } $p_msg .= "> " ; while($prompt eq '') { print $p_msg ; chop($prompt = <STDIN>); if ($prompt eq '' && $def ne '') { $prompt = ' ' ;} elsif ($#opt >= 0) { my $clean = 1 ; foreach my $opt_i ( @opt ) { if ($prompt =~ /^$opt_i$/i) { $prompt = $opt_i ; $clean = 0 ;} } if ($clean == 1) { $prompt = '' ;} } } if ($prompt =~ /^\s+$/ ) { $prompt = $def ;} print " <$prompt>\n\n" ; return( $prompt ) ; } ############# # DATA FILE # ############# $do_msg = 'data' ; if (-e $file && $file ne '') { $do_msg = $file ; open (LOG,$file) ; binmode(LOG); $data = join '' , <LOG> ; close (LOG) ; } ######## # INIT # ######## print "\n" ; if ($james_do =~ /^dec/i) { print " Decrypting... $do_msg\n " ; $james_data = &james_decrypt($data,$data_key) ; if ($file ne '') { if ($file =~ /\.enc\.(\w+)$/i ) { my $ext = $1 ; $file =~ s/\.enc\.\w+$//i ; $file_new = "$file.dec.$ext" ; } else { $file_new = "$file.dec" ;} } } elsif ($james_do =~ /^enc/i) { print " Encrypting... $do_msg\n " ; $james_data = &james_encrypt($data,$data_key); if ($file ne '') { my ($ext) = ( $file =~ /\.(\w+)$/g ); $file =~ s/\.$ext$// ; $file_new = "$file.enc.$ext" ; } } ########## # OUT UP # ########## if ($file_new ne '') { open (LOG,">$file_new") ; binmode(LOG); print LOG $james_data ; close (LOG) ; print "\n\n New data saved in file: $file_new\n" ; } else { print "\n New code -> $james_data\n" ; } print " KEY: $data_key\n" ; print " BLock size: $block_sz\n" ; ################# # JAMES_DECRYPT # ################# sub james_decrypt { my ( $data , $data_key ) = @_ ; my $data_new ; my $data_lng = length($data) ; $get_key_n = 0 ; for (my $i = 0 ; $i < $data_lng ;) { $p++; print "." ; if ($p =~ /\d0$/ ) { print "\n " ;} my $block = substr($data,$i,$block_sz) ; $i += $block_sz ; my $bits = get_bit($block); my $bits_lng = length($bits) - 1; my @bits = split("" , $bits) ; my @new_bits = ('') x ($bits_lng+1) ; my @dec_bits = ('') x ($bits_lng+1) ; my $c = -1 ; for (my $j = 0 ; $j <= $bits_lng ; $j++) { $c++; @bits[$j] = '' ; my $bt = substr($bits,$j,1) ; my $key_n = &get_key_n($data_key) ; my $pos = get_bit_pos($key_n,$j,$bits_lng) ; while(@new_bits[$pos] ne '') { $pos++ ; if ($pos > $bits_lng) { $pos = 0 ;} } @new_bits[$pos] = $bt ; @dec_bits[$j] = substr($bits,$pos,1) ; if ($c >= $bits_lng) { last ;} } my $new_bytes = &make_bytes( join ("", @dec_bits) ) ; $data_new .= $new_bytes ; } return( $data_new ) ; } ################# # JAMES_DECRYPT # ################# sub james_encrypt { my ( $data , $data_key ) = @_ ; my $data_new ; my $data_lng = length($data) ; $get_key_n = 0 ; for (my $i = 0 ; $i < $data_lng ;) { $p++; print "." ; if ($p =~ /\d0$/ ) { print "\n " ;} my $block = substr($data,$i,$block_sz) ; $i += $block_sz ; my $bits = get_bit($block); my $bits_lng = length($bits) - 1; my @bits = split("" , $bits) ; my @new_bits = ('') x ($bits_lng+1) ; my $c = -1 ; for (my $j = 0 ; $j <= $bits_lng ; $j++) { $c++; @bits[$j] = '' ; my $bt = substr($bits,$j,1) ; my $key_n = &get_key_n($data_key) ; my $pos = get_bit_pos($key_n,$j,$bits_lng) ; while(@new_bits[$pos] ne '') { $pos++ ; if ($pos > $bits_lng) { $pos = 0 ;} } @new_bits[$pos] = $bt ; if ($c >= $bits_lng) { last ;} } my $new_bytes = &make_bytes( join ("", @new_bits) ) ; $data_new .= $new_bytes ; } return( $data_new ) ; } ############### # GET_BIT_POS # ############### sub get_bit_pos { my ( $key_n , $pos , $size) = @_ ; my $new = $pos + ($key_n * $pos) ; #my $new = $pos / (1 + $key_n) ; while($new > $size) { $new -= $size ;} while($new < 0) { $new += $size ;} return( $new ) ; } ############# # GET_KEY_N # ############# sub get_key_n { my ($data_key) = @_ ; $get_key_n++ ; if ($get_key_n >= length($data_key)) { $get_key_n = 0 ;} my $n = substr($data_key,$get_key_n,1) ; if ($n =~ /\D/) { $n = unpack("C", $n) ;} return( $n ) ; } ########### # GET_BIT # ########### sub get_bit { my ( $s ) = @_ ; my $bit = unpack("b*", $s) ; return( $bit ) ; } ############## # MAKE_BYTES # ############## sub make_bytes { my ( $bits ) = @_ ; my $byte = pack("b*", $bits) ; return( $byte ) ; } ####### # END # ####### exit;

Edited ~Sun Jul 28 18:45:31 2002 (GMT), by footpad - Added <READMORE> tag, per Consideration.

  • Comment on Re: password protect. (with James Bond encrypter/decrypter source)
  • Download Code

Replies are listed 'Best First'.
I'm sorry, Mr. Bond
by no_slogan (Deacon) on Jul 27, 2002 at 23:27 UTC
    ...but your code has been broken. Below is a simple known plaintext attack which "nearly" recovers the encryption key, given a block of encrypted data and a few known plaintext bytes. It's generally not difficult to get ahold of the known plaintexts, especially if you're encrypting files like Word docs that have a fixed header.

    You say your program was "based on the ABC1 idea." I don't know how close the resemblence is, but I'd like to point out that changing a cipher even slightly can destroy its security.

    Here's the sample output. Notice that, for each key byte, the correct value is one of the given possibilities.

    Secret key is 'Shaken'
    Guessing key bytes
    key byte 0
    'S' : 10
    key byte 1
    '#' : 9
    'h' : 10
    key byte 2
    '/' : 10
    '3' : 9
    'F' : 10
    'N' : 9
    'a' : 11
    key byte 3
    'k' : 11
    'o' : 9
    key byte 4
    'F' : 9
    '[' : 9
    'e' : 11
    'o' : 9
    key byte 5
    'a' : 9
    'n' : 10
    
    And here's the code. It needs to know the block size and the length of the encryption key. That information might not be available, but it's easy enough to find by brute force.

    #!/usr/bin/perl use strict; use warnings; # this information is known to the attacker my ($ciphertext, $known_plaintext, $keylen); { # secret stuff in here my $key = "Shaken"; print "Secret key is '$key'\n"; $keylen = length($key); open F, $0 or die; # read test data from this script - why not? my $plaintext; read F, $plaintext, 1024 or die; close F; $known_plaintext = substr($plaintext, 0, 8); $ciphertext = encrypt_blk($plaintext, $key); } # secret stuff in here print "Guessing key bytes\n"; my $plain_bits = length($known_plaintext)*8; my $cipher_bits = length($ciphertext)*8 - 1; foreach my $keypos (0 .. $keylen-1) { print "key byte $keypos\n"; my $first = $keypos > 1 ? $keypos - 1 : $keylen + $keypos - 1; foreach my $keybyte (0x20 .. 0x7e) { my $keyval = ($keybyte >= 0x30 && $keybyte <= 0x39) ? $keybyte-0x2f : $keybyte+1; my $hits = 0; my $trials = 0; for (my $bitpos = $first; $bitpos < $plain_bits; $bitpos += $keyle +n) { my $pos = ($bitpos * $keyval) % $cipher_bits; $trials++; $hits++ if vec($known_plaintext,$bitpos,1) == vec($ciphertext,$p +os,1); } my $thresh = int($trials * .8); print "'",chr($keybyte),"' : $hits\n" if $hits > $thresh; } } sub encrypt_blk { my ($inblk, $key) = @_; my @key = map { (/\d/ ? $_ : ord) + 1 } split(//, $key); my $blkbytes = length($inblk); my $blkbits = $blkbytes * 8; my $outblk = "\0" x $blkbytes; my $used = "\0" x $blkbytes; my $keypos = 0; my $newpos; for (my $blkpos = 0; $blkpos < $blkbits; $blkpos++) { ++$keypos >= @key and $keypos = 0; $newpos = ($key[$keypos] * $blkpos) % ($blkbits - 1); while (vec($used, $newpos, 1)) { ++$newpos >= $blkbits and $newpos = 0; } vec($used, $newpos, 1) = 1; vec($outblk, $newpos, 1) = vec($inblk, $blkpos, 1); } return $outblk; } # encrypt_blk
    Update: The DMCA can byte me. Show me where this cipher is used to "effectively control access to a copyrighted work." Cryptography is perfectly legal, and I'm getting tired of hearing from you fear-mongers.
      Cool! I liked what you made, and you are right, documents like word, pdf, have the same header, and using this information we can use brute force to get the headers, and geting the headers we can get the rest. But if we use another block size (not 1024, the default) and a key with 20+ digits will be very difficult. To make a better cipher we can just add something to mask the headers too, or encrypt again the data!

      The James Bond cipher are not based in the source of the ABC1, just in the idea to move bits.

      But remember, I made this for fun, this is the only cipher that I made! I never used this for real, because I don't have top secret things! Every thing that I made is for Open Source. Why I will encrypt what I will publish for the world!?

      "The hardest door to breack is the door that we don't need to open".

      And "no_slogan", DMCA can't kill our liberty of expression. Nice code! And Cryptography is legal, because without it internet can't exist.

      "The creativity is the expression of the liberty".
        I like your attitude, so I gave you a ++. Some people get really touchy about their home-grown ciphers. It might be a good idea to include a comment on your thoughts about the cipher's strength, if you're going to be distributing it.

        ...a key with 20+ digits will be very difficult.
        The central problem with your cipher is that there is very little diffusion of key information, which allows me to attack the key bytes one at a time. Adding more key bytes only results in a linear increase in the difficulty of attack. In a properly diffused cipher, it would increase exponentially. Of course, more key bytes means more diffusion required... take a look at CAST5 or AES sometime. There's a lot to be learned by looking at existing ciphers, even though they appear very confusing.
    A reply falls below the community's threshold of quality. You may see it by logging in.