Exemple #1
0
MD5_state MD5_from_string(XString msg)
{
    MD5_state state;
    MD5_init(&state);
    MD5_block block;
    const uint64_t msg_full_len = msg.size();
    while (msg.size() >= 64)
    {
        for (int i = 0; i < 0x10; i++)
            X[i] = msg[4 * i + 0] | msg[4 * i + 1] << 8 | msg[4 * i + 2] << 16 | msg[4 * i + 3] << 24;
        MD5_do_block(&state, block);
        msg = msg.xslice_t(64);
    }
    // now pad 1-512 bits + the 64-bit length - may be two blocks
    uint8_t buf[0x40] = {};
    really_memcpy(buf, reinterpret_cast<const uint8_t *>(msg.data()), msg.size());
    buf[msg.size()] = 0x80; // a single one bit
    if (64 - msg.size() > 8)
    {
        for (int i = 0; i < 8; i++)
            buf[0x38 + i] = (msg_full_len * 8) >> (i * 8);
    }
    for (int i = 0; i < 0x10; i++)
        X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
    MD5_do_block(&state, block);
    if (64 - msg.size() <= 8)
    {
        really_memset0(buf, 0x38);
        for (int i = 0; i < 8; i++)
            buf[0x38 + i] = (msg_full_len * 8) >> (i * 8);
        for (int i = 0; i < 0x10; i++)
            X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
        MD5_do_block(&state, block);
    }
Exemple #2
0
/**
 * Computes the MD5 on the contents of the provided file.
 * @param filename The name of the file to process.
 */
void hash_file_md5(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;
    }

    MD5_Context md4;
    MD5_init(&md4);

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

    unsigned char result[16];
    MD5_final(&md4, result);

    close(file);

    printf("  ");
    for (int i = 0; i < 16; ++i) {
        printf("%02x", result[i]);
    }
    printf(" %s\n", filename);
}
Exemple #3
0
int MD5_testRun(void)
{
	int i;
	MD5_Context context;
	MD5_init(&context);

	hash_begin(&context.h);
	hash_update(&context.h, "abc", 3);
	ASSERT(memcmp(hash_final(&context.h), "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72", 16) == 0);

	hash_begin(&context.h);
	hash_update(&context.h, "aaa", 3);
	ASSERT(memcmp(hash_final(&context.h), "\x47\xBC\xE5\xC7\x4F\x58\x9F\x48\x67\xDB\xD5\x7E\x9C\xA9\xF8\x08", 16) == 0);

	hash_begin(&context.h);
	hash_update(&context.h, "abcdefghijklmnopqrstuvwxyz", 26);
	ASSERT(memcmp(hash_final(&context.h), "\xC3\xFC\xD3\xD7\x61\x92\xE4\x00\x7D\xFB\x49\x6C\xCA\x67\xE1\x3B", 16) == 0);

	hash_begin(&context.h);
	hash_update(&context.h, "0123456789", 10);
	ASSERT(memcmp(hash_final(&context.h), "\x78\x1E\x5E\x24\x5D\x69\xB5\x66\x97\x9B\x86\xE2\x8D\x23\xF2\xC7", 16) == 0);

	hash_begin(&context.h);
	for (i = 0; i < 1000; i++)
		hash_update(&context.h, "a", 1);
	ASSERT(memcmp(hash_final(&context.h), "\xCA\xBE\x45\xDC\xC9\xAE\x5B\x66\xBA\x86\x60\x0C\xCA\x6B\x8B\xA8", 16) == 0);

	hash_begin(&context.h);
	for (i = 0; i < 1000000; i++)
		hash_update(&context.h, "a", 1);
	ASSERT(memcmp(hash_final(&context.h), "\x77\x07\xd6\xae\x4e\x02\x7c\x70\xee\xa2\xa9\x35\xc2\x29\x6f\x21", 16) == 0);
	
	return 0;
}
Exemple #4
0
void MD5_buffer(const char *buffer, const unsigned int buf_len, void *signature)
{
    md5_t md5;

    /* initialize the computation context */
    MD5_init(&md5);

    /* process whole buffer but last buf_len % MD5_BLOCK bytes */
    MD5_process(&md5, buffer, buf_len);

    /* put result in desired memory area */
    MD5_finish(&md5, signature);
}
Exemple #5
0
std::string lc_md5(const char * str, size_t len)
{
    int32_t i;

	uint8_t PADDING[64] = {
		0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	};

	uint32_t context_state[4];       /* state (ABCD) */
	uint32_t context_count[2];       /* number of bits, modulo 2^64 (lsb first) */
	uint8_t context_buffer[64];    /* input buffer */

    uint8_t hash[16];
            
    MD5_init();
    MD5_update(str, len);
    MD5_fini(hash);
        
	std::string ret;
	for ( i = 0 ; i < 16 ; i++ )
	{
		std::string rettmp = lc_itoa16((uint8_t)hash[i]);

		if (rettmp.size() == 1)
		{
			ret += "0";
			ret += rettmp;
		}
		else
		{
			ret += rettmp;
		}
	}

    return ret;
}
Exemple #6
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;
}
Exemple #7
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;
}