]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgo/go/crypto/sha256/sha256.go
libgo: Merge from revision 18783:00cce3a34d7e of master library.
[thirdparty/gcc.git] / libgo / go / crypto / sha256 / sha256.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package sha256 implements the SHA224 and SHA256 hash algorithms as defined
6 // in FIPS 180-4.
7 package sha256
8
9 import (
10 "crypto"
11 "hash"
12 )
13
14 func init() {
15 crypto.RegisterHash(crypto.SHA224, New224)
16 crypto.RegisterHash(crypto.SHA256, New)
17 }
18
19 // The size of a SHA256 checksum in bytes.
20 const Size = 32
21
22 // The size of a SHA224 checksum in bytes.
23 const Size224 = 28
24
25 // The blocksize of SHA256 and SHA224 in bytes.
26 const BlockSize = 64
27
28 const (
29 chunk = 64
30 init0 = 0x6A09E667
31 init1 = 0xBB67AE85
32 init2 = 0x3C6EF372
33 init3 = 0xA54FF53A
34 init4 = 0x510E527F
35 init5 = 0x9B05688C
36 init6 = 0x1F83D9AB
37 init7 = 0x5BE0CD19
38 init0_224 = 0xC1059ED8
39 init1_224 = 0x367CD507
40 init2_224 = 0x3070DD17
41 init3_224 = 0xF70E5939
42 init4_224 = 0xFFC00B31
43 init5_224 = 0x68581511
44 init6_224 = 0x64F98FA7
45 init7_224 = 0xBEFA4FA4
46 )
47
48 // digest represents the partial evaluation of a checksum.
49 type digest struct {
50 h [8]uint32
51 x [chunk]byte
52 nx int
53 len uint64
54 is224 bool // mark if this digest is SHA-224
55 }
56
57 func (d *digest) Reset() {
58 if !d.is224 {
59 d.h[0] = init0
60 d.h[1] = init1
61 d.h[2] = init2
62 d.h[3] = init3
63 d.h[4] = init4
64 d.h[5] = init5
65 d.h[6] = init6
66 d.h[7] = init7
67 } else {
68 d.h[0] = init0_224
69 d.h[1] = init1_224
70 d.h[2] = init2_224
71 d.h[3] = init3_224
72 d.h[4] = init4_224
73 d.h[5] = init5_224
74 d.h[6] = init6_224
75 d.h[7] = init7_224
76 }
77 d.nx = 0
78 d.len = 0
79 }
80
81 // New returns a new hash.Hash computing the SHA256 checksum.
82 func New() hash.Hash {
83 d := new(digest)
84 d.Reset()
85 return d
86 }
87
88 // New224 returns a new hash.Hash computing the SHA224 checksum.
89 func New224() hash.Hash {
90 d := new(digest)
91 d.is224 = true
92 d.Reset()
93 return d
94 }
95
96 func (d *digest) Size() int {
97 if !d.is224 {
98 return Size
99 }
100 return Size224
101 }
102
103 func (d *digest) BlockSize() int { return BlockSize }
104
105 func (d *digest) Write(p []byte) (nn int, err error) {
106 nn = len(p)
107 d.len += uint64(nn)
108 if d.nx > 0 {
109 n := copy(d.x[d.nx:], p)
110 d.nx += n
111 if d.nx == chunk {
112 block(d, d.x[:])
113 d.nx = 0
114 }
115 p = p[n:]
116 }
117 if len(p) >= chunk {
118 n := len(p) &^ (chunk - 1)
119 block(d, p[:n])
120 p = p[n:]
121 }
122 if len(p) > 0 {
123 d.nx = copy(d.x[:], p)
124 }
125 return
126 }
127
128 func (d0 *digest) Sum(in []byte) []byte {
129 // Make a copy of d0 so that caller can keep writing and summing.
130 d := *d0
131 hash := d.checkSum()
132 if d.is224 {
133 return append(in, hash[:Size224]...)
134 }
135 return append(in, hash[:]...)
136 }
137
138 func (d *digest) checkSum() [Size]byte {
139 len := d.len
140 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
141 var tmp [64]byte
142 tmp[0] = 0x80
143 if len%64 < 56 {
144 d.Write(tmp[0 : 56-len%64])
145 } else {
146 d.Write(tmp[0 : 64+56-len%64])
147 }
148
149 // Length in bits.
150 len <<= 3
151 for i := uint(0); i < 8; i++ {
152 tmp[i] = byte(len >> (56 - 8*i))
153 }
154 d.Write(tmp[0:8])
155
156 if d.nx != 0 {
157 panic("d.nx != 0")
158 }
159
160 h := d.h[:]
161 if d.is224 {
162 h = d.h[:7]
163 }
164
165 var digest [Size]byte
166 for i, s := range h {
167 digest[i*4] = byte(s >> 24)
168 digest[i*4+1] = byte(s >> 16)
169 digest[i*4+2] = byte(s >> 8)
170 digest[i*4+3] = byte(s)
171 }
172
173 return digest
174 }
175
176 // Sum256 returns the SHA256 checksum of the data.
177 func Sum256(data []byte) [Size]byte {
178 var d digest
179 d.Reset()
180 d.Write(data)
181 return d.checkSum()
182 }
183
184 // Sum224 returns the SHA224 checksum of the data.
185 func Sum224(data []byte) (sum224 [Size224]byte) {
186 var d digest
187 d.is224 = true
188 d.Reset()
189 d.Write(data)
190 sum := d.checkSum()
191 copy(sum224[:], sum[:Size224])
192 return
193 }