blob: 78f5fe26f80762f82877156dc9d5a65dfd5b2ae5 [file] [log] [blame]
Conrad Meyer5bebadf2010-03-08 17:00:04 -08001// 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
Nigel Tao6a186d32011-04-20 09:57:05 +10005// Package sha512 implements the SHA384 and SHA512 hash algorithms as defined
6// in FIPS 180-2.
Conrad Meyer5bebadf2010-03-08 17:00:04 -08007package sha512
8
9import (
Adam Langleye308d552011-02-01 11:02:48 -050010 "crypto"
Conrad Meyer5bebadf2010-03-08 17:00:04 -080011 "hash"
12 "os"
13)
14
Adam Langleye308d552011-02-01 11:02:48 -050015func init() {
16 crypto.RegisterHash(crypto.SHA384, New384)
17 crypto.RegisterHash(crypto.SHA512, New)
18}
19
Conrad Meyer5bebadf2010-03-08 17:00:04 -080020// The size of a SHA512 checksum in bytes.
21const Size = 64
22
Conrad Meyer899e2e62010-03-16 13:26:21 -070023// The size of a SHA384 checksum in bytes.
24const Size384 = 48
25
Conrad Meyer5bebadf2010-03-08 17:00:04 -080026const (
Conrad Meyer899e2e62010-03-16 13:26:21 -070027 _Chunk = 128
28 _Init0 = 0x6a09e667f3bcc908
29 _Init1 = 0xbb67ae8584caa73b
30 _Init2 = 0x3c6ef372fe94f82b
31 _Init3 = 0xa54ff53a5f1d36f1
32 _Init4 = 0x510e527fade682d1
33 _Init5 = 0x9b05688c2b3e6c1f
34 _Init6 = 0x1f83d9abfb41bd6b
35 _Init7 = 0x5be0cd19137e2179
36 _Init0_384 = 0xcbbb9d5dc1059ed8
37 _Init1_384 = 0x629a292a367cd507
38 _Init2_384 = 0x9159015a3070dd17
39 _Init3_384 = 0x152fecd8f70e5939
40 _Init4_384 = 0x67332667ffc00b31
41 _Init5_384 = 0x8eb44a8768581511
42 _Init6_384 = 0xdb0c2e0d64f98fa7
43 _Init7_384 = 0x47b5481dbefa4fa4
Conrad Meyer5bebadf2010-03-08 17:00:04 -080044)
45
46// digest represents the partial evaluation of a checksum.
47type digest struct {
Conrad Meyer899e2e62010-03-16 13:26:21 -070048 h [8]uint64
49 x [_Chunk]byte
50 nx int
51 len uint64
52 is384 bool // mark if this digest is SHA-384
Conrad Meyer5bebadf2010-03-08 17:00:04 -080053}
54
55func (d *digest) Reset() {
Conrad Meyer899e2e62010-03-16 13:26:21 -070056 if !d.is384 {
57 d.h[0] = _Init0
58 d.h[1] = _Init1
59 d.h[2] = _Init2
60 d.h[3] = _Init3
61 d.h[4] = _Init4
62 d.h[5] = _Init5
63 d.h[6] = _Init6
64 d.h[7] = _Init7
65 } else {
66 d.h[0] = _Init0_384
67 d.h[1] = _Init1_384
68 d.h[2] = _Init2_384
69 d.h[3] = _Init3_384
70 d.h[4] = _Init4_384
71 d.h[5] = _Init5_384
72 d.h[6] = _Init6_384
73 d.h[7] = _Init7_384
74 }
Conrad Meyer5bebadf2010-03-08 17:00:04 -080075 d.nx = 0
76 d.len = 0
77}
78
79// New returns a new hash.Hash computing the SHA512 checksum.
80func New() hash.Hash {
81 d := new(digest)
82 d.Reset()
83 return d
84}
85
Conrad Meyer899e2e62010-03-16 13:26:21 -070086// New384 returns a new hash.Hash computing the SHA384 checksum.
87func New384() hash.Hash {
88 d := new(digest)
89 d.is384 = true
90 d.Reset()
91 return d
92}
93
94func (d *digest) Size() int {
95 if !d.is384 {
96 return Size
97 }
98 return Size384
99}
Conrad Meyer5bebadf2010-03-08 17:00:04 -0800100
101func (d *digest) Write(p []byte) (nn int, err os.Error) {
102 nn = len(p)
103 d.len += uint64(nn)
104 if d.nx > 0 {
105 n := len(p)
106 if n > _Chunk-d.nx {
107 n = _Chunk - d.nx
108 }
109 for i := 0; i < n; i++ {
110 d.x[d.nx+i] = p[i]
111 }
112 d.nx += n
113 if d.nx == _Chunk {
Russ Coxbb84f4b2010-05-27 14:51:47 -0700114 _Block(d, d.x[0:])
Conrad Meyer5bebadf2010-03-08 17:00:04 -0800115 d.nx = 0
116 }
117 p = p[n:]
118 }
119 n := _Block(d, p)
120 p = p[n:]
121 if len(p) > 0 {
Russ Coxd86ab012010-10-26 21:52:54 -0700122 d.nx = copy(d.x[:], p)
Conrad Meyer5bebadf2010-03-08 17:00:04 -0800123 }
124 return
125}
126
127func (d0 *digest) Sum() []byte {
128 // Make a copy of d0 so that caller can keep writing and summing.
129 d := new(digest)
130 *d = *d0
131
132 // Padding. Add a 1 bit and 0 bits until 112 bytes mod 128.
133 len := d.len
134 var tmp [128]byte
135 tmp[0] = 0x80
136 if len%128 < 112 {
137 d.Write(tmp[0 : 112-len%128])
138 } else {
139 d.Write(tmp[0 : 128+112-len%128])
140 }
141
142 // Length in bits.
143 len <<= 3
144 for i := uint(0); i < 16; i++ {
145 tmp[i] = byte(len >> (120 - 8*i))
146 }
147 d.Write(tmp[0:16])
148
149 if d.nx != 0 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700150 panic("d.nx != 0")
Conrad Meyer5bebadf2010-03-08 17:00:04 -0800151 }
152
153 p := make([]byte, 64)
154 j := 0
155 for _, s := range d.h {
156 p[j+0] = byte(s >> 56)
157 p[j+1] = byte(s >> 48)
158 p[j+2] = byte(s >> 40)
159 p[j+3] = byte(s >> 32)
160 p[j+4] = byte(s >> 24)
161 p[j+5] = byte(s >> 16)
162 p[j+6] = byte(s >> 8)
163 p[j+7] = byte(s >> 0)
164 j += 8
165 }
Conrad Meyer899e2e62010-03-16 13:26:21 -0700166 if d.is384 {
167 return p[0:48]
168 }
Conrad Meyer5bebadf2010-03-08 17:00:04 -0800169 return p
170}