Created
June 1, 2015 14:33
-
-
Save Yengas/eb0764b53d028480a8dd to your computer and use it in GitHub Desktop.
SHA-1 Hash Function Implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "SHA.h" | |
| #include <cmath> | |
| #include <iostream> | |
| #include <iomanip> | |
| uint32_t stageOneFunction(uint32_t b, uint32_t c, uint32_t d) { | |
| return (b & c) | ((~b) & d); | |
| } | |
| uint32_t stageTwoFunction(uint32_t b, uint32_t c, uint32_t d) { | |
| return b ^ c ^ d; | |
| } | |
| uint32_t stageThreeFunction(uint32_t b, uint32_t c, uint32_t d) { | |
| return (b & c) | (b & d) | (c & d); | |
| } | |
| uint32_t circularShift(uint32_t word, int amount) { | |
| return (word << amount) | (word >> (32 - amount)); | |
| } | |
| uint32_t getWord(uint32_t* word, int round) { | |
| if(round < 16) | |
| return word[round]; | |
| return circularShift((getWord(word, round - 16) ^ getWord(word, round - 14) ^ getWord(word, round - 8) ^ getWord(word, round - 3)), 1); | |
| } | |
| const uint32_t SHA::constants[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }, SHA::registerStart[5] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; | |
| const roundFunction SHA::functions[4] = { stageOneFunction, stageTwoFunction, stageThreeFunction, stageTwoFunction }; | |
| void SHA::reset() { | |
| registers[0] = 0x67452301; | |
| registers[1] = 0xEFCDAB89; | |
| registers[2] = 0x98BADCFE; | |
| registers[3] = 0x10325476; | |
| registers[4] = 0xC3D2E1F0; | |
| read = 0; | |
| block_index = 0; | |
| padded = false; | |
| } | |
| void SHA::update(uint8_t* data, uint64_t length) { | |
| for(uint64_t i = 0; i < length; i++) { | |
| block[block_index++] = data[i]; | |
| read += 8; | |
| if(block_index == 64) { | |
| transform(); | |
| } | |
| } | |
| } | |
| void SHA::round(uint32_t word, uint32_t constant, roundFunction function) { | |
| uint32_t temp = registers[4] + function(registers[1], registers[2], registers[3]) + circularShift(registers[0], 5) + word + constant; | |
| registers[4] = registers[3]; | |
| registers[3] = registers[2]; | |
| registers[2] = circularShift(registers[1], 30); | |
| registers[1] = registers[0]; | |
| registers[0] = temp; | |
| } | |
| void SHA::padding() { | |
| block[block_index++] = 0x80; | |
| if(block_index > 56) { | |
| transform(); | |
| memset(block, 0, 56); | |
| }else { | |
| memset(block + block_index, 0, 56 - block_index); | |
| } | |
| for(int i = 0; i < 8; i++) { | |
| block[56 + i] = (read >> ((8 - i - 1) * 8)) & 0xFF; | |
| } | |
| transform(); | |
| } | |
| void SHA::transform() { | |
| if(padded) this->reset(); | |
| uint32_t beforeRegisters[5]; | |
| memcpy(beforeRegisters, registers.data(), sizeof(uint32_t) * 5); | |
| uint32_t W[80]; | |
| for(int x = 0; x < 80; x++) { | |
| if(x < 16) { | |
| W[x] = 0; | |
| for(int i = 0; i < 4; i++) { | |
| W[x] = (W[x] << 8) | block[x * 4 + i]; | |
| } | |
| }else { | |
| W[x] = circularShift(W[x - 16] ^ W[x - 14] ^ W[x - 8] ^ W[x - 3], 1); | |
| } | |
| } | |
| for(int i = 0; i < 80; i++) { | |
| int stage = i / 20; | |
| round(W[i], constants[stage], functions[stage]); | |
| } | |
| for(int i = 0; i < registers.size(); i++) { | |
| registers[i] = (registers[i] + beforeRegisters[i]) & 0xFFFFFFFF; | |
| } | |
| block_index = 0; | |
| } | |
| std::string SHA::digest() { | |
| if(!padded) { | |
| padding(); | |
| padded = true; | |
| } | |
| std::stringstream result; | |
| result.fill('0'); | |
| for(int i = 0; i < 5; i++) { | |
| result << std::hex << std::uppercase << std::setw(8) << registers[i]; | |
| } | |
| return result.str(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include <stdint.h> | |
| #include <string> | |
| #include <sstream> | |
| #include <array> | |
| typedef uint32_t(*roundFunction)(uint32_t b, uint32_t c, uint32_t d); | |
| class SHA | |
| { | |
| public: | |
| SHA(){ this->reset(); }; | |
| void reset(); | |
| void update(uint8_t* data, uint64_t size); | |
| std::string digest(); | |
| private: | |
| void round(uint32_t word, uint32_t constant, roundFunction function); | |
| void transform(); | |
| void padding(); | |
| bool padded = false; | |
| uint64_t read = 0; | |
| uint8_t block_index = 0; | |
| uint8_t block[64]; | |
| std::array<uint32_t, 5> registers; | |
| static const uint32_t constants[], registerStart[]; | |
| static const roundFunction functions[]; | |
| }; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment