?? aescrypt.c
字號:
/* * AES Crypt for Linux * Copyright (C) 2007, 2008 * * Contributors: * Glenn Washburn <crass@berlios.de> * Paul E. Jones <paulej@packetizer.com> * Mauro Gilardi <galvao.m@gmail.com> * * This software is licensed as "freeware." Permission to distribute * this software in source and binary forms is hereby granted without a * fee. THIS SOFTWARE IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * THE AUTHOR SHALL NOT BE HELD LIABLE FOR ANY DAMAGES RESULTING FROM * THE USE OF THIS SOFTWARE, EITHER DIRECTLY OR INDIRECTLY, INCLUDING, * BUT NOT LIMITED TO, LOSS OF DATA OR DATA BEING RENDERED INACCURATE. * */#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h> // getopt#include <assert.h>#include <stdlib.h> // malloc#include <time.h> // time#include <iconv.h> // iconv stuff#include <langinfo.h> // nl_langinfo#include <errno.h> // errno#include "aescrypt.h"#include "password.h"#include "version.h"/* * encrypt_stream * * This function is called to encrypt the open data steam "infp". */int encrypt_stream(FILE *infp, FILE *outfp, char* passwd, int passlen){ aes_context aes_ctx; sha256_context sha_ctx; aescrypt_hdr aeshdr; sha256_t digest; unsigned char IV[16]; unsigned char iv_key[48]; int i, j, n; unsigned char buffer[32]; unsigned char ipad[64], opad[64]; time_t current_time; pid_t process_id; FILE *randfp = NULL; unsigned char tag_buffer[256]; // Open the source for random data. Note that while the entropy // might be lower with /dev/urandom than /dev/random, it will not // fail to produce something. Also, we're going to hash the result // anyway. if ((randfp = fopen("/dev/urandom", "r")) == NULL) { perror("Error open /dev/urandom:"); return -1; } // Create the 16-bit IV and 32-bit encryption key // used for encrypting the plaintext file. We do // not trust the rand() function, so we improve on // that by also hashing the random digits and using // only a portion of the hash. This IV and key // generation could be replaced with any good random // source of data. memset(iv_key, 0, 48); for (i=0; i<48; i+=16) { memset(buffer, 0, 32); sha256_starts(&sha_ctx); for(j=0; j<256; j++) { if ((n = fread(buffer, 1, 32, randfp)) != 32) { fprintf(stderr, "Error: Couldn't read from /dev/urandom : %d\n",n); fclose(randfp); return -1; } sha256_update(&sha_ctx, buffer, 32); } sha256_finish(&sha_ctx, digest); memcpy(iv_key+i, digest, 16); } // Write an AES signature at the head of the file, along // with the AES file format version number. buffer[0] = 'A'; buffer[1] = 'E'; buffer[2] = 'S'; buffer[3] = (unsigned char) 0x02; // Version 2 buffer[4] = '\0'; // Reserved for version 0 if (fwrite(buffer, 1, 5, outfp) != 5) { fprintf(stderr, "Error: Could not write out header data\n"); fclose(randfp); return -1; } // Write out the CREATED-BY tag j = 11 + // "CREATED-BY\0" strlen(PROG_NAME) + // Program name 1 + // Space strlen(PROG_VERSION); // Program version ID // Our extension buffer is only 256 octets long, so // let's not write an extension if it is too big if (j < 256) { buffer[0] = '\0'; buffer[1] = (unsigned char) (j & 0xff); if (fwrite(buffer, 1, 2, outfp) != 2) { fprintf(stderr, "Error: Could not write tag to AES file (1)\n"); fclose(randfp); return -1; } strncpy(tag_buffer, "CREATED_BY", 255); tag_buffer[255] = '\0'; if (fwrite(tag_buffer, 1, 11, outfp) != 11) { fprintf(stderr, "Error: Could not write tag to AES file (2)\n"); fclose(randfp); return -1; } sprintf(tag_buffer, "%s %s", PROG_NAME, PROG_VERSION); j = strlen(tag_buffer); if (fwrite(tag_buffer, 1, j, outfp) != j) { fprintf(stderr, "Error: Could not write tag to AES file (3)\n"); fclose(randfp); return -1; } } // Write out the "container" extension buffer[0] = '\0'; buffer[1] = (unsigned char) 128; if (fwrite(buffer, 1, 2, outfp) != 2) { fprintf(stderr, "Error: Could not write tag to AES file (4)\n"); fclose(randfp); return -1; } bzero(tag_buffer, 128); if (fwrite(tag_buffer, 1, 128, outfp) != 128) { fprintf(stderr, "Error: Could not write tag to AES file (5)\n"); fclose(randfp); return -1; } // Write out 0x0000 to indicate that no more extensions exist buffer[0] = '\0'; buffer[1] = '\0'; if (fwrite(buffer, 1, 2, outfp) != 2) { fprintf(stderr, "Error: Could not write tag to AES file (6)\n"); fclose(randfp); return -1; } // We will use an initialization vector comprised of the current time // process ID, and random data, all hashed together with SHA-256. current_time = time(NULL); for(i = 0; i < 8; i++) { buffer[i] = (unsigned char) (current_time >> (i * 8)); } process_id = getpid(); for(i = 0; i < 8; i++) { buffer[i+8] = (unsigned char) (process_id >> (i * 8)); } sha256_starts( &sha_ctx); sha256_update( &sha_ctx, buffer, 16); for (i=0; i<256; i++) { if (fread(buffer, 1, 32, randfp) != 32) { fprintf(stderr, "Error: Couldn't read from /dev/random\n"); fclose(randfp); return -1; } sha256_update( &sha_ctx, buffer, 32); } sha256_finish( &sha_ctx, digest); memcpy(IV, digest, 16); // We're finished collecting random data fclose(randfp); // Write the initialization vector to the file if (fwrite(IV, 1, 16, outfp) != 16) { fprintf(stderr, "Error: Could not write out initialization vector\n"); return -1; } // Hash the IV and password 8192 times memset(digest, 0, 32); memcpy(digest, IV, 16); for(i=0; i<8192; i++) { sha256_starts( &sha_ctx); sha256_update( &sha_ctx, digest, 32); sha256_update( &sha_ctx, (unsigned char*)passwd, (unsigned long)passlen); sha256_finish( &sha_ctx, digest); } // Set the AES encryption key aes_set_key(&aes_ctx, digest, 256); // Set the ipad and opad arrays with values as // per RFC 2104 (HMAC). HMAC is defined as // H(K XOR opad, H(K XOR ipad, text)) memset(ipad, 0x36, 64); memset(opad, 0x5C, 64); for(i=0; i<32; i++) { ipad[i] ^= digest[i]; opad[i] ^= digest[i]; } sha256_starts(&sha_ctx); sha256_update(&sha_ctx, ipad, 64); // Encrypt the IV and key used to encrypt the plaintext file, // writing that encrypted text to the output file. for(i=0; i<48; i+=16) { // Place the next 16 octets of IV and key buffer into // the input buffer. memcpy(buffer, iv_key+i, 16); // XOR plain text block with previous encrypted // output (i.e., use CBC) for(j=0; j<16; j++) { buffer[j] ^= IV[j]; } // Encrypt the contents of the buffer aes_encrypt(&aes_ctx, buffer, buffer); // Concatenate the "text" as we compute the HMAC sha256_update(&sha_ctx, buffer, 16); // Write the encrypted block if (fwrite(buffer, 1, 16, outfp) != 16) { fprintf(stderr, "Error: Could not write iv_key data\n"); return -1; } // Update the IV (CBC mode) memcpy(IV, buffer, 16); } // Write the HMAC sha256_finish(&sha_ctx, digest); sha256_starts(&sha_ctx); sha256_update(&sha_ctx, opad, 64); sha256_update(&sha_ctx, digest, 32); sha256_finish(&sha_ctx, digest); // Write the encrypted block if (fwrite(digest, 1, 32, outfp) != 32) { fprintf(stderr, "Error: Could not write iv_key HMAC\n"); return -1; } // Re-load the IV and encryption key with the IV and // key to now encrypt the datafile. Also, reset the HMAC // computation. memcpy(IV, iv_key, 16); // Set the AES encryption key aes_set_key(&aes_ctx, iv_key+16, 256); // Set the ipad and opad arrays with values as // per RFC 2104 (HMAC). HMAC is defined as // H(K XOR opad, H(K XOR ipad, text)) memset(ipad, 0x36, 64); memset(opad, 0x5C, 64); for(i=0; i<32; i++) { ipad[i] ^= iv_key[i+16]; opad[i] ^= iv_key[i+16]; } // Wipe the IV and encryption mey from memory memset(iv_key, 0, 48); sha256_starts(&sha_ctx); sha256_update(&sha_ctx, ipad, 64); while ((n = fread(buffer, 1, 16, infp)) > 0) { // XOR plain text block with previous encrypted // output (i.e., use CBC) for(i=0; i<16; i++) { buffer[i] ^= IV[i]; } // Encrypt the contents of the buffer aes_encrypt(&aes_ctx, buffer, buffer); // Concatenate the "text" as we compute the HMAC sha256_update(&sha_ctx, buffer, 16); // Write the encrypted block if (fwrite(buffer, 1, 16, outfp) != 16) { fprintf(stderr, "Error: Could not write to output file\n"); return -1; } // Update the IV (CBC mode) memcpy(IV, buffer, 16); // Assume this number of octets is the file modulo aeshdr.last_block_size = n; } // Check to see if we had a read error if (n < 0) { fprintf(stderr, "Error: Couldn't read input file\n"); return -1; } // Write the file size modulo buffer[0] = (char) (aeshdr.last_block_size & 0x0F); if (fwrite(buffer, 1, 1, outfp) != 1) { fprintf(stderr, "Error: Could not write the file size modulo\n"); return -1; } // Write the HMAC sha256_finish(&sha_ctx, digest); sha256_starts(&sha_ctx); sha256_update(&sha_ctx, opad, 64); sha256_update(&sha_ctx, digest, 32); sha256_finish(&sha_ctx, digest); if (fwrite(digest, 1, 32, outfp) != 32) { fprintf(stderr, "Error: Could not write the file HMAC\n"); return -1; } return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -