// setup produces a sub-key and Salsa20 counter given a nonce and key. func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { // We use XSalsa20 for encryption so first we need to generate a // key and nonce with HSalsa20. var hNonce [16]byte copy(hNonce[:], nonce[:]) salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) // The final 8 bytes of the original nonce form the new nonce. copy(counter[:], nonce[16:]) }
// XORKeyStream crypts bytes from in to out using the given key and nonce. In // and out may be the same slice but otherwise should not overlap. Nonce must // be either 8 or 24 bytes long. func XORKeyStream(out, in []byte, nonce []byte, key *[32]byte) { if len(out) < len(in) { in = in[:len(out)] } var subNonce [16]byte if len(nonce) == 24 { var subKey [32]byte var hNonce [16]byte copy(hNonce[:], nonce[:16]) salsa.HSalsa20(&subKey, &hNonce, key, &salsa.Sigma) copy(subNonce[:], nonce[16:]) key = &subKey } else if len(nonce) == 8 { copy(subNonce[:], nonce[:]) } else { panic("salsa20: nonce must be 8 or 24 bytes") } salsa.XORKeyStream(out, in, &subNonce, key) }
// Precompute calculates the shared key between peersPublicKey and privateKey // and writes it to sharedKey. The shared key can be used with // OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing // when using the same pair of keys repeatedly. func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) }