github.com/bir3/gocompiler@v0.9.2202/src/cmd/internal/notsha256/sha256.go (about) 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 5 // Package notsha256 implements the NOTSHA256 algorithm, 6 // a hash defined as bitwise NOT of SHA256. 7 // It is used in situations where exact fidelity to SHA256 is unnecessary. 8 // In particular, it is used in the compiler toolchain, 9 // which cannot depend directly on cgo when GOEXPERIMENT=boringcrypto 10 // (and in that mode the real sha256 uses cgo). 11 package notsha256 12 13 import ( 14 "encoding/binary" 15 "hash" 16 ) 17 18 // The size of a checksum in bytes. 19 const Size = 32 20 21 // The blocksize in bytes. 22 const BlockSize = 64 23 24 const ( 25 chunk = 64 26 init0 = 0x6A09E667 27 init1 = 0xBB67AE85 28 init2 = 0x3C6EF372 29 init3 = 0xA54FF53A 30 init4 = 0x510E527F 31 init5 = 0x9B05688C 32 init6 = 0x1F83D9AB 33 init7 = 0x5BE0CD19 34 ) 35 36 // digest represents the partial evaluation of a checksum. 37 type digest struct { 38 h [8]uint32 39 x [chunk]byte 40 nx int 41 len uint64 42 } 43 44 func (d *digest) Reset() { 45 d.h[0] = init0 46 d.h[1] = init1 47 d.h[2] = init2 48 d.h[3] = init3 49 d.h[4] = init4 50 d.h[5] = init5 51 d.h[6] = init6 52 d.h[7] = init7 53 d.nx = 0 54 d.len = 0 55 } 56 57 // New returns a new hash.Hash computing the NOTSHA256 checksum. 58 // state of the hash. 59 func New() hash.Hash { 60 d := new(digest) 61 d.Reset() 62 return d 63 } 64 65 func (d *digest) Size() int { 66 return Size 67 } 68 69 func (d *digest) BlockSize() int { return BlockSize } 70 71 func (d *digest) Write(p []byte) (nn int, err error) { 72 nn = len(p) 73 d.len += uint64(nn) 74 if d.nx > 0 { 75 n := copy(d.x[d.nx:], p) 76 d.nx += n 77 if d.nx == chunk { 78 block(d, d.x[:]) 79 d.nx = 0 80 } 81 p = p[n:] 82 } 83 if len(p) >= chunk { 84 n := len(p) &^ (chunk - 1) 85 block(d, p[:n]) 86 p = p[n:] 87 } 88 if len(p) > 0 { 89 d.nx = copy(d.x[:], p) 90 } 91 return 92 } 93 94 func (d *digest) Sum(in []byte) []byte { 95 // Make a copy of d so that caller can keep writing and summing. 96 d0 := *d 97 hash := d0.checkSum() 98 return append(in, hash[:]...) 99 } 100 101 func (d *digest) checkSum() [Size]byte { 102 len := d.len 103 // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64. 104 var tmp [64]byte 105 tmp[0] = 0x80 106 if len%64 < 56 { 107 d.Write(tmp[0 : 56-len%64]) 108 } else { 109 d.Write(tmp[0 : 64+56-len%64]) 110 } 111 112 // Length in bits. 113 len <<= 3 114 binary.BigEndian.PutUint64(tmp[:], len) 115 d.Write(tmp[0:8]) 116 117 if d.nx != 0 { 118 panic("d.nx != 0") 119 } 120 121 var digest [Size]byte 122 123 binary.BigEndian.PutUint32(digest[0:], d.h[0]^0xFFFFFFFF) 124 binary.BigEndian.PutUint32(digest[4:], d.h[1]^0xFFFFFFFF) 125 binary.BigEndian.PutUint32(digest[8:], d.h[2]^0xFFFFFFFF) 126 binary.BigEndian.PutUint32(digest[12:], d.h[3]^0xFFFFFFFF) 127 binary.BigEndian.PutUint32(digest[16:], d.h[4]^0xFFFFFFFF) 128 binary.BigEndian.PutUint32(digest[20:], d.h[5]^0xFFFFFFFF) 129 binary.BigEndian.PutUint32(digest[24:], d.h[6]^0xFFFFFFFF) 130 binary.BigEndian.PutUint32(digest[28:], d.h[7]^0xFFFFFFFF) 131 132 return digest 133 } 134 135 // Sum256 returns the SHA256 checksum of the data. 136 func Sum256(data []byte) [Size]byte { 137 var d digest 138 d.Reset() 139 d.Write(data) 140 return d.checkSum() 141 }