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.
7 // SHA-1 is cryptographically broken and should not be used for secure
19 crypto
.RegisterHash(crypto
.SHA1
, New
)
22 // The size of a SHA-1 checksum in bytes.
25 // The blocksize of SHA-1 in bytes.
37 // digest represents the partial evaluation of a checksum.
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)
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")
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
)
83 func appendUint64(b
[]byte, x
uint64) []byte {
85 binary
.BigEndian
.PutUint64(a
[:], x
)
86 return append(b
, a
[:]...)
89 func appendUint32(b
[]byte, x
uint32) []byte {
91 binary
.BigEndian
.PutUint32(a
[:], x
)
92 return append(b
, a
[:]...)
95 func consumeUint64(b
[]byte) ([]byte, uint64) {
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
102 func consumeUint32(b
[]byte) ([]byte, uint32) {
104 x
:= uint32(b
[3]) |
uint32(b
[2])<<8 |
uint32(b
[1])<<16 |
uint32(b
[0])<<24
108 func (d
*digest
) Reset() {
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
{
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
) {
135 n
:= copy(d
.x
[d
.nx
:], p
)
144 n
:= len(p
) &^ (chunk
- 1)
149 d
.nx
= copy(d
.x
[:], p
)
154 func (d
*digest
) Sum(in
[]byte) []byte {
155 // Make a copy of d so that caller can keep writing and summing.
157 hash
:= d0
.checkSum()
158 return append(in
, hash
[:]...)
161 func (d
*digest
) checkSum() [Size
]byte {
163 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
167 d
.Write(tmp
[0 : 56-len%64
])
169 d
.Write(tmp
[0 : 64+56-len%64
])
174 binary
.BigEndian
.PutUint64(tmp
[:], len)
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])
192 // ConstantTimeSum computes the same result of Sum() but in constant time
193 func (d
*digest
) ConstantTimeSum(in
[]byte) []byte {
195 hash
:= d0
.constSum()
196 return append(in
, hash
[:]...)
199 func (d
*digest
) constSum() [Size
]byte {
202 for i
:= uint(0); i
< 8; i
++ {
203 length
[i
] = byte(l
>> (56 - 8*i
))
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
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
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
243 d
.x
[i
] = length
[i
-56]
247 // compress, and only keep the digest if we actually needed the second block
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
)
260 // Sum returns the SHA-1 checksum of the data.
261 func Sum(data
[]byte) [Size
]byte {