| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| /* |
| * Implementation of the Secure Hashing Algorithm (SHA-256) |
| * |
| * Generates a 256 bit message digest. It should be impossible to come |
| * come up with two messages that hash to the same value ("collision free"). |
| * |
| * For use with byte-oriented messages only. |
| */ |
| |
| public class HASH |
| { |
| private int[] length = new int[2]; |
| private int[] h = new int[8]; |
| private int[] w = new int[64]; |
| |
| public const int H0 = 0x6A09E667; |
| public const int H1 = unchecked((int)0xBB67AE85); |
| public const int H2 = 0x3C6EF372; |
| public const int H3 = unchecked((int)0xA54FF53A); |
| public const int H4 = 0x510E527F; |
| public const int H5 = unchecked((int)0x9B05688C); |
| public const int H6 = 0x1F83D9AB; |
| public const int H7 = 0x5BE0CD19; |
| |
| public const int len = 32; |
| |
| public static readonly int[] K = new int[] {0x428a2f98, 0x71374491, unchecked((int)0xb5c0fbcf), unchecked((int)0xe9b5dba5), 0x3956c25b, 0x59f111f1, unchecked((int)0x923f82a4), unchecked((int)0xab1c5ed5), unchecked((int)0xd807aa98), 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, unchecked((int)0x80deb1fe), unchecked((int)0x9bdc06a7), unchecked((int)0xc19bf174), unchecked((int)0xe49b69c1), unchecked((int)0xefbe4786), 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, unchecked((int)0x983e5152), unchecked((int)0xa831c66d), unchecked((int)0xb00327c8), unchecked((int)0xbf597fc7), unchecked((int)0xc6e00bf3), unchecked((int)0xd5a79147), 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, unchecked((int)0x81c2c92e), unchecked((int)0x92722c85), unchecked((int)0xa2bfe8a1), unchecked((int)0xa81a664b), unchecked((int)0xc24b8b70), unchecked((int)0xc76c51a3), unchecked((int)0xd192e819), unchecked((int)0xd6990624), unchecked((int)0xf40e3585), 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, unchecked((int)0x84c87814), unchecked((int)0x8cc70208), unchecked((int)0x90befffa), unchecked((int)0xa4506ceb), unchecked((int)0xbef9a3f7), unchecked((int)0xc67178f2)}; |
| |
| |
| /* functions */ |
| private static int S(int n, int x) |
| { |
| return (((int)((uint)(x) >> n)) | ((x) << (32 - n))); |
| } |
| |
| private static int R(int n, int x) |
| { |
| return ((int)((uint)(x) >> n)); |
| } |
| |
| private static int Ch(int x, int y, int z) |
| { |
| return ((x & y) ^ (~(x) & z)); |
| } |
| |
| private static int Maj(int x, int y, int z) |
| { |
| return ((x & y) ^ (x & z) ^ (y & z)); |
| } |
| |
| private static int Sig0(int x) |
| { |
| return (S(2,x) ^ S(13,x) ^ S(22,x)); |
| } |
| |
| private static int Sig1(int x) |
| { |
| return (S(6,x) ^ S(11,x) ^ S(25,x)); |
| } |
| |
| private static int theta0(int x) |
| { |
| return (S(7,x) ^ S(18,x) ^ R(3,x)); |
| } |
| |
| private static int theta1(int x) |
| { |
| return (S(17,x) ^ S(19,x) ^ R(10,x)); |
| } |
| |
| |
| private void transform() |
| { // basic transformation step |
| int a, b, c, d, e, f, g, hh, t1, t2; |
| int j; |
| for (j = 16;j < 64;j++) |
| { |
| w[j] = theta1(w[j - 2]) + w[j - 7] + theta0(w[j - 15]) + w[j - 16]; |
| } |
| a = h[0]; |
| b = h[1]; |
| c = h[2]; |
| d = h[3]; |
| e = h[4]; |
| f = h[5]; |
| g = h[6]; |
| hh = h[7]; |
| |
| for (j = 0;j < 64;j++) |
| { // 64 times - mush it up |
| t1 = hh + Sig1(e) + Ch(e,f,g) + K[j] + w[j]; |
| t2 = Sig0(a) + Maj(a,b,c); |
| hh = g; |
| g = f; |
| f = e; |
| e = d + t1; |
| d = c; |
| c = b; |
| b = a; |
| a = t1 + t2; |
| |
| } |
| h[0] += a; |
| h[1] += b; |
| h[2] += c; |
| h[3] += d; |
| h[4] += e; |
| h[5] += f; |
| h[6] += g; |
| h[7] += hh; |
| } |
| |
| /* Initialise Hash function */ |
| public virtual void init() |
| { // initialise |
| int i; |
| for (i = 0;i < 64;i++) |
| { |
| w[i] = 0; |
| } |
| length[0] = length[1] = 0; |
| h[0] = H0; |
| h[1] = H1; |
| h[2] = H2; |
| h[3] = H3; |
| h[4] = H4; |
| h[5] = H5; |
| h[6] = H6; |
| h[7] = H7; |
| } |
| |
| /* Constructor */ |
| public HASH() |
| { |
| init(); |
| } |
| |
| /* process a single byte */ |
| public virtual void process(int byt) |
| { // process the next message byte |
| int cnt; |
| cnt = (length[0] / 32) % 16; |
| |
| w[cnt] <<= 8; |
| w[cnt] |= (byt & 0xFF); |
| length[0] += 8; |
| if (length[0] == 0) |
| { |
| length[1]++; |
| length[0] = 0; |
| } |
| if ((length[0] % 512) == 0) |
| { |
| transform(); |
| } |
| } |
| |
| /* process an array of bytes */ |
| public virtual void process_array(sbyte[] b) |
| { |
| for (int i = 0;i < b.Length;i++) |
| { |
| process((int)b[i]); |
| } |
| } |
| |
| /* process a 32-bit integer */ |
| public virtual void process_num(int n) |
| { |
| process((n >> 24) & 0xff); |
| process((n >> 16) & 0xff); |
| process((n >> 8) & 0xff); |
| process(n & 0xff); |
| } |
| |
| /* Generate 32-byte Hash */ |
| public virtual sbyte[] hash() |
| { // pad message and finish - supply digest |
| int i; |
| sbyte[] digest = new sbyte[32]; |
| int len0, len1; |
| len0 = length[0]; |
| len1 = length[1]; |
| process(0x80); |
| while ((length[0] % 512) != 448) |
| { |
| process(0); |
| } |
| w[14] = len1; |
| w[15] = len0; |
| transform(); |
| for (i = 0;i < len;i++) |
| { // convert to bytes |
| digest[i] = unchecked((sbyte)((h[i / 4] >> (8 * (3 - i % 4))) & 0xff)); |
| } |
| init(); |
| return digest; |
| } |
| |
| /* test program: should produce digest */ |
| |
| //248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1 |
| /* |
| public static void main(String[] args) { |
| byte[] test="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes(); |
| byte[] digest; |
| int i; |
| HASH sh=new HASH(); |
| |
| for (i=0;i<test.length;i++) |
| sh.process(test[i]); |
| |
| digest=sh.hash(); |
| for (i=0;i<32;i++) System.out.format("%02x",digest[i]); |
| |
| // for (i=0;i<32;i++) System.out.format("%d ",digest[i]); |
| |
| System.out.println(""); |
| } */ |
| } |
| |