public
Last active

C blowfish demo

  • Download Gist
Makefile
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
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
dec.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
#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;
}
enc.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
#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;
}
io.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#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
}
io.h
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#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
my_diff.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
#!/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 ++;
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.