Daily bump.
[official-gcc.git] / libgo / go / crypto / sha1 / sha1.go
blob286a59d33d662bfa6fc955dea711f0a3d5eba6a8
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.
5 // Package sha1 implements the SHA-1 hash algorithm as defined in RFC 3174.
6 //
7 // SHA-1 is cryptographically broken and should not be used for secure
8 // applications.
9 package sha1
11 import (
12 "crypto"
13 "encoding/binary"
14 "errors"
15 "hash"
18 func init() {
19 crypto.RegisterHash(crypto.SHA1, New)
22 // The size of a SHA-1 checksum in bytes.
23 const Size = 20
25 // The blocksize of SHA-1 in bytes.
26 const BlockSize = 64
28 const (
29 chunk = 64
30 init0 = 0x67452301
31 init1 = 0xEFCDAB89
32 init2 = 0x98BADCFE
33 init3 = 0x10325476
34 init4 = 0xC3D2E1F0
37 // digest represents the partial evaluation of a checksum.
38 type digest struct {
39 h [5]uint32
40 x [chunk]byte
41 nx int
42 len uint64
45 const (
46 magic = "sha\x01"
47 marshaledSize = len(magic) + 5*4 + chunk + 8
50 func (d *digest) MarshalBinary() ([]byte, error) {
51 b := make([]byte, 0, marshaledSize)
52 b = append(b, magic...)
53 b = appendUint32(b, d.h[0])
54 b = appendUint32(b, d.h[1])
55 b = appendUint32(b, d.h[2])
56 b = appendUint32(b, d.h[3])
57 b = appendUint32(b, d.h[4])
58 b = append(b, d.x[:d.nx]...)
59 b = b[:len(b)+len(d.x)-int(d.nx)] // already zero
60 b = appendUint64(b, d.len)
61 return b, nil
64 func (d *digest) UnmarshalBinary(b []byte) error {
65 if len(b) < len(magic) || string(b[:len(magic)]) != magic {
66 return errors.New("crypto/sha1: invalid hash state identifier")
68 if len(b) != marshaledSize {
69 return errors.New("crypto/sha1: invalid hash state size")
71 b = b[len(magic):]
72 b, d.h[0] = consumeUint32(b)
73 b, d.h[1] = consumeUint32(b)
74 b, d.h[2] = consumeUint32(b)
75 b, d.h[3] = consumeUint32(b)
76 b, d.h[4] = consumeUint32(b)
77 b = b[copy(d.x[:], b):]
78 b, d.len = consumeUint64(b)
79 d.nx = int(d.len % chunk)
80 return nil
83 func appendUint64(b []byte, x uint64) []byte {
84 var a [8]byte
85 binary.BigEndian.PutUint64(a[:], x)
86 return append(b, a[:]...)
89 func appendUint32(b []byte, x uint32) []byte {
90 var a [4]byte
91 binary.BigEndian.PutUint32(a[:], x)
92 return append(b, a[:]...)
95 func consumeUint64(b []byte) ([]byte, uint64) {
96 _ = b[7]
97 x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
98 uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
99 return b[8:], x
102 func consumeUint32(b []byte) ([]byte, uint32) {
103 _ = b[3]
104 x := uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
105 return b[4:], x
108 func (d *digest) Reset() {
109 d.h[0] = init0
110 d.h[1] = init1
111 d.h[2] = init2
112 d.h[3] = init3
113 d.h[4] = init4
114 d.nx = 0
115 d.len = 0
118 // New returns a new hash.Hash computing the SHA1 checksum. The Hash also
119 // implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
120 // marshal and unmarshal the internal state of the hash.
121 func New() hash.Hash {
122 d := new(digest)
123 d.Reset()
124 return d
127 func (d *digest) Size() int { return Size }
129 func (d *digest) BlockSize() int { return BlockSize }
131 func (d *digest) Write(p []byte) (nn int, err error) {
132 nn = len(p)
133 d.len += uint64(nn)
134 if d.nx > 0 {
135 n := copy(d.x[d.nx:], p)
136 d.nx += n
137 if d.nx == chunk {
138 block(d, d.x[:])
139 d.nx = 0
141 p = p[n:]
143 if len(p) >= chunk {
144 n := len(p) &^ (chunk - 1)
145 block(d, p[:n])
146 p = p[n:]
148 if len(p) > 0 {
149 d.nx = copy(d.x[:], p)
151 return
154 func (d *digest) Sum(in []byte) []byte {
155 // Make a copy of d so that caller can keep writing and summing.
156 d0 := *d
157 hash := d0.checkSum()
158 return append(in, hash[:]...)
161 func (d *digest) checkSum() [Size]byte {
162 len := d.len
163 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
164 var tmp [64]byte
165 tmp[0] = 0x80
166 if len%64 < 56 {
167 d.Write(tmp[0 : 56-len%64])
168 } else {
169 d.Write(tmp[0 : 64+56-len%64])
172 // Length in bits.
173 len <<= 3
174 binary.BigEndian.PutUint64(tmp[:], len)
175 d.Write(tmp[0:8])
177 if d.nx != 0 {
178 panic("d.nx != 0")
181 var digest [Size]byte
183 binary.BigEndian.PutUint32(digest[0:], d.h[0])
184 binary.BigEndian.PutUint32(digest[4:], d.h[1])
185 binary.BigEndian.PutUint32(digest[8:], d.h[2])
186 binary.BigEndian.PutUint32(digest[12:], d.h[3])
187 binary.BigEndian.PutUint32(digest[16:], d.h[4])
189 return digest
192 // ConstantTimeSum computes the same result of Sum() but in constant time
193 func (d *digest) ConstantTimeSum(in []byte) []byte {
194 d0 := *d
195 hash := d0.constSum()
196 return append(in, hash[:]...)
199 func (d *digest) constSum() [Size]byte {
200 var length [8]byte
201 l := d.len << 3
202 for i := uint(0); i < 8; i++ {
203 length[i] = byte(l >> (56 - 8*i))
206 nx := byte(d.nx)
207 t := nx - 56 // if nx < 56 then the MSB of t is one
208 mask1b := byte(int8(t) >> 7) // mask1b is 0xFF iff one block is enough
210 separator := byte(0x80) // gets reset to 0x00 once used
211 for i := byte(0); i < chunk; i++ {
212 mask := byte(int8(i-nx) >> 7) // 0x00 after the end of data
214 // if we reached the end of the data, replace with 0x80 or 0x00
215 d.x[i] = (^mask & separator) | (mask & d.x[i])
217 // zero the separator once used
218 separator &= mask
220 if i >= 56 {
221 // we might have to write the length here if all fit in one block
222 d.x[i] |= mask1b & length[i-56]
226 // compress, and only keep the digest if all fit in one block
227 block(d, d.x[:])
229 var digest [Size]byte
230 for i, s := range d.h {
231 digest[i*4] = mask1b & byte(s>>24)
232 digest[i*4+1] = mask1b & byte(s>>16)
233 digest[i*4+2] = mask1b & byte(s>>8)
234 digest[i*4+3] = mask1b & byte(s)
237 for i := byte(0); i < chunk; i++ {
238 // second block, it's always past the end of data, might start with 0x80
239 if i < 56 {
240 d.x[i] = separator
241 separator = 0
242 } else {
243 d.x[i] = length[i-56]
247 // compress, and only keep the digest if we actually needed the second block
248 block(d, d.x[:])
250 for i, s := range d.h {
251 digest[i*4] |= ^mask1b & byte(s>>24)
252 digest[i*4+1] |= ^mask1b & byte(s>>16)
253 digest[i*4+2] |= ^mask1b & byte(s>>8)
254 digest[i*4+3] |= ^mask1b & byte(s)
257 return digest
260 // Sum returns the SHA-1 checksum of the data.
261 func Sum(data []byte) [Size]byte {
262 var d digest
263 d.Reset()
264 d.Write(data)
265 return d.checkSum()