1// Copyright 2022 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package aead 18 19import ( 20 "errors" 21 "fmt" 22 23 "golang.org/x/crypto/chacha20poly1305" 24) 25 26const poly1305TagSize = 16 27 28// ChaCha20Poly1305InsecureNonce is an insecure implementation of the AEAD 29// interface that permits the user to set the nonce. 30type ChaCha20Poly1305InsecureNonce struct { 31 Key []byte 32} 33 34// NewChaCha20Poly1305InsecureNonce returns a ChaCha20Poly1305InsecureNonce instance. 35// The key argument should be a 32-bytes key. 36func NewChaCha20Poly1305InsecureNonce(key []byte) (*ChaCha20Poly1305InsecureNonce, error) { 37 if len(key) != chacha20poly1305.KeySize { 38 return nil, errors.New("bad key length") 39 } 40 41 return &ChaCha20Poly1305InsecureNonce{Key: key}, nil 42} 43 44// Encrypt encrypts plaintext with nonce and associatedData. 45func (ca *ChaCha20Poly1305InsecureNonce) Encrypt(nonce, plaintext, associatedData []byte) ([]byte, error) { 46 if len(plaintext) > maxInt-chacha20poly1305.NonceSize-poly1305TagSize { 47 return nil, fmt.Errorf("plaintext too long") 48 } 49 c, err := chacha20poly1305.New(ca.Key) 50 if err != nil { 51 return nil, err 52 } 53 return c.Seal(nil, nonce, plaintext, associatedData), nil 54} 55 56// Decrypt decrypts ciphertext with nonce and associatedData. 57func (ca *ChaCha20Poly1305InsecureNonce) Decrypt(nonce, ciphertext, associatedData []byte) ([]byte, error) { 58 if len(nonce) != chacha20poly1305.NonceSize { 59 return nil, fmt.Errorf("bad nonce length") 60 } 61 if len(ciphertext) < poly1305TagSize { 62 return nil, fmt.Errorf("ciphertext too short") 63 } 64 c, err := chacha20poly1305.New(ca.Key) 65 if err != nil { 66 return nil, err 67 } 68 return c.Open(nil, nonce, ciphertext, associatedData) 69} 70