fix(deps): update github.com/containers/image/v5 digest to 58d5eb6

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
renovate[bot]
2023-09-04 18:19:51 +00:00
committed by GitHub
parent 7f2f46e1b9
commit 897619f6b5
43 changed files with 1803 additions and 216 deletions

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2021 NYU Secure Systems Lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,290 @@
// Package encrypted provides a simple, secure system for encrypting data
// symmetrically with a passphrase.
//
// It uses scrypt derive a key from the passphrase and the NaCl secret box
// cipher for authenticated encryption.
package encrypted
import (
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"io"
"golang.org/x/crypto/nacl/secretbox"
"golang.org/x/crypto/scrypt"
)
const saltSize = 32
const (
boxKeySize = 32
boxNonceSize = 24
)
// KDFParameterStrength defines the KDF parameter strength level to be used for
// encryption key derivation.
type KDFParameterStrength uint8
const (
// Legacy defines legacy scrypt parameters (N:2^15, r:8, p:1)
Legacy KDFParameterStrength = iota + 1
// Standard defines standard scrypt parameters which is focusing 100ms of computation (N:2^16, r:8, p:1)
Standard
// OWASP defines OWASP recommended scrypt parameters (N:2^17, r:8, p:1)
OWASP
)
var (
// legacyParams represents old scrypt derivation parameters for backward
// compatibility.
legacyParams = scryptParams{
N: 32768, // 2^15
R: 8,
P: 1,
}
// standardParams defines scrypt parameters based on the scrypt creator
// recommendation to limit key derivation in time boxed to 100ms.
standardParams = scryptParams{
N: 65536, // 2^16
R: 8,
P: 1,
}
// owaspParams defines scrypt parameters recommended by OWASP
owaspParams = scryptParams{
N: 131072, // 2^17
R: 8,
P: 1,
}
// defaultParams defines scrypt parameters which will be used to generate a
// new key.
defaultParams = standardParams
)
const (
nameScrypt = "scrypt"
nameSecretBox = "nacl/secretbox"
)
type data struct {
KDF scryptKDF `json:"kdf"`
Cipher secretBoxCipher `json:"cipher"`
Ciphertext []byte `json:"ciphertext"`
}
type scryptParams struct {
N int `json:"N"`
R int `json:"r"`
P int `json:"p"`
}
func (sp *scryptParams) Equal(in *scryptParams) bool {
return in != nil && sp.N == in.N && sp.P == in.P && sp.R == in.R
}
func newScryptKDF(level KDFParameterStrength) (scryptKDF, error) {
salt := make([]byte, saltSize)
if err := fillRandom(salt); err != nil {
return scryptKDF{}, fmt.Errorf("unable to generate a random salt: %w", err)
}
var params scryptParams
switch level {
case Legacy:
params = legacyParams
case Standard:
params = standardParams
case OWASP:
params = owaspParams
default:
// Fallback to default parameters
params = defaultParams
}
return scryptKDF{
Name: nameScrypt,
Params: params,
Salt: salt,
}, nil
}
type scryptKDF struct {
Name string `json:"name"`
Params scryptParams `json:"params"`
Salt []byte `json:"salt"`
}
func (s *scryptKDF) Key(passphrase []byte) ([]byte, error) {
return scrypt.Key(passphrase, s.Salt, s.Params.N, s.Params.R, s.Params.P, boxKeySize)
}
// CheckParams checks that the encoded KDF parameters are what we expect them to
// be. If we do not do this, an attacker could cause a DoS by tampering with
// them.
func (s *scryptKDF) CheckParams() error {
switch {
case legacyParams.Equal(&s.Params):
case standardParams.Equal(&s.Params):
case owaspParams.Equal(&s.Params):
default:
return errors.New("unsupported scrypt parameters")
}
return nil
}
func newSecretBoxCipher() (secretBoxCipher, error) {
nonce := make([]byte, boxNonceSize)
if err := fillRandom(nonce); err != nil {
return secretBoxCipher{}, err
}
return secretBoxCipher{
Name: nameSecretBox,
Nonce: nonce,
}, nil
}
type secretBoxCipher struct {
Name string `json:"name"`
Nonce []byte `json:"nonce"`
encrypted bool
}
func (s *secretBoxCipher) Encrypt(plaintext, key []byte) []byte {
var keyBytes [boxKeySize]byte
var nonceBytes [boxNonceSize]byte
if len(key) != len(keyBytes) {
panic("incorrect key size")
}
if len(s.Nonce) != len(nonceBytes) {
panic("incorrect nonce size")
}
copy(keyBytes[:], key)
copy(nonceBytes[:], s.Nonce)
// ensure that we don't re-use nonces
if s.encrypted {
panic("Encrypt must only be called once for each cipher instance")
}
s.encrypted = true
return secretbox.Seal(nil, plaintext, &nonceBytes, &keyBytes)
}
func (s *secretBoxCipher) Decrypt(ciphertext, key []byte) ([]byte, error) {
var keyBytes [boxKeySize]byte
var nonceBytes [boxNonceSize]byte
if len(key) != len(keyBytes) {
panic("incorrect key size")
}
if len(s.Nonce) != len(nonceBytes) {
// return an error instead of panicking since the nonce is user input
return nil, errors.New("encrypted: incorrect nonce size")
}
copy(keyBytes[:], key)
copy(nonceBytes[:], s.Nonce)
res, ok := secretbox.Open(nil, ciphertext, &nonceBytes, &keyBytes)
if !ok {
return nil, errors.New("encrypted: decryption failed")
}
return res, nil
}
// Encrypt takes a passphrase and plaintext, and returns a JSON object
// containing ciphertext and the details necessary to decrypt it.
func Encrypt(plaintext, passphrase []byte) ([]byte, error) {
return EncryptWithCustomKDFParameters(plaintext, passphrase, Standard)
}
// EncryptWithCustomKDFParameters takes a passphrase, the plaintext and a KDF
// parameter level (Legacy, Standard, or OWASP), and returns a JSON object
// containing ciphertext and the details necessary to decrypt it.
func EncryptWithCustomKDFParameters(plaintext, passphrase []byte, kdfLevel KDFParameterStrength) ([]byte, error) {
k, err := newScryptKDF(kdfLevel)
if err != nil {
return nil, err
}
key, err := k.Key(passphrase)
if err != nil {
return nil, err
}
c, err := newSecretBoxCipher()
if err != nil {
return nil, err
}
data := &data{
KDF: k,
Cipher: c,
}
data.Ciphertext = c.Encrypt(plaintext, key)
return json.Marshal(data)
}
// Marshal encrypts the JSON encoding of v using passphrase.
func Marshal(v interface{}, passphrase []byte) ([]byte, error) {
return MarshalWithCustomKDFParameters(v, passphrase, Standard)
}
// MarshalWithCustomKDFParameters encrypts the JSON encoding of v using passphrase.
func MarshalWithCustomKDFParameters(v interface{}, passphrase []byte, kdfLevel KDFParameterStrength) ([]byte, error) {
data, err := json.MarshalIndent(v, "", "\t")
if err != nil {
return nil, err
}
return EncryptWithCustomKDFParameters(data, passphrase, kdfLevel)
}
// Decrypt takes a JSON-encoded ciphertext object encrypted using Encrypt and
// tries to decrypt it using passphrase. If successful, it returns the
// plaintext.
func Decrypt(ciphertext, passphrase []byte) ([]byte, error) {
data := &data{}
if err := json.Unmarshal(ciphertext, data); err != nil {
return nil, err
}
if data.KDF.Name != nameScrypt {
return nil, fmt.Errorf("encrypted: unknown kdf name %q", data.KDF.Name)
}
if data.Cipher.Name != nameSecretBox {
return nil, fmt.Errorf("encrypted: unknown cipher name %q", data.Cipher.Name)
}
if err := data.KDF.CheckParams(); err != nil {
return nil, err
}
key, err := data.KDF.Key(passphrase)
if err != nil {
return nil, err
}
return data.Cipher.Decrypt(data.Ciphertext, key)
}
// Unmarshal decrypts the data using passphrase and unmarshals the resulting
// plaintext into the value pointed to by v.
func Unmarshal(data []byte, v interface{}, passphrase []byte) error {
decrypted, err := Decrypt(data, passphrase)
if err != nil {
return err
}
return json.Unmarshal(decrypted, v)
}
func fillRandom(b []byte) error {
_, err := io.ReadFull(rand.Reader, b)
return err
}