package crypto import ( "cachefs/pkg/provider" "crypto/rand" "io" "math" ) func isZero(nonce []byte) bool { for i := 0; i < len(nonce); i++ { if nonce[i] != 0 { return false } } return true } func initNonce(f provider.File) (nonce []byte, err error) { nonce = make([]byte, KDFNonceSize) n, err := io.ReadFull(f, nonce) if err != nil || n != len(nonce) || isZero(nonce) { _, err = io.ReadFull(rand.Reader, nonce) if err != nil { return } _, err = f.Seek(0, io.SeekStart) if err != nil { return } _, err = f.Write(nonce) return } return } func incNonce(nonce *[NonceSize]byte) { for i := len(nonce) - 2; i >= 0; i-- { nonce[i]++ if nonce[i] != 0 { break } else if i == 0 { // The counter is 88 bits, this is unreachable. panic("stream: chunk counter wrapped around") } } } func Size(s int64) int64 { return KDFNonceSize + s + (int64(math.Ceil(float64(s)/ChunkSize)) * Overhead) } func RealSize(s int64) int64 { s -= KDFNonceSize return s - (((s / FullSize) + 1) * Overhead) } func chunkNum(o int64) int64 { return int64(math.Ceil(float64(o) / ChunkSize)) } func align(o int64) (cn, off, roff int64) { cn = chunkNum(o) off = cn * FullSize roff = o - (cn * ChunkSize) if roff < 0 { cn-- off = cn * FullSize roff = o - (cn * ChunkSize) } return } func inc(nonce *[NonceSize]byte, n int64) { for i := int64(0); i < n; i++ { incNonce(nonce) } }