github.com/Oyster-zx/tendermint@v0.34.24-fork/crypto/xchacha20poly1305/xchachapoly.go (about) 1 // Package xchacha20poly1305 creates an AEAD using hchacha, chacha, and poly1305 2 // This allows for randomized nonces to be used in conjunction with chacha. 3 package xchacha20poly1305 4 5 import ( 6 "crypto/cipher" 7 "encoding/binary" 8 "errors" 9 "fmt" 10 11 "golang.org/x/crypto/chacha20poly1305" 12 ) 13 14 // Implements crypto.AEAD 15 type xchacha20poly1305 struct { 16 key [KeySize]byte 17 } 18 19 const ( 20 // KeySize is the size of the key used by this AEAD, in bytes. 21 KeySize = 32 22 // NonceSize is the size of the nonce used with this AEAD, in bytes. 23 NonceSize = 24 24 // TagSize is the size added from poly1305 25 TagSize = 16 26 // MaxPlaintextSize is the max size that can be passed into a single call of Seal 27 MaxPlaintextSize = (1 << 38) - 64 28 // MaxCiphertextSize is the max size that can be passed into a single call of Open, 29 // this differs from plaintext size due to the tag 30 MaxCiphertextSize = (1 << 38) - 48 31 32 // sigma are constants used in xchacha. 33 // Unrolled from a slice so that they can be inlined, as slices can't be constants. 34 sigma0 = uint32(0x61707865) 35 sigma1 = uint32(0x3320646e) 36 sigma2 = uint32(0x79622d32) 37 sigma3 = uint32(0x6b206574) 38 ) 39 40 // New returns a new xchachapoly1305 AEAD 41 func New(key []byte) (cipher.AEAD, error) { 42 if len(key) != KeySize { 43 return nil, errors.New("xchacha20poly1305: bad key length") 44 } 45 ret := new(xchacha20poly1305) 46 copy(ret.key[:], key) 47 return ret, nil 48 } 49 50 func (c *xchacha20poly1305) NonceSize() int { 51 return NonceSize 52 } 53 54 func (c *xchacha20poly1305) Overhead() int { 55 return TagSize 56 } 57 58 func (c *xchacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte { 59 if len(nonce) != NonceSize { 60 panic("xchacha20poly1305: bad nonce length passed to Seal") 61 } 62 63 if uint64(len(plaintext)) > MaxPlaintextSize { 64 panic("xchacha20poly1305: plaintext too large") 65 } 66 67 var subKey [KeySize]byte 68 var hNonce [16]byte 69 var subNonce [chacha20poly1305.NonceSize]byte 70 copy(hNonce[:], nonce[:16]) 71 72 HChaCha20(&subKey, &hNonce, &c.key) 73 74 // This can't error because we always provide a correctly sized key 75 chacha20poly1305, _ := chacha20poly1305.New(subKey[:]) 76 77 copy(subNonce[4:], nonce[16:]) 78 79 return chacha20poly1305.Seal(dst, subNonce[:], plaintext, additionalData) 80 } 81 82 func (c *xchacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { 83 if len(nonce) != NonceSize { 84 return nil, fmt.Errorf("xchacha20poly1305: bad nonce length passed to Open") 85 } 86 if uint64(len(ciphertext)) > MaxCiphertextSize { 87 return nil, fmt.Errorf("xchacha20poly1305: ciphertext too large") 88 } 89 var subKey [KeySize]byte 90 var hNonce [16]byte 91 var subNonce [chacha20poly1305.NonceSize]byte 92 copy(hNonce[:], nonce[:16]) 93 94 HChaCha20(&subKey, &hNonce, &c.key) 95 96 // This can't error because we always provide a correctly sized key 97 chacha20poly1305, _ := chacha20poly1305.New(subKey[:]) 98 99 copy(subNonce[4:], nonce[16:]) 100 101 return chacha20poly1305.Open(dst, subNonce[:], ciphertext, additionalData) 102 } 103 104 // HChaCha exported from 105 // https://github.com/aead/chacha20/blob/8b13a72661dae6e9e5dea04f344f0dc95ea29547/chacha/chacha_generic.go#L194 106 // TODO: Add support for the different assembly instructions used there. 107 108 // The MIT License (MIT) 109 110 // Copyright (c) 2016 Andreas Auernhammer 111 112 // Permission is hereby granted, free of charge, to any person obtaining a copy 113 // of this software and associated documentation files (the "Software"), to deal 114 // in the Software without restriction, including without limitation the rights 115 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 116 // copies of the Software, and to permit persons to whom the Software is 117 // furnished to do so, subject to the following conditions: 118 119 // The above copyright notice and this permission notice shall be included in all 120 // copies or substantial portions of the Software. 121 122 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 123 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 124 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 125 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 126 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 127 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 128 // SOFTWARE. 129 130 // HChaCha20 generates 32 pseudo-random bytes from a 128 bit nonce and a 256 bit secret key. 131 // It can be used as a key-derivation-function (KDF). 132 func HChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) { hChaCha20Generic(out, nonce, key) } 133 134 func hChaCha20Generic(out *[32]byte, nonce *[16]byte, key *[32]byte) { 135 v00 := sigma0 136 v01 := sigma1 137 v02 := sigma2 138 v03 := sigma3 139 v04 := binary.LittleEndian.Uint32(key[0:]) 140 v05 := binary.LittleEndian.Uint32(key[4:]) 141 v06 := binary.LittleEndian.Uint32(key[8:]) 142 v07 := binary.LittleEndian.Uint32(key[12:]) 143 v08 := binary.LittleEndian.Uint32(key[16:]) 144 v09 := binary.LittleEndian.Uint32(key[20:]) 145 v10 := binary.LittleEndian.Uint32(key[24:]) 146 v11 := binary.LittleEndian.Uint32(key[28:]) 147 v12 := binary.LittleEndian.Uint32(nonce[0:]) 148 v13 := binary.LittleEndian.Uint32(nonce[4:]) 149 v14 := binary.LittleEndian.Uint32(nonce[8:]) 150 v15 := binary.LittleEndian.Uint32(nonce[12:]) 151 152 for i := 0; i < 20; i += 2 { 153 v00 += v04 154 v12 ^= v00 155 v12 = (v12 << 16) | (v12 >> 16) 156 v08 += v12 157 v04 ^= v08 158 v04 = (v04 << 12) | (v04 >> 20) 159 v00 += v04 160 v12 ^= v00 161 v12 = (v12 << 8) | (v12 >> 24) 162 v08 += v12 163 v04 ^= v08 164 v04 = (v04 << 7) | (v04 >> 25) 165 v01 += v05 166 v13 ^= v01 167 v13 = (v13 << 16) | (v13 >> 16) 168 v09 += v13 169 v05 ^= v09 170 v05 = (v05 << 12) | (v05 >> 20) 171 v01 += v05 172 v13 ^= v01 173 v13 = (v13 << 8) | (v13 >> 24) 174 v09 += v13 175 v05 ^= v09 176 v05 = (v05 << 7) | (v05 >> 25) 177 v02 += v06 178 v14 ^= v02 179 v14 = (v14 << 16) | (v14 >> 16) 180 v10 += v14 181 v06 ^= v10 182 v06 = (v06 << 12) | (v06 >> 20) 183 v02 += v06 184 v14 ^= v02 185 v14 = (v14 << 8) | (v14 >> 24) 186 v10 += v14 187 v06 ^= v10 188 v06 = (v06 << 7) | (v06 >> 25) 189 v03 += v07 190 v15 ^= v03 191 v15 = (v15 << 16) | (v15 >> 16) 192 v11 += v15 193 v07 ^= v11 194 v07 = (v07 << 12) | (v07 >> 20) 195 v03 += v07 196 v15 ^= v03 197 v15 = (v15 << 8) | (v15 >> 24) 198 v11 += v15 199 v07 ^= v11 200 v07 = (v07 << 7) | (v07 >> 25) 201 v00 += v05 202 v15 ^= v00 203 v15 = (v15 << 16) | (v15 >> 16) 204 v10 += v15 205 v05 ^= v10 206 v05 = (v05 << 12) | (v05 >> 20) 207 v00 += v05 208 v15 ^= v00 209 v15 = (v15 << 8) | (v15 >> 24) 210 v10 += v15 211 v05 ^= v10 212 v05 = (v05 << 7) | (v05 >> 25) 213 v01 += v06 214 v12 ^= v01 215 v12 = (v12 << 16) | (v12 >> 16) 216 v11 += v12 217 v06 ^= v11 218 v06 = (v06 << 12) | (v06 >> 20) 219 v01 += v06 220 v12 ^= v01 221 v12 = (v12 << 8) | (v12 >> 24) 222 v11 += v12 223 v06 ^= v11 224 v06 = (v06 << 7) | (v06 >> 25) 225 v02 += v07 226 v13 ^= v02 227 v13 = (v13 << 16) | (v13 >> 16) 228 v08 += v13 229 v07 ^= v08 230 v07 = (v07 << 12) | (v07 >> 20) 231 v02 += v07 232 v13 ^= v02 233 v13 = (v13 << 8) | (v13 >> 24) 234 v08 += v13 235 v07 ^= v08 236 v07 = (v07 << 7) | (v07 >> 25) 237 v03 += v04 238 v14 ^= v03 239 v14 = (v14 << 16) | (v14 >> 16) 240 v09 += v14 241 v04 ^= v09 242 v04 = (v04 << 12) | (v04 >> 20) 243 v03 += v04 244 v14 ^= v03 245 v14 = (v14 << 8) | (v14 >> 24) 246 v09 += v14 247 v04 ^= v09 248 v04 = (v04 << 7) | (v04 >> 25) 249 } 250 251 binary.LittleEndian.PutUint32(out[0:], v00) 252 binary.LittleEndian.PutUint32(out[4:], v01) 253 binary.LittleEndian.PutUint32(out[8:], v02) 254 binary.LittleEndian.PutUint32(out[12:], v03) 255 binary.LittleEndian.PutUint32(out[16:], v12) 256 binary.LittleEndian.PutUint32(out[20:], v13) 257 binary.LittleEndian.PutUint32(out[24:], v14) 258 binary.LittleEndian.PutUint32(out[28:], v15) 259 }