Beispiel #1
0
/**
 * Computes the SHA1 on the contents of the provided file.
 * @param filename The name of the file to process.
 */
void hash_file_sha1(char* filename) {
    int file = open(filename, O_RDONLY | O_SHLOCK);
    if (file == -1) {
        fprintf(stderr, "Unable to open file %s: %s\n", filename, strerror(errno));
        return;
    }

    SHA1_Context sha1;
    SHA1_init(&sha1);

    int bytesRead;
    unsigned char data[1024];
    while ((bytesRead = read(file, data, 1024)) != 0) {
        SHA1_update(&sha1, data, bytesRead);
    }

    unsigned char result[20];
    SHA1_final(&sha1, result);

    close(file);

    printf("  ");
    for (int i = 0; i < 20; ++i) {
        printf("%02x", result[i]);
    }

    printf(" %s\n", filename);
}
Beispiel #2
0
	hasher::hasher()
	{
#ifdef TORRENT_USE_GCRYPT
		gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
#elif TORRENT_USE_COMMONCRYPTO
		CC_SHA1_Init(&m_context);
#elif defined TORRENT_USE_OPENSSL
		SHA1_Init(&m_context);
#else
		SHA1_init(&m_context);
#endif
	}
Beispiel #3
0
	hasher::hasher(const char* data, int len)
	{
		TORRENT_ASSERT(data != 0);
		TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
		gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
		gcry_md_write(m_context, data, len);
#elif TORRENT_USE_COMMONCRYPTO
		CC_SHA1_Init(&m_context);
		CC_SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#elif defined TORRENT_USE_OPENSSL
		SHA1_Init(&m_context);
		SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#else
		SHA1_init(&m_context);
		SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
	}
Beispiel #4
0
	hasher::hasher()
	{
#ifdef TORRENT_USE_LIBGCRYPT
		gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
#elif TORRENT_USE_COMMONCRYPTO
		CC_SHA1_Init(&m_context);
#elif TORRENT_USE_CRYPTOAPI
		if (CryptCreateHash(get_crypt_provider(), CALG_SHA1, 0, 0, &m_context) == false)
		{
#ifndef BOOST_NO_EXCEPTIONS
			throw system_error(error_code(GetLastError(), system_category()));
#else
			std::terminate();
#endif
		}
#elif defined TORRENT_USE_LIBCRYPTO
		SHA1_Init(&m_context);
#else
		SHA1_init(&m_context);
#endif
	}
Beispiel #5
0
int ProcessAsyncRequest(JobDetails* job) {
    /* Variables to hold our options. */
    char doCRC32 = 0;
    char doMD5 = 0;
    char doSHA1 = 0;
    char doED2k = 0;

    /* Standard variables (same between platforms) */
    CRC32_Context crc32;
    MD4_Context ed2k;
    MD5_Context md5;
    SHA1_Context sha1;
    Block* blocks = job->blocks;
    uint8_t  block = 0;
    uint32_t ed2kBlockIdx = 0;
    uint32_t ed2kBlocks = 0;
    unsigned char* ed2kHashes = NULL;
    uint32_t ed2kHashLength = 0;
    uint8_t  ed2kLoopIdx = 0;
    uint64_t position = 0;
    uint32_t progressLoopCount = 0;
    uint64_t totalBytesRead = 0;
    BOOL result = FALSE;

    /* Set our options */
    doCRC32 = job->request->options & OPTION_CRC32;
    doMD5 = job->request->options & OPTION_MD5;
    doSHA1 = job->request->options & OPTION_SHA1;
    doED2k = job->request->options & OPTION_ED2K;

    if (doED2k) {
        /* Determine the number of blocks needed for calculating the file's
         * ED2k's hash. If the file isn't an even multiple of BLOCKSIZE then we
         * add one more block. */
        ed2kBlocks = (uint32_t)((uint64_t)job->size / BLOCKSIZE);
        if (job->size % BLOCKSIZE > 0) {
            ++ed2kBlocks;
        }

        /* Only allocate an array if we have more than one block to hash.
         * Files that are smaller in size than BLOCKSIZE simply use the normal
         * computed MD4 hash. */
        if (ed2kBlocks > 1) {
            ed2kHashLength = ed2kBlocks * 16;
            ed2kHashes = (unsigned char*)HeapAlloc(
                job->heap,
                HEAP_ZERO_MEMORY,
                ed2kHashLength);

            if (ed2kHashes == NULL) {
                return -6;
            }
        }
    }
    if (doCRC32) { CRC32_init(&crc32); }
    if (doMD5) { MD5_init(&md5); }
    if (doSHA1) { SHA1_init(&sha1); }

    /* Issue our initial read requests. */
    for (block = 0; block < MAX_REQUESTS && position <= job->size; ++block) {
        blocks[block].overlapped.Offset = LOPOS(position);
        blocks[block].overlapped.OffsetHigh = HIPOS(position);

        result = ReadFile(
            job->file,
            blocks[block].data,
            BUFFERSIZE,
            NULL,
            &blocks[block].overlapped);
        if (!result && GetLastError() != ERROR_IO_PENDING) {
            if (ed2kHashes) {
                HeapFree(job->heap, 0, ed2kHashes);
            }

            return -8;
        }

        position += BUFFERSIZE;
    }

    block = 0;
    while (TRUE) {
        uint32_t bytesRead = 0;
        int getLastError = 0;

        /* Use the mask to determine which block we'll process next. */
        block = block % MAX_REQUESTS;

        /* Get the results of the asynchronous read. */
        result = GetOverlappedResult(
            job->file, &blocks[block].overlapped, &bytesRead, TRUE);
        getLastError = GetLastError();

        /* Check to see if we reached the end of the file. */
        if (!result && getLastError == ERROR_HANDLE_EOF) {
            break;
        }

        /* This scenario should never happen, but check for it anyway. */
        if (!result && getLastError == ERROR_IO_INCOMPLETE) {
            continue;
        }

        /* Any other error is a failure, so bail out. */
        if (!result) {
            if (ed2kHashes) {
                HeapFree(job->heap, 0, ed2kHashes);
            }

            return -8;
        }

        /* Update the total bytes read and inform the callback of our progress
         * if it's time. Don't forget to bail out if they request it. */
        totalBytesRead += bytesRead;
        if (job->callback && progressLoopCount % 10 == 0) {
            int32_t result = job->callback(job->request->tag, totalBytesRead);
            if (result != 0) {
                if (ed2kHashes) {
                    HeapFree(job->heap, 0, ed2kHashes);
                }

                return -9;
            }
        }

        ++progressLoopCount;

        /* Update the hashes with the file data. */
        if (doED2k) {
            /* If we've looped 10 times, finish the current MD4 hash, update
             * the block counter and set the hash to be initialized again.
             * Also, if the BUFFERSIZE is ever changed, the loop index will
             * need to be adjusted as well. */
            if (ed2kLoopIdx == 10) {
                MD4_final(&ed2k, &ed2kHashes[ed2kBlockIdx * 16]);
                ++ed2kBlockIdx;
                ed2kLoopIdx = 0;
            }

            /* If this is the first loop (or we've just finished a hash)
             * initialize the MD4 hash for the next block. */
            if (ed2kLoopIdx == 0) {
                MD4_init(&ed2k);
            }

            ++ed2kLoopIdx;
            MD4_update(&ed2k, blocks[block].data, bytesRead);
        }
        if (doCRC32) { CRC32_update(&crc32, blocks[block].data, bytesRead); }
        if (doMD5) { MD5_update(&md5, blocks[block].data, bytesRead); }
        if (doSHA1) { SHA1_update(&sha1, blocks[block].data, bytesRead); }

        /* Update our position in the file and issue a new request if there's
         * still more data to read. */
        blocks[block].overlapped.Offset = LOPOS(position);
        blocks[block].overlapped.OffsetHigh = HIPOS(position);

        result = ReadFile(
            job->file,
            blocks[block].data,
            BUFFERSIZE,
            NULL,
            &blocks[block].overlapped);
        if (!result && GetLastError() != ERROR_IO_PENDING) {
            if (ed2kHashes) {
                HeapFree(job->heap, 0, ed2kHashes);
            }

            return -8;
        }

        /* Update our position in the file and the next block to read. */
        position += BUFFERSIZE;
        ++block;
    }

    if (job->callback) {
        job->callback(job->request->tag, totalBytesRead);
    }

       /* Finalize all of the hashes that were selected and store the results in
     * the request result buffer. The order of the hashes are:
     *     0 - 15: ED2k
     *    16 - 19: CRC32
     *    20 - 35: MD5
     *    36 - 55: SHA1 */
    if (doED2k) {
        /* If we just had one block to process directly store the result of the
         * block in the result buffer. */
        if (ed2kBlocks == 1) {
            MD4_final(&ed2k, &job->request->result[0]);
        } else {
            /* Check to see if we were in the middle of a loop and finalize the
             * final pending block if we were. */
            if (ed2kLoopIdx > 0) {
                MD4_final(&ed2k, &ed2kHashes[ed2kBlockIdx * 16]);
            }

            /* Calculate the MD4 hash of the concatenated hashes from each ED2k
             * block. The resulting hash is the final ED2k hash. */
            MD4_init(&ed2k);
            MD4_update(&ed2k, ed2kHashes, ed2kHashLength);
            MD4_final(&ed2k, &job->request->result[0]);

            /* Don't forget to free our ED2k buffer. */
            HeapFree(GetProcessHeap(), 0, ed2kHashes);
        }
    }
    if (doCRC32) { CRC32_final(&crc32, &job->request->result[16]); }
    if (doMD5) { MD5_final(&md5, &job->request->result[20]); }
    if (doSHA1) { SHA1_final(&sha1, &job->request->result[36]); }

    return 0;
}
Beispiel #6
0
/**
 * Accepts a HashRequest structure and attempts to calculate the requested hash
 * of the provided file using synchronous IO.
 */
int HashFileWithSyncIO(HashRequest* request, HashProgressCallback* callback) {
    /* Variables to hold our options. */
    char doCRC32 = 0;
    char doMD5 = 0;
    char doSHA1 = 0;
    char doED2k = 0;

    /* Standard variables (same between platforms) */
    CRC32_Context crc32;
    MD4_Context ed2k;
    MD5_Context md5;
    SHA1_Context sha1;
    uint32_t bytesRead = 0;
    uint32_t ed2kBlockIdx = 0;
    uint32_t ed2kBlocks = 0;
    uint32_t ed2kHashLength = 0;
    uint8_t  ed2kLoopIdx = 0;
    uint32_t progressLoopCount = 0;
    uint64_t totalBytesRead = 0;
    unsigned char* ed2kHashes = NULL;
    unsigned char* fileData = NULL;

    /* Platform specific variables */
    HANDLE file = NULL;
    WIN32_FILE_ATTRIBUTE_DATA fileAttributeData = { 0 };
    BOOL readFailed = FALSE;
    FILE_IO_PRIORITY_HINT_INFO priorityHint = { 0 };


    /* Simple guard condition. If we have no request, we can't process. */
    if (request == NULL) {
        return -1;
    }

    /* clear the result buffer */
    SecureZeroMemory(&request->result, 56);

    /* Set our options */
    doCRC32 = request->options & OPTION_CRC32;
    doMD5 = request->options & OPTION_MD5;
    doSHA1 = request->options & OPTION_SHA1;
    doED2k = request->options & OPTION_ED2K;

    /* If they didn't pass any valid options (or passed 0) for the options,
     * return since we can't calculate a hash without knowing which hashing
     * algorithm(s) to use. */
    if (!doCRC32 && !doMD5 && !doSHA1 && !doED2k) {
        return -2;
    }

    file = CreateFileW(
        request->filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN,
        NULL);
    if (file == INVALID_HANDLE_VALUE) {
        return -4;
    }

    /* Set our file priority hint to background. This is only a hint to Windows
     * that our file IO should be secondary to other scheduled IO. If there is
     * no other IO at the time, it will run at full speed. */
    priorityHint.PriorityHint = IoPriorityHintVeryLow;
    SetFileInformationByHandle(
        file,
        FileIoPriorityHintInfo,
        &priorityHint,
        sizeof(priorityHint));

    /* Set up our hashes, also calculate the space needed for the ED2k hash if
     * we were requested to produce an ED2k hash result. */
    if (doED2k) {
        BOOL result = 0;
        uint64_t fileSize = 0;

        result = GetFileAttributesExW(
            request->filename,
            GetFileExInfoStandard,
            &fileAttributeData);

        if (!result) {
            CloseHandle(file);
            return -5;
        }

        /* Convert the file size from two 32-bit DWORDS to a uint64_t. */
        fileSize =
            (((uint64_t)fileAttributeData.nFileSizeHigh) << 32) |
            fileAttributeData.nFileSizeLow;

        /* Determine the number of blocks needed for calculating the file's
         * ED2k's hash. If the file isn't an even multiple of BLOCKSIZE then we
         * add one more block. */
         ed2kBlocks = (uint32_t)((uint64_t)fileSize / BLOCKSIZE);
         if (fileSize % BLOCKSIZE > 0) {
            ++ed2kBlocks;
         }

        /* Only allocate an array if we have more than one block to hash.
         * Files that are smaller in size than BLOCKSIZE simply use the normal
         * computed MD4 hash. */
        if (ed2kBlocks > 1) {
            ed2kHashLength = ed2kBlocks * 16;
            ed2kHashes = (unsigned char*)HeapAlloc(
                GetProcessHeap(),
                HEAP_ZERO_MEMORY,
                ed2kHashLength);
            if (ed2kHashes == NULL) {
                CloseHandle(file);
                return -6;
            }
        }
    }
    if (doCRC32) { CRC32_init(&crc32); }
    if (doMD5) { MD5_init(&md5); }
    if (doSHA1) { SHA1_init(&sha1); }

    /* Allocate the file buffer. The BUFFERSIZE constant is a clean multiple of
     * the BLOCKSIZE for ED2k hashing, which will make for easier looping. */
    fileData = (unsigned char*)HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        BUFFERSIZE);
    if (fileData == NULL) {
        CloseHandle(file);
        if (doED2k && ed2kHashes) {
            HeapFree(GetProcessHeap(), 0, ed2kHashes);
        }

        return -7;
    }

    do {
        if (!ReadFile(file, fileData, BUFFERSIZE, &bytesRead, NULL)) {
            readFailed = TRUE;
            break;
        }

        if (bytesRead == 0) {
            break;
        }

        /* Update the total bytes read and inform the callback of our progress
         * if it's time. Don't forget to bail out if they request it. */
        totalBytesRead += bytesRead;
        if (callback && progressLoopCount % 10 == 0) {
            int32_t result = callback(request->tag, totalBytesRead);
            if (result != 0) {
                CloseHandle(file);
                HeapFree(GetProcessHeap(), 0, fileData);
                if (doED2k && ed2kHashes) {
                    HeapFree(GetProcessHeap(), 0, ed2kHashes);
                }

                return -9;
            }
        }

        ++progressLoopCount;

        /* Update the hashes with the file data. */
        if (doED2k) {
            /* If we've looped 10 times, finish the current MD4 hash, update
             * the block counter and set the hash to be initialized again.
             * Also, if the BUFFERSIZE is ever changed, the loop index will
             * need to be adjusted as well. */
            if (ed2kLoopIdx == 10) {
                MD4_final(&ed2k, &ed2kHashes[ed2kBlockIdx * 16]);
                ++ed2kBlockIdx;
                ed2kLoopIdx = 0;
            }

            /* If this is the first loop (or we've just finished a hash)
             * initialize the MD4 hash for the next block. */
            if (ed2kLoopIdx == 0) {
                MD4_init(&ed2k);
            }

            ++ed2kLoopIdx;
            MD4_update(&ed2k, fileData, bytesRead);
        }
        if (doCRC32) { CRC32_update(&crc32, fileData, bytesRead); }
        if (doMD5) { MD5_update(&md5, fileData, bytesRead); }
        if (doSHA1) { SHA1_update(&sha1, fileData, bytesRead); }
    } while (bytesRead != 0);

    /* Free our file buffer and close the file since we're done with it. */
    HeapFree(GetProcessHeap(), 0, fileData);
    CloseHandle(file);

    /* If we have a callback, call them one last time informing them of our
     * final progress (even if we failed). We'll ignore the request to cancel
     * since we'll be done in no time anyway. */
    if (callback) {
        callback(request->tag, totalBytesRead);
    }

    /* If we had a read failure, free up the ed2k hash (if we have one) and
     * inform our caller that we had a problem. */
    if (readFailed) {
        if (doED2k && ed2kHashes) {
            HeapFree(GetProcessHeap(), 0, ed2kHashes);
        }

        return -8;
    }

    /* Finalize all of the hashes that were selected and store the results in
     * the request result buffer. The order of the hashes are:
     *     0 - 15: ED2k
     *    16 - 19: CRC32
     *    20 - 35: MD5
     *    36 - 55: SHA1 */
    if (doED2k) {
        /* If we just had one block to process directly store the result of the
         * block in the result buffer. */
        if (ed2kBlocks == 1) {
            MD4_final(&ed2k, &request->result[0]);
        } else {
            /* Check to see if we were in the middle of a loop and finalize the
             * final pending block if we were. */
            if (ed2kLoopIdx > 0) {
                MD4_final(&ed2k, &ed2kHashes[ed2kBlockIdx * 16]);
            }

            /* Calculate the MD4 hash of the concatenated hashes from each ED2k
             * block. The resulting hash is the final ED2k hash. */
            MD4_init(&ed2k);
            MD4_update(&ed2k, ed2kHashes, ed2kHashLength);
            MD4_final(&ed2k, &request->result[0]);

            /* Don't forget to free our ED2k buffer. */
            HeapFree(GetProcessHeap(), 0, ed2kHashes);
        }
    }
    if (doCRC32) { CRC32_final(&crc32, &request->result[16]); }
    if (doMD5) { MD5_final(&md5, &request->result[20]); }
    if (doSHA1) { SHA1_final(&sha1, &request->result[36]); }

    return 0;
}