Created
January 14, 2012 17:50
-
-
Save t-mat/1612251 to your computer and use it in GitHub Desktop.
SHA256ハッシュを算出する
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
| /* | |
| http://www.ouah.org/ogay/sha2/ | |
| から SHA-256 部分だけを抜き出してテキトーに書き換えたもの。BSDライセンス | |
| */ | |
| /* | |
| * FIPS 180-2 SHA-224/256/384/512 implementation | |
| * Last update: 02/02/2007 | |
| * Issue date: 04/30/2005 | |
| * | |
| * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch> | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * 3. Neither the name of the project nor the names of its contributors | |
| * may be used to endorse or promote products derived from this software | |
| * without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 THE PROJECT OR 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 <string.h> | |
| #define SHA256_DIGEST_SIZE ( 256 / 8) | |
| #define SHA256_BLOCK_SIZE ( 512 / 8) | |
| #define SHFR(x, n) (x >> n) | |
| #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) | |
| #define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) | |
| #define CH(x, y, z) ((x & y) ^ (~x & z)) | |
| #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) | |
| #define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) | |
| #define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) | |
| #define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) | |
| #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) | |
| Sha256::Sha256() { | |
| clear(); | |
| } | |
| void Sha256::getDigest(Digest* digest) const { | |
| memcpy(digest->bytes, this->digest, sizeof(digest->bytes)); | |
| } | |
| void Sha256::clear() { | |
| static const u32 sha256_h0[8] = { | |
| 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, | |
| 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 | |
| }; | |
| memcpy(&h[0], &sha256_h0[0], sizeof(h)); | |
| tot_len = 0; | |
| len = 0; | |
| } | |
| void Sha256::update(const void* message, unsigned int len) { | |
| if(len) { | |
| unsigned int tmp_len = SHA256_BLOCK_SIZE - this->len; | |
| unsigned int rem_len = len < tmp_len ? len : tmp_len; | |
| memcpy(&this->block[this->len], message, rem_len); | |
| if(this->len + len < SHA256_BLOCK_SIZE) { | |
| this->len += len; | |
| } else { | |
| unsigned int new_len = len - rem_len; | |
| unsigned int block_nb = new_len / SHA256_BLOCK_SIZE; | |
| const unsigned char* shifted_message = static_cast<const unsigned char*>(message) + rem_len; | |
| transf(this->block, 1); | |
| transf(shifted_message, block_nb); | |
| rem_len = new_len % SHA256_BLOCK_SIZE; | |
| memcpy(this->block, &shifted_message[block_nb << 6], rem_len); | |
| this->len = rem_len; | |
| this->tot_len += (block_nb + 1) << 6; | |
| } | |
| } | |
| } | |
| static void storeBigendianU32(Sha256::u32 x, void* p) { | |
| unsigned char* str = static_cast<unsigned char*>(p); | |
| *((str) + 3) = (unsigned char) ((x) ); | |
| *((str) + 2) = (unsigned char) ((x) >> 8); | |
| *((str) + 1) = (unsigned char) ((x) >> 16); | |
| *((str) + 0) = (unsigned char) ((x) >> 24); | |
| } | |
| void Sha256::final() { | |
| unsigned int block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (this->len % SHA256_BLOCK_SIZE))); | |
| unsigned int len_b = (this->tot_len + this->len) << 3; | |
| unsigned int pm_len = block_nb << 6; | |
| memset(this->block + this->len, 0, pm_len - this->len); | |
| this->block[this->len] = 0x80; | |
| storeBigendianU32(len_b, this->block + pm_len - 4); | |
| transf(this->block, block_nb); | |
| for (int i = 0 ; i < 8; i++) { | |
| storeBigendianU32(this->h[i], &digest[i << 2]); | |
| } | |
| } | |
| void Sha256::transf(const void* msg, unsigned int block_nb) { | |
| const unsigned char* message = static_cast<const unsigned char*>(msg); | |
| static const u32 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 | |
| }; | |
| for (int i = 0; i < (int) block_nb; i++) { | |
| const unsigned char *sub_block = message + (i << 6); | |
| u32 w[64]; | |
| u32 wv[8]; | |
| for (int j = 0; j < 16; j++) { | |
| const unsigned char* str = &sub_block[j << 2]; | |
| w[j] = ((u32) *((str) + 3) ) | |
| | ((u32) *((str) + 2) << 8) | |
| | ((u32) *((str) + 1) << 16) | |
| | ((u32) *((str) + 0) << 24); | |
| } | |
| for (int j = 16; j < 64; j++) { | |
| w[j] = SHA256_F4(w[j - 2]) + w[j - 7] + SHA256_F3(w[j - 15]) + w[j - 16]; | |
| } | |
| for (int j = 0; j < 8; j++) { | |
| wv[j] = this->h[j]; | |
| } | |
| for (int j = 0; j < 64; j++) { | |
| u32 t1, t2; | |
| t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j]; | |
| t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); | |
| wv[7] = wv[6]; | |
| wv[6] = wv[5]; | |
| wv[5] = wv[4]; | |
| wv[4] = wv[3] + t1; | |
| wv[3] = wv[2]; | |
| wv[2] = wv[1]; | |
| wv[1] = wv[0]; | |
| wv[0] = t1 + t2; | |
| } | |
| for (int j = 0; j < 8; j++) { | |
| this->h[j] += wv[j]; | |
| } | |
| } | |
| } | |
| #if defined(MY_SHA256_EXAMPLE) | |
| #include <stdio.h> | |
| #include <vector> | |
| int main(int argc, const char* argv[]) { | |
| if(argc > 1) { | |
| const char* filename = argv[1]; | |
| FILE* fp = fopen(filename, "rb"); | |
| if(fp) { | |
| Sha256 s; | |
| std::vector<char> f(1024*1024); | |
| size_t r = 0; | |
| do { | |
| r = fread(&f[0], sizeof(f[0]), f.size(), fp); | |
| s.update(&f[0], r); | |
| } while(r == f.size()); | |
| s.final(); | |
| fclose(fp); | |
| Sha256::Digest d; | |
| s.getDigest(&d); | |
| printf("%s\nSHA256 ", filename); | |
| for(int i = 0; i < sizeof(d.bytes); ++i) { | |
| printf("%02x", d.bytes[i]); | |
| } | |
| } | |
| } | |
| return 0; | |
| } | |
| #endif |
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
| // http://www.ouah.org/ogay/sha2/ | |
| // から SHA-256 部分だけを抜き出してテキトーに書き換えたもの。本体のコードは BSD ライセンス | |
| class Sha256 { | |
| public: | |
| typedef unsigned int u32; | |
| struct Digest { | |
| unsigned char bytes[256/8]; | |
| }; | |
| Sha256(); | |
| ~Sha256() {} | |
| void getDigest(Digest* digest) const; | |
| void clear(); | |
| void update(const void* message, unsigned int len); | |
| void final(); | |
| static void getDigest(Digest* digest, const void* message, unsigned int len) { | |
| Sha256 s; | |
| s.update(message, len); | |
| s.final(); | |
| s.getDigest(digest); | |
| } | |
| protected: | |
| void transf(const void* message, unsigned int block_nb); | |
| u32 h[8]; | |
| unsigned int tot_len; | |
| unsigned int len; | |
| unsigned char block[2 * 512 / 8]; | |
| unsigned char digest[256/8]; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment