001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
Min/Max





























































































































































































































































































/*
* Copyright (c), Zeriph Enterprises
* All rights reserved.
*
* Contributor(s):
* Zechariah Perez, omni (at) zeriph (dot) com
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <omni/crypto/sha256.hpp>
#include <omni/defs/file_def.hpp>
#include <fstream>
#include <sstream>
#include <cstring>
#define OMNI_IO_FILE_EX_FW 1
#include <omni/xx/io/file_ex.hxx>

#if defined(OMNI_SAFE_SHA256)
    #define OMNI_SAFE_SHA256DMTX_FW ,m_mtx()
    #define OMNI_SAFE_SHA256LOCK_FW this->m_mtx.lock();
    #define OMNI_SAFE_SHA256UNLOCK_FW this->m_mtx.unlock();
    #define OMNI_SAFE_SHA256ALOCK_FW omni::sync::scoped_basic_lock uuid12345(&this->m_mtx);
    #define OMNI_SAFE_SHA256OALOCK_FW(o) omni::sync::scoped_basic_lock uuid54321(&o.m_mtx);
#else
    #define OMNI_SAFE_SHA256DMTX_FW
    #define OMNI_SAFE_SHA256LOCK_FW
    #define OMNI_SAFE_SHA256UNLOCK_FW
    #define OMNI_SAFE_SHA256ALOCK_FW
    #define OMNI_SAFE_SHA256OALOCK_FW(o)
#endif

#define OMNI_SHA2_SHFR_FW(x, n) (x >> n)
#define OMNI_SHA2_ROTR_FW(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define OMNI_SHA2_ROTL_FW(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define OMNI_SHA2_CH_FW(x, y, z) ((x & y) ^ (~x & z))
#define OMNI_SHA2_MAJ_FW(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define OMNI_SHA256_F1_FW(x) (OMNI_SHA2_ROTR_FW(x, 2) ^ OMNI_SHA2_ROTR_FW(x, 13) ^ OMNI_SHA2_ROTR_FW(x, 22))
#define OMNI_SHA256_F2_FW(x) (OMNI_SHA2_ROTR_FW(x, 6) ^ OMNI_SHA2_ROTR_FW(x, 11) ^ OMNI_SHA2_ROTR_FW(x, 25))
#define OMNI_SHA256_F3_FW(x) (OMNI_SHA2_ROTR_FW(x, 7) ^ OMNI_SHA2_ROTR_FW(x, 18) ^ OMNI_SHA2_SHFR_FW(x, 3))
#define OMNI_SHA256_F4_FW(x) (OMNI_SHA2_ROTR_FW(x, 17) ^ OMNI_SHA2_ROTR_FW(x, 19) ^ OMNI_SHA2_SHFR_FW(x, 10))
#define OMNI_SHA2_UNPACK32_FW(x, str) { *((str) + 3) = static_cast<uint8_t>((x)); *((str) + 2) = static_cast<uint8_t>((x) >> 8); *((str) + 1) = static_cast<uint8_t>((x) >> 16); *((str) + 0) = static_cast<uint8_t>((x) >> 24); }
#define OMNI_SHA2_PACK32_FW(str, x) { *(x) = (static_cast<uint32_t>(*((str) + 3))) | (static_cast<uint32_t>(*((str) + 2)) << 8) | (static_cast<uint32_t>(*((str) + 1)) << 16) | (static_cast<uint32_t>(*((str) + 0)) << 24); }
#define OMNI_SHA2_DIGEST_SIZE_FW 32 // (256 / 8)
#define OMNI_SHA2_BLOCK_SIZE_FW 64 // (512 / 8)

namespace omni { namespace crypto { namespace sha256_internal {
    void transform(const unsigned char* message, uint32_t block_nb, uint32_t* hex_vals)
    {
        const uint32_t sha256_k[64] = {
            0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
            0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
            0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
            0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
            0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
            0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
            0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
            0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
            0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
            0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
            0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
            0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
            0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
            0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
            0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
            0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
        };
        uint32_t blkx[64];
        uint32_t blky[8];
        uint32_t t1, t2, i, j;
        const unsigned char* sub_block;
        for (i = 0; i < block_nb; ++i) {
            sub_block = message + (i << 6);
            for (j = 0; j < 16; ++j) {
                OMNI_SHA2_PACK32_FW(&sub_block[j << 2], &blkx[j]);
            }
            for (j = 16; j < 64; ++j) {
                blkx[j] = OMNI_SHA256_F4_FW(blkx[j - 2]) + blkx[j - 7] + OMNI_SHA256_F3_FW(blkx[j - 15]) + blkx[j - 16];
            }
            for (j = 0; j < 8; ++j) {
                blky[j] = hex_vals[j];
            }
            for (j = 0; j < 64; ++j) {
                t1 = blky[7] + OMNI_SHA256_F2_FW(blky[4]) + OMNI_SHA2_CH_FW(blky[4], blky[5], blky[6]) + sha256_k[j] + blkx[j];
                t2 = OMNI_SHA256_F1_FW(blky[0]) + OMNI_SHA2_MAJ_FW(blky[0], blky[1], blky[2]);
                blky[7] = blky[6]; blky[6] = blky[5]; blky[5] = blky[4];
                blky[4] = blky[3] + t1; blky[3] = blky[2]; blky[2] = blky[1];
                blky[1] = blky[0]; blky[0] = t1 + t2;
            }
            for (j = 0; j < 8; ++j) { hex_vals[j] += blky[j]; }
        }
    }
} } }

omni::crypto::sha256::sha256() :
    OMNI_CTOR_FW(omni::crypto::sha256)
    m_hash()
    OMNI_SAFE_SHA256DMTX_FW
{}

omni::crypto::sha256::sha256(const omni::crypto::sha256& cp) :
    OMNI_CPCTOR_FW(cp)
    m_hash(cp.m_hash)
    OMNI_SAFE_SHA256DMTX_FW
{}

OMNI_EXPLICIT omni::crypto::sha256::sha256(const std::string& hash) :
    OMNI_CTOR_FW(omni::crypto::sha256)
    m_hash(hash)
    OMNI_SAFE_SHA256DMTX_FW
{
}

omni::crypto::sha256::sha256(const std::string& text, const omni::crypto::hash_type& type) :
    OMNI_CTOR_FW(omni::crypto::sha256)
    m_hash()
    OMNI_SAFE_SHA256DMTX_FW
{
    if (type == omni::crypto::hash_type::STRING) {
        this->_compute(text);
    } else {
        if (!omni::io::file_internal::exists(text)) {
            OMNI_ERRV_FW("File not found: ", text, omni::exceptions::file_not_found(text))
        }
        std::ifstream ifile;
        if (type == omni::crypto::hash_type::BINARY_FILE) {
            ifile.open(text.c_str(), std::ios::binary);
        } else {
            ifile.open(text.c_str());
        }
        ifile.seekg(0, ifile.end);
        uint32_t length = static_cast<uint32_t>(ifile.tellg());
        ifile.seekg(0, ifile.beg);
        if (length > 0) {
            char* data = new char[length];
            ifile.read(data, length);
            ifile.close();
            this->_compute(reinterpret_cast<const unsigned char*>(data), length);
            delete[] data;
        }
    }
}

omni::crypto::sha256::~sha256()
{
    OMNI_TRY_FW
    OMNI_DTOR_FW
    OMNI_CATCH_FW
}

std::string omni::crypto::sha256::hash_code() const
{
    return this->to_string();
}

void omni::crypto::sha256::swap(omni::crypto::sha256& o)
{
    if (this != &o) {
        OMNI_SAFE_SHA256ALOCK_FW
        OMNI_SAFE_SHA256OALOCK_FW(o)
        std::swap(this->m_hash, o.m_hash);
    }
}

omni::string_t omni::crypto::sha256::to_string_t() const
{
    OMNI_SAFE_SHA256ALOCK_FW
    return omni::string::util::to_string_t(this->m_hash);
}

std::string omni::crypto::sha256::to_string() const
{
    OMNI_SAFE_SHA256ALOCK_FW
    return this->m_hash;
}

std::wstring omni::crypto::sha256::to_wstring() const
{
    OMNI_SAFE_SHA256ALOCK_FW
    return omni::string::util::to_wstring(this->m_hash);
}

omni::crypto::sha256& omni::crypto::sha256::operator=(const omni::crypto::sha256& other)
{
    if (this != &other) {
        OMNI_SAFE_SHA256ALOCK_FW
        OMNI_SAFE_SHA256OALOCK_FW(other)
        this->m_hash = other.m_hash;
    }
    return *this;
}

bool omni::crypto::sha256::operator==(const omni::crypto::sha256& o) const
{
    if (this != &o) {
        OMNI_SAFE_SHA256ALOCK_FW
        OMNI_SAFE_SHA256OALOCK_FW(o)
        return this->m_hash == o.m_hash;
    }
    return true;
}

bool omni::crypto::sha256::operator!=(const omni::crypto::sha256& o) const
{
    return !(*this == o);
}

std::string omni::crypto::sha256::compute_hash(const std::string& text)
{
    omni::crypto::sha256 sha(text, omni::crypto::hash_type::STRING);
    return sha.m_hash;
}

std::string omni::crypto::sha256::compute_file_hash(const std::string& file)
{
    omni::crypto::sha256 sha(file, omni::crypto::hash_type::TEXT_FILE);
    return sha.m_hash;
}

std::string omni::crypto::sha256::compute_binary_file_hash(const std::string& file)
{
    omni::crypto::sha256 sha(file, omni::crypto::hash_type::BINARY_FILE);
    return sha.m_hash;
}

void omni::crypto::sha256::_compute(const std::string& text)
{
    this->_compute(reinterpret_cast<const unsigned char*>(text.c_str()), static_cast<uint32_t>(text.size()));
}

void omni::crypto::sha256::_compute(const unsigned char* message, uint32_t len)
{
    uint32_t block_nb, pm_len, len_b, i;
    uint32_t cur_len = 0;
    uint32_t tot_len = 0;
    uint32_t rem_len = 0;
    uint32_t tmp_len = 0;
    uint32_t hex_vals[8] = {
        0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
        0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
    };
    unsigned char data_block[2 * OMNI_SHA2_BLOCK_SIZE_FW];
    unsigned char digest[OMNI_SHA2_DIGEST_SIZE_FW];
    std::memset(digest, 0, sizeof(digest));

    tmp_len = OMNI_SHA2_BLOCK_SIZE_FW - cur_len;
    rem_len = len < tmp_len ? len : tmp_len;
    std::memcpy(&data_block[cur_len], message, rem_len);
    if (cur_len + len < OMNI_SHA2_BLOCK_SIZE_FW) {
        cur_len += len;
    } else {
        uint32_t new_len;
        const unsigned char* shifted_message;
        new_len = len - rem_len;
        block_nb = new_len / OMNI_SHA2_BLOCK_SIZE_FW;
        shifted_message = message + rem_len;
        omni::crypto::sha256_internal::transform(data_block, 1, hex_vals);
        omni::crypto::sha256_internal::transform(shifted_message, block_nb, hex_vals);
        rem_len = new_len % OMNI_SHA2_BLOCK_SIZE_FW;
        std::memcpy(data_block, &shifted_message[block_nb << 6], rem_len);
        cur_len = rem_len;
        tot_len += (block_nb + 1) << 6;
    }

    block_nb = (1 + ((OMNI_SHA2_BLOCK_SIZE_FW - 9) < (cur_len % OMNI_SHA2_BLOCK_SIZE_FW)));
    len_b = (tot_len + cur_len) << 3;
    pm_len = block_nb << 6;
    std::memset(data_block + cur_len, 0, pm_len - cur_len);
    data_block[cur_len] = 0x80;
    OMNI_SHA2_UNPACK32_FW(len_b, data_block + pm_len - 4);
    omni::crypto::sha256_internal::transform(data_block, block_nb, hex_vals);
    for (i = 0 ; i < 8; ++i) {
        OMNI_SHA2_UNPACK32_FW(hex_vals[i], &digest[i << 2]);
    }

    this->m_hash = omni::crypto::util::buffer_to_hex_string(digest);
}