82 lines
1.5 KiB
Go
82 lines
1.5 KiB
Go
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))
|
|
}
|