File: sm3.go

package info (click to toggle)
golang-github-henrydcase-nobs 0.1%2Bgit20200305.7d891c7-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,928 kB
  • sloc: asm: 6,587; makefile: 53; python: 38
file content (110 lines) | stat: -rw-r--r-- 1,989 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Package sm3 implements the SM-3 hash algorithm as defined in "SM3 Hash
// function draft-shen-sm3-hash-01" draft
//
package sm3

import (
	"hash"
)

const (
	init0 = 0x7380166F
	init1 = 0x4914B2B9
	init2 = 0x172442D7
	init3 = 0xDA8A0600
	init4 = 0xA96F30BC
	init5 = 0x163138AA
	init6 = 0xE38DEE4D
	init7 = 0xB0FB0E4E
)

// The size of a SM-3 checksum in bytes.
const Size = 32

// The blocksize of SM-3 in bytes.
const BlockSize int = 64

// digest represents the partial evaluation of a checksum.
type digest struct {
	h   [8]uint32
	len uint64
	b   [BlockSize]byte
}

func New() hash.Hash {
	d := new(digest)
	d.Reset()
	return d
}

func (d *digest) BlockSize() int { return BlockSize }

func (d *digest) Size() int { return Size }

func (d *digest) Init() { d.Reset() }

func (d *digest) Reset() {
	d.h[0] = init0
	d.h[1] = init1
	d.h[2] = init2
	d.h[3] = init3
	d.h[4] = init4
	d.h[5] = init5
	d.h[6] = init6
	d.h[7] = init7
	d.len = 0
}

func (d *digest) Write(input []byte) (nn int, err error) {

	// current possition in the buffer
	idx := int(d.len & uint64((d.BlockSize() - 1)))
	d.len += uint64(len(input))

	if len(input)+idx < d.BlockSize() {
		copy(d.b[idx:], input)
		return
	}

	c := d.BlockSize() - idx
	copy(d.b[idx:], input[:c])
	d.compress(d.b[:], 1)

	input = input[c:]
	nblocks := int(len(input) / d.BlockSize())
	d.compress(input[:], nblocks)

	// this eventually could be done in d.compress
	copy(d.b[:], input[nblocks*d.BlockSize():])
	return
}

func (d *digest) Sum(in []byte) []byte {
	var output [32]byte

	// Copy context so that caller can keep updating
	dc := *d

	dc.Write(in)

	idx := int(dc.len & uint64(dc.BlockSize()-1))
	for i := idx + 1; i < len(dc.b); i++ {
		dc.b[i] = 0
	}
	dc.b[idx] = 0x80
	if idx >= 56 {
		dc.compress(dc.b[:], 1)
		for i := range dc.b {
			dc.b[i] = 0
		}
	}

	// add total bits
	store64Be(dc.b[56:], dc.len*8)

	dc.compress(dc.b[:], 1)
	for i := 0; i < Size/4; i++ {
		store32Be(output[4*i:], dc.h[i])
	}
	return output[:]
}