git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/crypto/chacha20/chacha20_generic.go (about)

     1  //go:build !amd64
     2  
     3  package chacha20
     4  
     5  import (
     6  	"golang.org/x/crypto/chacha20"
     7  )
     8  
     9  // see also: https://cs.opensource.google/go/x/crypto/+/master:chacha20/chacha_generic.go
    10  
    11  // XORKeyStream crypts bytes from src to dst using the given nonce and key.
    12  // The length of the nonce determinds the version of ChaCha20:
    13  // - 8 bytes:  ChaCha20 with a 64 bit nonce and a 2^64 * 64 byte period.
    14  // - 12 bytes: ChaCha20 as defined in RFC 7539 and a 2^32 * 64 byte period.
    15  // - 24 bytes: XChaCha20 with a 192 bit nonce and a 2^64 * 64 byte period.
    16  // Src and dst may be the same slice but otherwise should not overlap.
    17  // If len(dst) < len(src) this function panics.
    18  // If the nonce is neither 64, 96 nor 192 bits long, this function panics.
    19  // func XORKeyStream(dst, src, nonce, key []byte) {
    20  // 	if runtime.GOARCH == "amd64" || runtime.GOARCH == "386" {
    21  // 		chacha.XORKeyStream(dst, src, nonce, key, 20)
    22  // 		return
    23  // 	}
    24  
    25  // 	chacha20.(dst, src, nonce, key, 20)
    26  // }
    27  
    28  // New returns a new cipher.Stream implementing a ChaCha20 version.
    29  // The nonce must be unique for one key for all time.
    30  // The length of the nonce determinds the version of ChaCha20:
    31  // - 8 bytes:  ChaCha20 with a 64 bit nonce and a 2^64 * 64 byte period.
    32  // - 12 bytes: ChaCha20 as defined in RFC 7539 and a 2^32 * 64 byte period.
    33  // - 24 bytes: XChaCha20 with a 192 bit nonce and a 2^64 * 64 byte period.
    34  // If the nonce is neither 64, 96 nor 192 bits long, a non-nil error is returned.
    35  func New(key, nonce []byte) (StreamCipher, error) {
    36  	// TODO: here we use a 96-bit nonce, because IETF's ChaCha20 use a 96-bit nonce,
    37  	// but in the future we will want to use the original ChaCha20 with a 64-bit nonce
    38  	// so for now, messages are limited to (64 B * 2^32-1) = ~256 GB
    39  	var ietfNonce [12]byte
    40  
    41  	if len(key) != KeySize {
    42  		return nil, ErrBadKeyLength
    43  	}
    44  	if len(nonce) != NonceSize {
    45  		return nil, ErrBadNonceLength
    46  	}
    47  
    48  	copy(ietfNonce[4:12], nonce[0:8])
    49  	return chacha20.NewUnauthenticatedCipher(key, ietfNonce[:])
    50  }