forked from emailfabric/dkim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
body_hash.go
70 lines (65 loc) · 1.64 KB
/
body_hash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package dkim
import (
"hash"
)
// simpleBodyHash is used to generate the body hash using simple canonicalization.
// simpleBodyHash implements io.Writer. Write chunks of body content to it,
// write the whole body at once, or copy the body from a reader using io.Copy.
type simpleBodyHash struct {
h hash.Hash
crlfs []byte
}
// newSimpleBodyHash creates a new simpleBodyHash.
func newSimpleBodyHash(hash hash.Hash) *simpleBodyHash {
return &simpleBodyHash{
h: hash,
crlfs: make([]byte, 0, 8), // small initial empty buffer
}
}
// Write (chunk of) raw body using "simple" canonicalization.
// It ignores all empty lines at the end of the last Write.
// Close() should be called to add the final single CRLF.
func (bh *simpleBodyHash) Write(p []byte) (n int, err error) {
// note: n is number consumed from p, not number written to hash
l := len(p)
if l == 0 {
return
}
// find trailing CR/LFs in this chunk
i := l
for {
c := p[i-1]
if c == '\r' || c == '\n' {
i--
if i == 0 {
break
}
} else {
break
}
}
// write trailing CR/LFs from last chunk if this chunk has non-empty lines
if len(bh.crlfs) != 0 && i > 0 {
nw, ew := bh.h.Write(bh.crlfs)
if ew != nil {
bh.crlfs = bh.crlfs[nw:]
return 0, ew
}
bh.crlfs = bh.crlfs[0:0] // clear buffer
}
// write this chunk up to trailing CR/LFs
nw, ew := bh.h.Write(p[0:i])
if ew != nil {
return nw, ew
}
// save trailing CR/LFs for next write
if i != l {
bh.crlfs = append(bh.crlfs, p[i:l]...)
}
return l, nil
}
// Sum calculates the hash.
func (bh *simpleBodyHash) Sum() []byte {
bh.h.Write([]byte("\r\n")) // write final CRLF
return bh.h.Sum(nil)
}