//This program is free software: you can redistribute it and/or modify it under the terms #of the GNU General Public License as published by the Free Software Foundation, either #version 3 of the License, or (at your option) any later version. //This program is distributed in the hope that it will be useful, but WITHOUT ANY #WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A #PARTICULAR PURPOSE. See the GNU General Public License for more details. //You should have received a copy of the GNU General Public License along with this #program. If not, see /* blowfish.c */ /* blowfish cipher: 64 bit key, 64 bit block by Bruce Schneier */ /* Unless otherwise noted Copyright 1995 Willis E. Howard, III */ /* Willis E. Howard, III email: WEHoward@aol.com mail: POB 1473 Elkhart, IN 46515 */ /* under MSDOS, NMAKE /F BLOWFISH.MAK all clean */ #include #include #include #include "crypt.h" #include "hex.h" #include "blowfish.h" #ifdef big_endian #include #endif #include #include #include #include unsigned int crc (unsigned char , unsigned int ); /* This routine uses the common interface to CRYPT.C. Generally, the name of this module becomes the name of the executable file. */ static int key_defined_blowfish = 0; /* Set to 1 after a valid key has been defined */ static int encrypt_or_decrypt_blowfish = ENCRYPTION_SELECT; static char key_string_blowfish[257]; /* cipher_doc: This array of strings must have two sections: CIPHER that describes the cipher used and KEY that describes how the key is defined and entered. */ static char *cipher_doc[] = { "CIPHER", " The program uses the BLOWFISH cipher by Bruce Schneier.", " A 64 bit key is used to encrypt a 64 bit block.", "", " Because blocks of 8 bytes are processed, files that are not", " a multiple of 8 bytes long may increase slightly in size.", " Decrypted files may have additional spaces at the end.", " Use the -d option for decryption.", "", "KEY", " The key is an ASCII string. If you use more than one", " word in the phrase and give the key with the -k option", " on the command line, place the phrase within quotes.", " At most 72 characters will be used in the phrase.", "", " If a key file exists, only the first line is read, and", " it is used as the key phrase.", "", " If there is no key phrase, you will be prompted for one.", NULL }; char ** crypt_help_blowfish () { return cipher_doc; /* return a pointer to the help strings */ } /* crypt_key: Get the key from the passed string (that may be a file name in some implementations) or from a key file name. Return 0 on success but exit on error. */ int crypt_key_blowfish (int key_type, char *key_text) { int i; char *s; FILE *fp; if (key_type == KEY_FILE) /* a file name has been given */ { if ((fp = fopen (key_text, "r")) == NULL) { key_defined_blowfish = 0; return 0; } s = key_string_blowfish; i = 0; for (;;) { *s = fgetc (fp); if ((*s == '\n') || (*s == EOF)) { *s = '\0'; if (i == 0) { key_defined_blowfish = 0; break; } else { key_defined_blowfish = !InitializeBlowfish(key_string_blowfish, strlen(key_string_blowfish)); break; } } else if (i == 255) { *++s = '\0'; key_defined_blowfish = !InitializeBlowfish(key_string_blowfish, strlen(key_string_blowfish)); break; } s++; i++; } fclose (fp); return 0; } else if (key_type == KEY_IMMEDIATE) /* a key string has been given */ { if (!strcmp (key_text, "?")) /* prompt for key */ { printf ("Key: "); /* input key from stdin */ s = key_string_blowfish; i = 0; for (;;) { *s = fgetc (stdin); if ((*s == '\n') || (*s == EOF)) { *s = '\0'; key_defined_blowfish = !InitializeBlowfish(key_string_blowfish, strlen(key_string_blowfish)); break; } else if (i == 255) { *++s = '\0'; key_defined_blowfish = !InitializeBlowfish(key_string_blowfish, strlen(key_string_blowfish)); break; } s++; i++; } } else /* copy string up to 256 characters */ { strncpy (key_string_blowfish, key_text, 256); key_string_blowfish[256] = '\0'; key_defined_blowfish = !InitializeBlowfish(key_string_blowfish, strlen(key_string_blowfish)); } return 0; } fprintf (stderr, "Error getting key\n"); exit (1); } /* crypt_key_erase: If a local copy of the key has been made, erase it from memory. This increases security that the key can not be obtained from an examination of memory. */ void crypt_key_erase_blowfish () { int i; for (i = 0; i < 257; i++) key_string_blowfish[i] = '\0'; key_defined_blowfish = 0; return; } /* crypt_select: If encryption and decryption require different ciphers, this routine defines the direction. Valid choices are ENCRYPTION_SELECT and DECRYPTION_SELECT. */ int crypt_select_blowfish (int selection) { if (selection == ENCRYPTION_SELECT) { encrypt_or_decrypt_blowfish = ENCRYPTION_SELECT; } if (selection == DECRYPTION_SELECT) { encrypt_or_decrypt_blowfish = DECRYPTION_SELECT; } return encrypt_or_decrypt_blowfish; } /* crypt_file: encrypt or decrypt the source to the destination file. Do not exit from this routine. Return 0 on success and return 1 on error. Use an fprintf(stderr, ... ) to report the nature of the error and close any open files. This allows the main routine to do some cleanup before exiting. */ int crypt_file_blowfish (char *source, char *dest) { int i; int count = 8; /* block size */ char buffer[8]; FILE *infile; FILE *outfile; if(!key_defined_blowfish) qDebug() << endl << "No esta definida la key_blowfish"; while (!key_defined_blowfish){ crypt_key_blowfish (KEY_IMMEDIATE, "?"); } if ((infile = fopen (source, "rb")) == NULL) { fprintf (stderr, "Can not open %s for reading.\n", source); return 1; } if ((outfile = fopen (dest, "wb")) == NULL) { fprintf (stderr, "Can not open %s for writing.\n", dest); fclose (infile); return 1; } for (i = 0; i < count; i++) buffer[i] = (char) 0x20; /* text files padded with spaces */ qDebug() << endl << "Buffer=" << buffer << endl; //qDebug() << endl << "encrypt_or_decrypt_blowfish=" << encrypt_or_decrypt_blowfish; //system("pause"); while (fread (buffer, sizeof (char), count, infile)) { qDebug() << endl << "Buffer=" << buffer << endl; //qDebug() << endl << "encrypt_or_decrypt_blowfish=" << encrypt_or_decrypt_blowfish; //system("pause"); if (encrypt_or_decrypt_blowfish == ENCRYPTION_SELECT) { qDebug()<< "Cifrando"; Blowfish_encipher((unsigned long *) buffer,(unsigned long *) &buffer[4]); } else { Blowfish_decipher((unsigned long *) buffer,(unsigned long *) &buffer[4]); qDebug()<< "Descifrando"; } if (count != fwrite (buffer, sizeof (char), count, outfile)) { qDebug()<< endl << "No puedo escribir"; fprintf (stderr, "Could not write to %s\n", source); fclose (infile); fclose (outfile); return 1; } else { for (i = 0; i < count; i++){ buffer[i] = (char) 0x20; } } } fclose (infile); fclose (outfile); return 0; } /* blowfish.c written by Bruce Schneier */ /* Checksum of subkey file added by Willis E. Howard, III */ #define N 16 #define noErr 0 #define DATAERROR -1 #define KEYBYTES 8 #define subkeyfilename "Blowfish.dat" #define FILECHECKSUM 38491 unsigned long P[N + 2]; unsigned long S[4][256]; FILE *SubkeyFile; short opensubkeyfile (void) /* read only */ { short error; unsigned int i; unsigned int total = 0; if ((SubkeyFile = fopen (subkeyfilename, "rb")) == NULL) { printf("Can not open data file %s\n", subkeyfilename); qDebug() << endl << "No he podido abrir el SubkeyFile"; return DATAERROR; } while ((i = fgetc(SubkeyFile)) != EOF) total = crc ( (char) i, total ); total = crc ( 0, total ); total = crc ( 0, total ); if (total != FILECHECKSUM) { printf("Bad checksum in data file %s\n", subkeyfilename); printf("Checksum was %u, but should be %u\n", total, FILECHECKSUM); fclose(SubkeyFile); return DATAERROR; } fclose(SubkeyFile); if ((SubkeyFile = fopen (subkeyfilename, "rb")) == NULL) { return DATAERROR; } return noErr; } unsigned long F (unsigned long x) { unsigned short a; unsigned short b; unsigned short c; unsigned short d; unsigned long y; d = x & 0x00FF; x >>= 8; c = x & 0x00FF; x >>= 8; b = x & 0x00FF; x >>= 8; a = x & 0x00FF; //y = ((S[0][a] + S[1][b]) ^ S[2][c]) + S[3][d]; y = S[0][a] + S[1][b]; y = y ^ S[2][c]; y = y + S[3][d]; return y; } void Blowfish_encipher (unsigned long *xl, unsigned long *xr) { unsigned long Xl; unsigned long Xr; unsigned long temp; short i; Xl = *xl; Xr = *xr; for (i = 0; i < N; ++i) { Xl = Xl ^ P[i]; Xr = F (Xl) ^ Xr; temp = Xl; Xl = Xr; Xr = temp; } temp = Xl; Xl = Xr; Xr = temp; Xr = Xr ^ P[N]; Xl = Xl ^ P[N + 1]; *xl = Xl; *xr = Xr; } void Blowfish_decipher (unsigned long *xl, unsigned long *xr) { unsigned long Xl; unsigned long Xr; unsigned long temp; short i; Xl = *xl; Xr = *xr; for (i = N + 1; i > 1; --i) { Xl = Xl ^ P[i]; Xr = F (Xl) ^ Xr; /* Exchange Xl and Xr */ temp = Xl; Xl = Xr; Xr = temp; } /* Exchange Xl and Xr */ temp = Xl; Xl = Xr; Xr = temp; Xr = Xr ^ P[1]; Xl = Xl ^ P[0]; *xl = Xl; *xr = Xr; } short InitializeBlowfish (char key[], short keybytes) { short i; short j; short k; short error; short numread; unsigned long data; unsigned long datal; unsigned long datar; /* First, open the file containing the array initialization data */ error = opensubkeyfile (); if (error == noErr) { for (i = 0; i < N + 2; ++i) { numread = fread (&data, 4, 1, SubkeyFile); #ifdef little_endian /* Eg: Intel We want to process things in byte */ /* order, not as rearranged in a longword */ data = ((data & 0xFF000000) >> 24) | ((data & 0x00FF0000) >> 8) | ((data & 0x0000FF00) << 8) | ((data & 0x000000FF) << 24); #endif if (numread != 1) { return DATAERROR; } else { P[i] = data; } } for (i = 0; i < 4; ++i) { for (j = 0; j < 256; ++j) { numread = fread (&data, 4, 1, SubkeyFile); #ifdef little_endian /* Eg: Intel We want to process things in byte */ /* order, not as rearranged in a longword */ data = ((data & 0xFF000000) >> 24) | ((data & 0x00FF0000) >> 8) | ((data & 0x0000FF00) << 8) | ((data & 0x000000FF) << 24); #endif if (numread != 1) { return DATAERROR; } else { S[i][j] = data; } } } fclose (SubkeyFile); j = 0; for (i = 0; i < N + 2; ++i) { data = 0x00000000; for (k = 0; k < 4; ++k) { data = (data << 8) | key[j]; j = j + 1; if (j >= keybytes) { j = 0; } } P[i] = P[i] ^ data; } datal = 0x00000000; datar = 0x00000000; for (i = 0; i < N + 2; i += 2) { Blowfish_encipher (&datal, &datar); P[i] = datal; P[i + 1] = datar; } for (i = 0; i < 4; ++i) { for (j = 0; j < 256; j += 2) { Blowfish_encipher (&datal, &datar); S[i][j] = datal; S[i][j + 1] = datar; } } } else { printf ("Unable to open subkey initialization file : %d\n", error); } return error; } /* crc from PGP - update 16-bit CRC: X^16 + X^12 + X^5 + 1 */ unsigned int crc (unsigned char nuevo, unsigned int value) { unsigned int shift, flag, data; data = ((unsigned int) nuevo) & 0xff; for (shift = 0x80; shift; shift >>= 1) { flag = (value & 0x8000); value <<= 1; value |= ((shift & data) ? 1 : 0); if (flag) value ^= 0x1021; } return (value & 0xffff); }