mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-27 00:55:17 +00:00
303 lines
7.1 KiB
Go
303 lines
7.1 KiB
Go
/*
|
|
* Copyright (c) 2012-2020 MIRACL UK Ltd.
|
|
*
|
|
* This file is part of MIRACL Core
|
|
* (see https://github.com/miracl/core).
|
|
*
|
|
* Licensed 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 core
|
|
|
|
//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
|
|
}
|
|
|
|
func NewSHA3copy(HC *SHA3) *SHA3 {
|
|
H := new(SHA3)
|
|
for i := 0; i < 5; i++ {
|
|
for j := 0; j < 5; j++ {
|
|
H.s[i][j] = HC.s[i][j]
|
|
}
|
|
}
|
|
H.length = HC.length
|
|
H.len = HC.len
|
|
H.rate = HC.rate
|
|
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()
|
|
}
|
|
}
|
|
|
|
/* process an array of bytes */
|
|
func (H *SHA3) Process_array(b []byte) {
|
|
for i := 0; i < len(b); i++ {
|
|
H.Process((b[i]))
|
|
}
|
|
}
|
|
|
|
/* process a 32-bit integer */
|
|
func (H *SHA3) Process_num(n int32) {
|
|
H.Process(byte((n >> 24) & 0xff))
|
|
H.Process(byte((n >> 16) & 0xff))
|
|
H.Process(byte((n >> 8) & 0xff))
|
|
H.Process(byte(n & 0xff))
|
|
}
|
|
|
|
/* 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() []byte { /* generate a SHA3 hash of appropriate size */
|
|
var digest [64]byte
|
|
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(digest[:], H.len)
|
|
return digest[0:H.len]
|
|
}
|
|
|
|
func (H *SHA3) Continuing_Hash() []byte {
|
|
sh := NewSHA3copy(H)
|
|
return sh.Hash()
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
func (H *SHA3) Continuing_Shake(hash []byte, olen int) {
|
|
sh := NewSHA3copy(H)
|
|
sh.Shake(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");
|
|
|
|
} */
|