オープンソースなSHA256ハッシュを求める為のクラス(とプログラム)です.
結構前に某ソフトで使う為に書きました.
C++ディレクトリを探索してたら見つけたので公開します.

ライセンス

どんなソフトのどんな部分にでも,自由に使ったり参考にしていただいて構いません.

更新履歴

  • 2008/03/21
    高速化.
  • 2008/03/18
    無駄なコピーの削減,ループの展開等
  • 2008/03/16
    バグ修正.暗号工房さんありがとうございます.
  • 2005/11/20
    作った

ソースコード

VC.NET 2003とgcc4でコンパイルできる事を確認しています.
失敗しても,(long longが使えない環境とかだと)sha256.hのコメントを読めば*1直る事があるかもです.
C++的なプログラムの書き方の勉強にはなりませんので,注意.

  • ソース
    sha256.cpp filesha256.cpp
    sha256.h filesha256.h

    g++ sha256.cppな感じで普通にコンパイル通ると思います.

それと,私が最初に実装したSHA-256ライブラリも見つかったので置いておきます.
コードはこっちの方が読みやすいので,仕様をコードに落とせなくて困っている方はどうぞ.
filesha256_simple.cpp

使い方

コマンドラインで使う事になります.
ファイルを読み込ませて求める

sha256 file

か,直接文字列を入力する.

sha256 -s string

になります.引数無しで実行すると,標準入力から読み込みます(テストして無いけれど...)

性能

  • 入力のサイズ
    適当なバイナリ4GBのハッシュはちゃんと求めれました.それ以上は試してないですが
    2^64ビットまでは大丈夫な気がします(未確認です). 追記:未確認だった2^32ビット以上のメッセージですが,正常に動作しないようです.
    最新版は大丈夫な気がします(未確認ですが...).
  • 実行時間
    BSDに標準で入ってるsha256コマンドより1.5倍くらいの時間がかかります・・・
    チューニングとかしてないです^^;
  • バイナリサイズ
    > ll a.out
    -rwxr-xr-x  1 safii  safii  7120 Feb 28 19:29 a.out
    > ll /sbin/sha256
    -r-xr-xr-x  4 root  wheel  9412 Sep 14 18:50 /sbin/sha256
    実行ファイルのサイズはBSDの物より小さいです(ぉ.

参考

  • FIP180-2
    仕様書です.自分で実装する場合はここを見ながらする事になるかと思います.

コメント

使用報告やバグ報告,どこそこを修正すると早くなるかも等がありましたら是非教えてください.

  • sha256.hの #define U64_HIGH(a) *2 ではないでしょうか? -- 暗号工房 2008-03-15 16:22:55 (土)
  • SHA256::Final の W[m_WIndex++/4]|=0x00<<(24-(m_WIndex%4)*8);は W[m_WIndex++/4]|=0x0;と同じになってしまうように思いますが? -- 暗号工房 2008-03-15 16:30:47 (土)
  • SHA256::Final の W[m_WIndex++/4]|=0x00<<(24-(m_WIndex%4)*8);は W[m_WIndex++/4]|=0x0;と同じになってしまうように思いますが? -- 暗号工房 2008-03-15 16:31:27 (土)
  • その通りですね.ご指摘ありがとうございます.大きいサイズのメッセージを求めようとすると正常に動きませんね.謎のシフトはなんでこんなことになっているんでしょうね? 覚えていませんが直しておきます. あと,コメントが書きにくくて申し訳ありませんでした. -- Naoki 2008-03-16 00:31:09 (日)
  • 上記の者ですが、間違えて実名を入れてしまってので、訂正をお願いします。また、void SHA256::CalcIntermediateHash() を次の様に書き換えると、高速になります。エンターが使えないので見難いですが
    void SHA256::CalcIntermediateHash(){
        i_^=1;
        i_1^=1;
        u_32 x[8];
    
        memcpy(x, H[i_1], 32);
        int T1, T2;
        int t;
    #define ROUND(n,a,b,c,d,e,f,g,h) \
        T1=x[h]+S256_1(x[e])+Ch(x[e],x[f],x[g])+K[t+n]+W[t+n]; \
        T2=S256_0(x[a])+Maj(x[a],x[b],x[c]); \
        x[d]=x[d]+T1; \
        x[h]=T1+T2
        
        for(t=0; t<64; t+=8){
            ROUND(0,0,1,2,3,4,5,6,7);
            ROUND(1,7,0,1,2,3,4,5,6);
            ROUND(2,6,7,0,1,2,3,4,5);
            ROUND(3,5,6,7,0,1,2,3,4);
            ROUND(4,4,5,6,7,0,1,2,3);
            ROUND(5,3,4,5,6,7,0,1,2);
            ROUND(6,2,3,4,5,6,7,0,1);
            ROUND(7,1,2,3,4,5,6,7,0);
        }
        H[i_][0]=x[0]+H[i_1][0];
        H[i_][1]=x[1]+H[i_1][1];
        H[i_][2]=x[2]+H[i_1][2];
        H[i_][3]=x[3]+H[i_1][3];
        H[i_][4]=x[4]+H[i_1][4];
        H[i_][5]=x[5]+H[i_1][5];
        H[i_][6]=x[6]+H[i_1][6];
        H[i_][7]=x[7]+H[i_1][7];
    }
    
    • 暗号工房 2008-03-16 09:46:58 (日)
  • 名前は修正しておきました.それと,高速化のアイデアありがとうございます.昨日のループも0でor取ってるので意味がないんですよね・・・ 色々と修正できる部分がありそうですね. -- Naoki 2008-03-16 14:47:01 (日)
  • 修正版をアップロードしておきました.他の箇所のループの展開的なことはやっていませんが,他にも少しいじってあります.それと,コメントを見やすいように編集しておきました -- Naoki 2008-03-18 23:34:37 (火)
  • sha256.cppのコードを公開して頂き、大変勉強になりました。お蔭さまで、ハッシュのコードがわかるようになりました。ありがとうございました。ところで、コードに、もう2箇所ばかり気になるところがあります。一つ目は i_,i_1,H[2][8]についてです。これはi_,i_1を使わずにH[8]とした方が良いと思われます。ただし -- 暗号工房 2008-03-20 14:14:03 (木)
  • 間違って送信してしまったため、上記の続きです。  SHA256::CalcIntermediateHash()のH[i_][0]=x[0]+H[i_1][0];などはH[0]+=x[0];などに変わりますが、gccで試したところ、この方が高速になりました。二つ目はSHA256::Finalのfor(t=m_WIndex/4+1;t<16; t++)W[t]=0;の+1の部分です。W[t]に既に0が代入されているため、この行全体がなくても動作しますので、バグではありませんが、このコードを参考にする人のために+1は削除した方が良いと思います。 -- 暗号工房 2008-03-20 14:20:29 (木)
  • Hの内容はxにコピーしてあるのでいらないですね.ありがとうございます.196行目のmemsetもきちんと書けば削れそうですね.こんなに色々とレビューしていただけるなら,これからも喜んで公開しますよ^^ -- Naoki 2008-03-21 16:30:36 (金)
  • こちらのソースを参考にさせていただきました。ありがとうございます。ここがなかったら実装はあきらめていたかも知れません。 1つ質問させて下さい。sha256.cpp内 SHA256::Pushの167行〜182行までの記述ですが、これは簡単に記述しようとすれば、 W[t_4/4]|=pMes[MesIndex++]<<(24-(t_4%4)*8); の部分を、 (t_4<64) && (MesIndex<Len) まで繰り返す形で書けると思っています(やってみましたが同じ結果が出ました)。この記述方法になっているのは、高速化のためという理解でいいでしょうか? -- はるあき 2008-06-05 18:11:09 (木)
  • 参考になりましたか.嬉しいです.二つのループでまわしている部分ですが,高速化のためであっています.コメント書いておかないと分かりにくいですね^^; -- Naoki 2008-06-08 18:04:52 (日)

お名前:

*1 仮64ビット整数クラスがあります
*2 u_32)m_MesLen>>32) は #define U64_HIGH(a) ((u_32)(a>>32
添付ファイル: filesha256.h 2587件 [詳細] filesha256_simple.cpp 2468件 [詳細] filesha256.cpp 4573件 [詳細]