]>
Commit | Line | Data |
---|---|---|
7a938933 ILT |
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 | ||
9ff56c95 | 5 | // Package sha1 implements the SHA1 hash algorithm as defined in RFC 3174. |
7a938933 ILT |
6 | package sha1 |
7 | ||
8 | import ( | |
5133f00e | 9 | "crypto" |
7a938933 | 10 | "hash" |
7a938933 ILT |
11 | ) |
12 | ||
5133f00e ILT |
13 | func init() { |
14 | crypto.RegisterHash(crypto.SHA1, New) | |
15 | } | |
16 | ||
7a938933 ILT |
17 | // The size of a SHA1 checksum in bytes. |
18 | const Size = 20 | |
19 | ||
af92e385 ILT |
20 | // The blocksize of SHA1 in bytes. |
21 | const BlockSize = 64 | |
22 | ||
7a938933 | 23 | const ( |
4ccad563 ILT |
24 | chunk = 64 |
25 | init0 = 0x67452301 | |
26 | init1 = 0xEFCDAB89 | |
27 | init2 = 0x98BADCFE | |
28 | init3 = 0x10325476 | |
29 | init4 = 0xC3D2E1F0 | |
7a938933 ILT |
30 | ) |
31 | ||
32 | // digest represents the partial evaluation of a checksum. | |
33 | type digest struct { | |
34 | h [5]uint32 | |
4ccad563 | 35 | x [chunk]byte |
7a938933 ILT |
36 | nx int |
37 | len uint64 | |
38 | } | |
39 | ||
40 | func (d *digest) Reset() { | |
4ccad563 ILT |
41 | d.h[0] = init0 |
42 | d.h[1] = init1 | |
43 | d.h[2] = init2 | |
44 | d.h[3] = init3 | |
45 | d.h[4] = init4 | |
7a938933 ILT |
46 | d.nx = 0 |
47 | d.len = 0 | |
48 | } | |
49 | ||
50 | // New returns a new hash.Hash computing the SHA1 checksum. | |
51 | func New() hash.Hash { | |
52 | d := new(digest) | |
53 | d.Reset() | |
54 | return d | |
55 | } | |
56 | ||
57 | func (d *digest) Size() int { return Size } | |
58 | ||
af92e385 ILT |
59 | func (d *digest) BlockSize() int { return BlockSize } |
60 | ||
2fd401c8 | 61 | func (d *digest) Write(p []byte) (nn int, err error) { |
7a938933 ILT |
62 | nn = len(p) |
63 | d.len += uint64(nn) | |
64 | if d.nx > 0 { | |
65 | n := len(p) | |
4ccad563 ILT |
66 | if n > chunk-d.nx { |
67 | n = chunk - d.nx | |
7a938933 ILT |
68 | } |
69 | for i := 0; i < n; i++ { | |
70 | d.x[d.nx+i] = p[i] | |
71 | } | |
72 | d.nx += n | |
4ccad563 ILT |
73 | if d.nx == chunk { |
74 | block(d, d.x[0:]) | |
7a938933 ILT |
75 | d.nx = 0 |
76 | } | |
77 | p = p[n:] | |
78 | } | |
4ccad563 ILT |
79 | if len(p) >= chunk { |
80 | n := len(p) &^ (chunk - 1) | |
81 | block(d, p[:n]) | |
82 | p = p[n:] | |
83 | } | |
7a938933 ILT |
84 | if len(p) > 0 { |
85 | d.nx = copy(d.x[:], p) | |
86 | } | |
87 | return | |
88 | } | |
89 | ||
7b1c3dd9 | 90 | func (d0 *digest) Sum(in []byte) []byte { |
7a938933 | 91 | // Make a copy of d0 so that caller can keep writing and summing. |
d5363590 | 92 | d := *d0 |
7a938933 ILT |
93 | |
94 | // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. | |
95 | len := d.len | |
96 | var tmp [64]byte | |
97 | tmp[0] = 0x80 | |
98 | if len%64 < 56 { | |
99 | d.Write(tmp[0 : 56-len%64]) | |
100 | } else { | |
101 | d.Write(tmp[0 : 64+56-len%64]) | |
102 | } | |
103 | ||
104 | // Length in bits. | |
105 | len <<= 3 | |
106 | for i := uint(0); i < 8; i++ { | |
107 | tmp[i] = byte(len >> (56 - 8*i)) | |
108 | } | |
109 | d.Write(tmp[0:8]) | |
110 | ||
111 | if d.nx != 0 { | |
112 | panic("d.nx != 0") | |
113 | } | |
114 | ||
d5363590 ILT |
115 | var digest [Size]byte |
116 | for i, s := range d.h { | |
117 | digest[i*4] = byte(s >> 24) | |
118 | digest[i*4+1] = byte(s >> 16) | |
119 | digest[i*4+2] = byte(s >> 8) | |
120 | digest[i*4+3] = byte(s) | |
7a938933 | 121 | } |
d5363590 ILT |
122 | |
123 | return append(in, digest[:]...) | |
7a938933 | 124 | } |