cachefs/pkg/provider/crypto/helper.go

85 lines
1.6 KiB
Go

// Copyright (C) 2022 Marius Schellenberger
// crypto parts taken from https://github.com/filosottile/age
package crypto
import (
"cachefs/pkg/provider"
"crypto/rand"
"encoding/binary"
"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
}
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)
}
}
func put(nonce *[NonceSize]byte, n int64) {
binary.BigEndian.PutUint64((*nonce)[3:11], uint64(n))
}