76 lines
1.5 KiB
Go
76 lines
1.5 KiB
Go
/*
|
|
©AngelaMos | 2026
|
|
crypto.go
|
|
|
|
Argon2id key derivation and AEAD selection for the payload envelope
|
|
*/
|
|
|
|
package payload
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
|
|
"golang.org/x/crypto/argon2"
|
|
"golang.org/x/crypto/chacha20poly1305"
|
|
)
|
|
|
|
type kdfParams struct {
|
|
time uint32
|
|
memory uint32
|
|
threads uint8
|
|
}
|
|
|
|
func paramsForStrength(s Strength) kdfParams {
|
|
if s == StrengthHigh {
|
|
return kdfParams{time: argonHighTime, memory: argonHighMemory, threads: argonThreads}
|
|
}
|
|
return kdfParams{time: argonDefaultTime, memory: argonDefaultMemory, threads: argonThreads}
|
|
}
|
|
|
|
func (p kdfParams) valid() bool {
|
|
if p.threads == 0 || p.time == 0 {
|
|
return false
|
|
}
|
|
if p.memory > argonMaxMemory {
|
|
return false
|
|
}
|
|
return p.memory >= 8*uint32(p.threads)
|
|
}
|
|
|
|
func deriveKey(passphrase, salt []byte, p kdfParams) []byte {
|
|
return argon2.IDKey(passphrase, salt, p.time, p.memory, p.threads, keyLen)
|
|
}
|
|
|
|
func newAEAD(c Cipher, key []byte) (cipher.AEAD, byte, error) {
|
|
switch c {
|
|
case CipherAES256GCM:
|
|
aead, err := gcm(key)
|
|
return aead, cipherIDAES256GCM, err
|
|
case CipherChaCha20, "":
|
|
aead, err := chacha20poly1305.New(key)
|
|
return aead, cipherIDChaCha20, err
|
|
default:
|
|
return nil, 0, ErrUnknownCipher
|
|
}
|
|
}
|
|
|
|
func aeadByID(id byte, key []byte) (cipher.AEAD, error) {
|
|
switch id {
|
|
case cipherIDAES256GCM:
|
|
return gcm(key)
|
|
case cipherIDChaCha20:
|
|
return chacha20poly1305.New(key)
|
|
default:
|
|
return nil, ErrUnknownCipher
|
|
}
|
|
}
|
|
|
|
func gcm(key []byte) (cipher.AEAD, error) {
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return cipher.NewGCM(block)
|
|
}
|