| /* |
| 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-384) |
| * |
| * Generates a 384 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. |
| */ |
| |
| //package main |
| |
| package amcl |
| |
| //import "fmt" |
| |
| const SHA3_HASH224 int = 28 |
| const SHA3_HASH256 int = 32 |
| const SHA3_HASH384 int = 48 |
| const SHA3_HASH512 int = 64 |
| const SHA3_SHAKE128 int = 16 |
| const SHA3_SHAKE256 int = 32 |
| |
| const sha3_ROUNDS int = 24 |
| |
| var sha3_RC = [24]uint64{ |
| 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, |
| 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, |
| 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, |
| 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, |
| 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, |
| 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008} |
| |
| type SHA3 struct { |
| length uint64 |
| rate int |
| len int |
| s [5][5]uint64 |
| } |
| |
| /* functions */ |
| |
| func sha3_ROTL(x uint64, n uint64) uint64 { |
| return (((x) << n) | ((x) >> (64 - n))) |
| } |
| |
| func (H *SHA3) transform() { /* basic transformation step */ |
| |
| var c [5]uint64 |
| var d [5]uint64 |
| var b [5][5]uint64 |
| |
| for k := 0; k < sha3_ROUNDS; k++ { |
| c[0] = H.s[0][0] ^ H.s[0][1] ^ H.s[0][2] ^ H.s[0][3] ^ H.s[0][4] |
| c[1] = H.s[1][0] ^ H.s[1][1] ^ H.s[1][2] ^ H.s[1][3] ^ H.s[1][4] |
| c[2] = H.s[2][0] ^ H.s[2][1] ^ H.s[2][2] ^ H.s[2][3] ^ H.s[2][4] |
| c[3] = H.s[3][0] ^ H.s[3][1] ^ H.s[3][2] ^ H.s[3][3] ^ H.s[3][4] |
| c[4] = H.s[4][0] ^ H.s[4][1] ^ H.s[4][2] ^ H.s[4][3] ^ H.s[4][4] |
| |
| d[0] = c[4] ^ sha3_ROTL(c[1], 1) |
| d[1] = c[0] ^ sha3_ROTL(c[2], 1) |
| d[2] = c[1] ^ sha3_ROTL(c[3], 1) |
| d[3] = c[2] ^ sha3_ROTL(c[4], 1) |
| d[4] = c[3] ^ sha3_ROTL(c[0], 1) |
| |
| for i := 0; i < 5; i++ { |
| for j := 0; j < 5; j++ { |
| H.s[i][j] ^= d[i] |
| } |
| } |
| |
| b[0][0] = H.s[0][0] |
| b[1][3] = sha3_ROTL(H.s[0][1], 36) |
| b[2][1] = sha3_ROTL(H.s[0][2], 3) |
| b[3][4] = sha3_ROTL(H.s[0][3], 41) |
| b[4][2] = sha3_ROTL(H.s[0][4], 18) |
| |
| b[0][2] = sha3_ROTL(H.s[1][0], 1) |
| b[1][0] = sha3_ROTL(H.s[1][1], 44) |
| b[2][3] = sha3_ROTL(H.s[1][2], 10) |
| b[3][1] = sha3_ROTL(H.s[1][3], 45) |
| b[4][4] = sha3_ROTL(H.s[1][4], 2) |
| |
| b[0][4] = sha3_ROTL(H.s[2][0], 62) |
| b[1][2] = sha3_ROTL(H.s[2][1], 6) |
| b[2][0] = sha3_ROTL(H.s[2][2], 43) |
| b[3][3] = sha3_ROTL(H.s[2][3], 15) |
| b[4][1] = sha3_ROTL(H.s[2][4], 61) |
| |
| b[0][1] = sha3_ROTL(H.s[3][0], 28) |
| b[1][4] = sha3_ROTL(H.s[3][1], 55) |
| b[2][2] = sha3_ROTL(H.s[3][2], 25) |
| b[3][0] = sha3_ROTL(H.s[3][3], 21) |
| b[4][3] = sha3_ROTL(H.s[3][4], 56) |
| |
| b[0][3] = sha3_ROTL(H.s[4][0], 27) |
| b[1][1] = sha3_ROTL(H.s[4][1], 20) |
| b[2][4] = sha3_ROTL(H.s[4][2], 39) |
| b[3][2] = sha3_ROTL(H.s[4][3], 8) |
| b[4][0] = sha3_ROTL(H.s[4][4], 14) |
| |
| for i := 0; i < 5; i++ { |
| for j := 0; j < 5; j++ { |
| H.s[i][j] = b[i][j] ^ (^b[(i+1)%5][j] & b[(i+2)%5][j]) |
| } |
| } |
| |
| H.s[0][0] ^= sha3_RC[k] |
| } |
| } |
| |
| /* Initialise Hash function */ |
| func (H *SHA3) Init(olen int) { |
| for i := 0; i < 5; i++ { |
| for j := 0; j < 5; j++ { |
| H.s[i][j] = 0 |
| } |
| } |
| H.length = 0 |
| H.len = olen |
| H.rate = 200 - 2*olen |
| } |
| |
| func NewSHA3(olen int) *SHA3 { |
| H := new(SHA3) |
| H.Init(olen) |
| return H |
| } |
| |
| /* process a single byte */ |
| func (H *SHA3) Process(byt byte) { /* process the next message byte */ |
| cnt := int(H.length % uint64(H.rate)) |
| b := cnt % 8 |
| cnt /= 8 |
| i := cnt % 5 |
| j := cnt / 5 |
| H.s[i][j] ^= uint64(byt&0xff) << uint(8*b) |
| H.length++ |
| if int(H.length%uint64(H.rate)) == 0 { |
| H.transform() |
| } |
| } |
| |
| /* squeeze the sponge */ |
| func (H *SHA3) Squeeze(buff []byte, olen int) { |
| // olen:=len(buff) |
| done := false |
| m := 0 |
| /* extract by columns */ |
| for { |
| for j := 0; j < 5; j++ { |
| for i := 0; i < 5; i++ { |
| el := H.s[i][j] |
| for k := 0; k < 8; k++ { |
| buff[m] = byte(el & 0xff) |
| m++ |
| if m >= olen || (m%H.rate) == 0 { |
| done = true |
| break |
| } |
| el >>= 8 |
| } |
| if done { |
| break |
| } |
| } |
| if done { |
| break |
| } |
| } |
| if m >= olen { |
| break |
| } |
| done = false |
| H.transform() |
| |
| } |
| } |
| |
| /* Generate Hash */ |
| func (H *SHA3) Hash(hash []byte) { /* generate a SHA3 hash of appropriate size */ |
| q := H.rate - int(H.length%uint64(H.rate)) |
| if q == 1 { |
| H.Process(0x86) |
| } else { |
| H.Process(0x06) |
| for int(H.length%uint64(H.rate)) != (H.rate - 1) { |
| H.Process(0x00) |
| } |
| H.Process(0x80) |
| } |
| H.Squeeze(hash, H.len) |
| } |
| |
| func (H *SHA3) Shake(hash []byte, olen int) { /* generate a SHA3 hash of appropriate size */ |
| q := H.rate - int(H.length%uint64(H.rate)) |
| if q == 1 { |
| H.Process(0x9f) |
| } else { |
| H.Process(0x1f) |
| for int(H.length%uint64(H.rate)) != H.rate-1 { |
| H.Process(0x00) |
| } |
| H.Process(0x80) |
| } |
| H.Squeeze(hash, olen) |
| } |
| |
| /* test program: should produce digest */ |
| //916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18 |
| //afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185 |
| //98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2 |
| |
| /* |
| func main() { |
| |
| test := []byte("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") |
| var digest [172]byte |
| |
| sh:=NewSHA3(SHA3_HASH256) |
| for i:=0;i<len(test);i++ { |
| sh.Process(test[i]) |
| } |
| sh.Hash(digest[:]) |
| for i:=0;i<32;i++ {fmt.Printf("%02x",digest[i])} |
| fmt.Printf("\n"); |
| |
| sh=NewSHA3(SHA3_HASH512) |
| for i:=0;i<len(test);i++ { |
| sh.Process(test[i]) |
| } |
| sh.Hash(digest[:]) |
| for i:=0;i<64;i++ {fmt.Printf("%02x",digest[i])} |
| fmt.Printf("\n"); |
| |
| sh=NewSHA3(SHA3_SHAKE256) |
| for i:=0;i<len(test);i++ { |
| sh.Process(test[i]) |
| } |
| sh.Shake(digest[:],72) |
| for i:=0;i<72;i++ {fmt.Printf("%02x",digest[i])} |
| fmt.Printf("\n"); |
| |
| } */ |