Created
April 16, 2009 13:17
-
-
Save jettero/96410 to your computer and use it in GitHub Desktop.
C blowfish demo
This file contains 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
#include <openssl/blowfish.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include "io.h" | |
#define KEYARG 1 | |
#define SRCFILE 2 | |
#define DSTFILE 3 | |
#define MINARGS 2 | |
#define MAXARGS 4 | |
#define IV_SIZE 8 /* this is by definition, only 8 works */ | |
#define IV_PADI 9 // we store an extra byte in here, the number of pad chars on the last block | |
#define BUFFER_SIZE 1024 /* this can be as big as you like, must be a multile of 8 */ | |
#define PADI ivec[IV_SIZE] | |
int main(int argc, char **argv) { | |
BF_KEY key; | |
FILE *input, *output; | |
unsigned char ivec[IV_PADI]; | |
char buffer[BUFFER_SIZE]; | |
char bf_buf[BUFFER_SIZE]; | |
int i, input_len, output_len, err; | |
input = stdin; | |
output = stdout; | |
if( argc < MINARGS || argc > MAXARGS ) { | |
user_error("usage: dec key [input_file] [output_file]\n"); | |
return 1; | |
} | |
if( argc >= SRCFILE+1 ) { | |
if( !(input = fopen( argv[SRCFILE], "r" )) ) { | |
perror(csprintf("error while opening \"%s\" for read", argv[SRCFILE])); | |
exit(1); | |
} | |
if( argc >= DSTFILE+1 ) { | |
if( !(output = fopen( argv[DSTFILE], "w" )) ) { | |
perror(csprintf("error while opening \"%s\" for write", argv[DSTFILE])); | |
exit(1); | |
} | |
} | |
} | |
// we'll need our IV for decrypt | |
if( (input_len = fread(ivec, 1, IV_PADI, input)) != IV_PADI ) | |
die(csprintf("unknown error while reading IV+PADI from input file (errono: %d)", ferror(input))); | |
BF_set_key(&key, strlen(argv[KEYARG]), argv[KEYARG]); | |
while( input_len = fread(buffer, 1, BUFFER_SIZE, input) ) { | |
if( input_len < BUFFER_SIZE ) | |
if( err = ferror(input) ) | |
die(csprintf("unknown error while reading from input file (errono: %d)", err)); | |
BF_cbc_encrypt(buffer, bf_buf, input_len, &key, ivec, BF_DECRYPT); | |
/* | |
** BF_cbc_encrypt(const unsigned char *in, unsigned char *out, | |
** long length, BF_KEY *schedule, unsigned char *ivec, int enc); | |
** | |
** BF_cbc_encrypt() is the Cipher Block Chaining function for Blowfish. It | |
** encrypts or decrypts the 64 bits chunks of in using the key schedule, | |
** putting the result in out. enc decides if encryption (BF_ENCRYPT) or | |
** decryption (BF_DECRYPT) shall be performed. ivec must point at an 8 byte | |
** long initialization vector. | |
*/ | |
if( feof(input) && PADI ) | |
input_len -= PADI; // don't print the pad chars! | |
if( (output_len = fwrite(bf_buf, 1, input_len, output)) < input_len ) | |
die(csprintf("unknown error while writing to output file (errono: %d)", ferror(output))); | |
} | |
if( fclose(input) ) { | |
perror(csprintf("error while closing \"%s\"", argv[SRCFILE])); | |
exit(1); | |
} | |
if( fclose(output) ) { | |
perror(csprintf("error while closing \"%s\"", argv[DSTFILE])); | |
exit(1); | |
} | |
return 0; | |
} |
This file contains 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
#include <openssl/blowfish.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include "io.h" | |
#define KEYARG 1 | |
#define SRCFILE 2 | |
#define DSTFILE 3 | |
#define MINARGS 2 | |
#define MAXARGS 4 | |
#define IV_SIZE 8 /* this is by definition, only 8 works */ | |
#define IV_PADI 9 // we store an extra byte in here, the number of pad chars on the last block | |
#define BUFFER_SIZE 1024 /* this can be as big as you like, must be a multile of 8 */ | |
#define PADI ivec[IV_SIZE] | |
int main(int argc, char **argv) { | |
BF_KEY key; | |
FILE *input, *output; | |
unsigned char ivec[IV_PADI]; | |
char buffer[BUFFER_SIZE]; | |
char bf_buf[BUFFER_SIZE]; | |
int i, input_len, output_len, err; | |
input = stdin; | |
output = stdout; | |
if( argc < MINARGS || argc > MAXARGS ) { | |
user_error("usage: enc key [input_file] [output_file]\n"); | |
return 1; | |
} | |
if( argc >= SRCFILE+1 ) { | |
if( !(input = fopen( argv[SRCFILE], "r" )) ) { | |
perror(csprintf("error while opening \"%s\" for read", argv[SRCFILE])); | |
exit(1); | |
} | |
if( argc >= DSTFILE+1 ) { | |
if( !(output = fopen( argv[DSTFILE], "w" )) ) { | |
perror(csprintf("error while opening \"%s\" for write", argv[DSTFILE])); | |
exit(1); | |
} | |
} | |
} | |
// no need for the ivec to be "cryptographically strong." | |
if( !RAND_pseudo_bytes(ivec, IV_SIZE) ) | |
die(csprintf("unknown error while generating IV (error: %d)", ERR_get_error())); | |
PADI = '\0'; | |
// we'll need our IV for decrypt | |
if( (output_len = fwrite(ivec, 1, IV_PADI, output)) != IV_PADI ) | |
die(csprintf("unknown error while writing IV+PADI to output file (errono: %d)", ferror(output))); | |
BF_set_key(&key, strlen(argv[KEYARG]), argv[KEYARG]); | |
while( input_len = fread(buffer, 1, BUFFER_SIZE, input) ) { | |
if( input_len < BUFFER_SIZE ) | |
if( err = ferror(input) ) | |
die(csprintf("unknown error while reading from input file (errono: %d)", err)); | |
for(i=input_len; input_len%IV_SIZE; i++) { | |
buffer[i] = '.'; | |
input_len++; | |
PADI ++; | |
} | |
BF_cbc_encrypt(buffer, bf_buf, input_len, &key, ivec, BF_ENCRYPT); | |
/* | |
** BF_cbc_encrypt(const unsigned char *in, unsigned char *out, | |
** long length, BF_KEY *schedule, unsigned char *ivec, int enc); | |
** | |
** BF_cbc_encrypt() is the Cipher Block Chaining function for Blowfish. It | |
** encrypts or decrypts the 64 bits chunks of in using the key schedule, | |
** putting the result in out. enc decides if encryption (BF_ENCRYPT) or | |
** decryption (BF_DECRYPT) shall be performed. ivec must point at an 8 byte | |
** long initialization vector. | |
*/ | |
if( (output_len = fwrite(bf_buf, 1, input_len, output)) < input_len ) | |
die(csprintf("unknown error while writing to output file (errono: %d)", ferror(output))); | |
} | |
if( PADI ) { | |
if( fseek(output, IV_SIZE, SEEK_SET) ) { | |
perror(csprintf("error while closing \"%s\"", argv[SRCFILE])); | |
exit(1); | |
} | |
if( fwrite(ivec + IV_SIZE, 1, 1, output) != 1 ) | |
die(csprintf("unknown error while writing PADI to output file (errono: %d)", ferror(output))); | |
} | |
if( fclose(input) ) { | |
perror(csprintf("error while closing \"%s\"", argv[SRCFILE])); | |
exit(1); | |
} | |
if( fclose(output) ) { | |
perror(csprintf("error while closing \"%s\"", argv[DSTFILE])); | |
exit(1); | |
} | |
return 0; | |
} |
This file contains 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
#include <stdio.h> /* fprintf */ | |
#include <stdarg.h> /* vsnprintf */ | |
#include <stdlib.h> /* exit, realloc */ | |
#include "io.h" | |
char *csprintf_tmp = NULL; | |
FILE *cp = NULL; | |
void cleanup_csprintf() { | |
if( csprintf_tmp ) | |
free(csprintf_tmp); | |
} | |
void user_error(const char *error) { | |
fprintf(stderr, "%s\n", error); | |
exit(1); | |
} | |
void __die(const char *f, int l, const char *error) { | |
fprintf(stderr, "[%s:%d] fatal error: %s\n", f, l, error); | |
exit(1); | |
} | |
void __warn(const char *f, int l, const char *error) { | |
fprintf(stderr, "[%s:%d] warning: %s\n", f, l, error); | |
} | |
char * csprintf(const char *fmt, ...) { | |
/* NOTE: I was going to to write this myself, but it was sitting right there | |
** in the vfprintf() manpage -- so cut-and-pasted it. */ | |
int n, size = 100; /* Guess we need no more than 100 bytes. */ | |
char *np; | |
va_list ap; | |
if( csprintf_tmp == NULL ) | |
if ((csprintf_tmp = malloc(size)) == NULL) | |
return NULL; | |
while (1) { | |
/* Try to print in the allocated space. */ | |
va_start(ap, fmt); | |
n = vsnprintf(csprintf_tmp, size, fmt, ap); | |
va_end(ap); | |
/* If that worked, return the string. */ | |
if (n > -1 && n < size) | |
return csprintf_tmp; | |
size *= 2; /* twice the old size */ | |
if ((np = realloc (csprintf_tmp, size)) == NULL) { | |
free(csprintf_tmp); | |
return NULL; | |
} else { | |
csprintf_tmp = np; | |
} | |
} | |
// we never get here | |
} | |
This file contains 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
#ifndef __IO_H__ | |
#define __IO_H__ | |
#define die(X) __die(__FILE__, __LINE__, X); | |
#define warn(X) __warn(__FILE__, __LINE__, X); | |
void __die(const char *file, int parser_line, const char *error); | |
void __warn(const char *file, int parser_line, const char *warning); | |
void user_error(const char *error); | |
char *csprintf(const char *format, ...); | |
void cleanup_csprintf(); // call even if you don't use csprintf... only worth calling once, usually | |
#endif |
This file contains 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
SHELL=/bin/bash | |
key=my key | |
go: clean | |
@ make --no-print-directory `git ls-files | sed 's/$$/.ubf/'` | |
@ for i in *.ubf; do x=`basename $$i .ubf`; ./my_diff.pl $$x $$i; done | |
words.bf: enc | |
./enc "$(key)" $(words) $@ | |
enc: enc.c io.o | |
gcc -o $@ $< -lssl io.o | |
dec: dec.c io.o | |
gcc -o $@ $< -lssl io.o | |
%.o: %.c %.h | |
gcc -o $@ -c $< | |
%.bf: % enc | |
./enc "$(key)" $< $@ | |
%.ubf: %.bf dec | |
./dec "$(key)" $< $@ | |
%.xxd: %.bf | |
xxd $< $@ | |
clean: | |
git clean -dfx |
This file contains 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
#!/usr/bin/perl | |
use strict; | |
use Fcntl qw(:seek); | |
open my $orig, "<", $ARGV[0] or die $!; | |
open my $new, "<", $ARGV[1] or die $!; | |
my $s1 = -s $ARGV[0]; | |
my $s2 = -s $ARGV[1]; | |
my $s1x = sprintf("%07x", $s1); | |
my $s2x = sprintf("%07x", $s2); | |
if( $s1 != $s2 ) { | |
print "$ARGV[0] and $ARGV[1] differ in size by: ", abs($s1-$s2), " bytes\n"; | |
exit; | |
} | |
my $diffx = 10; | |
my $bfs = 1024; | |
my ($bo, $bn, $bor); | |
my $pos = 0; | |
while( $bor = read $orig, $bo, $bfs ) { | |
die $! unless defined $bor; | |
($bor == read $new, $bn, 1024) or die $!; | |
for(0 .. length $bo) { | |
unless( substr($bo, $_, 1) eq substr($bn, $_, 1) ) { | |
my $xp = sprintf("%07x", $pos); | |
print " byte $xp of $ARGV[0] and $ARGV[1] differ\n"; | |
$diffx--; | |
if( $diffx <= 0 ) { | |
print "that's enough ...\n"; | |
exit 1; | |
} | |
} | |
$pos ++; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment