ente/cli/internal/crypto/crypto_libsodium.go
2024-03-01 12:39:01 +05:30

260 lines
6.8 KiB
Go

package crypto
import (
"bufio"
"errors"
"github.com/ente-io/cli/utils/encoding"
"golang.org/x/crypto/nacl/box"
"golang.org/x/crypto/nacl/secretbox"
"io"
"log"
"os"
)
//func EncryptChaCha20poly1305LibSodium(data []byte, key []byte) ([]byte, []byte, error) {
// var buf bytes.Buffer
// encoder := sodium.MakeSecretStreamXCPEncoder(sodium.SecretStreamXCPKey{Bytes: key}, &buf)
// _, err := encoder.WriteAndClose(data)
// if err != nil {
// log.Println("Failed to write to encoder", err)
// return nil, nil, err
// }
// return buf.Bytes(), encoder.Header().Bytes, nil
//}
// EncryptChaCha20poly1305 encrypts the given data using the ChaCha20-Poly1305 algorithm.
// Parameters:
// - data: The plaintext data as a byte slice.
// - key: The key for encryption as a byte slice.
//
// Returns:
// - A byte slice representing the encrypted data.
// - A byte slice representing the header of the encrypted data.
// - An error object, which is nil if no error occurs.
func EncryptChaCha20poly1305(data []byte, key []byte) ([]byte, []byte, error) {
encryptor, header, err := NewEncryptor(key)
if err != nil {
return nil, nil, err
}
encoded, err := encryptor.Push(data, TagFinal)
if err != nil {
return nil, nil, err
}
return encoded, header, nil
}
// decryptChaCha20poly1305 decrypts the given data using the ChaCha20-Poly1305 algorithm.
// Parameters:
// - data: The encrypted data as a byte slice.
// - key: The key for decryption as a byte slice.
// - nonce: The nonce for decryption as a byte slice.
//
// Returns:
// - A byte slice representing the decrypted data.
// - An error object, which is nil if no error occurs.
//func decryptChaCha20poly1305LibSodium(data []byte, key []byte, nonce []byte) ([]byte, error) {
// reader := bytes.NewReader(data)
// header := sodium.SecretStreamXCPHeader{Bytes: nonce}
// decoder, err := sodium.MakeSecretStreamXCPDecoder(
// sodium.SecretStreamXCPKey{Bytes: key},
// reader,
// header)
// if err != nil {
// log.Println("Failed to make secret stream decoder", err)
// return nil, err
// }
// // Buffer to store the decrypted data
// decryptedData := make([]byte, len(data))
// n, err := decoder.Read(decryptedData)
// if err != nil && err != io.EOF {
// log.Println("Failed to read from decoder", err)
// return nil, err
// }
// return decryptedData[:n], nil
//}
func decryptChaCha20poly1305(data []byte, key []byte, nonce []byte) ([]byte, error) {
decryptor, err := NewDecryptor(key, nonce)
if err != nil {
return nil, err
}
decoded, tag, err := decryptor.Pull(data)
if tag != TagFinal {
return nil, errors.New("invalid tag")
}
if err != nil {
return nil, err
}
return decoded, nil
}
//func SecretBoxOpenLibSodium(c []byte, n []byte, k []byte) ([]byte, error) {
// var cp sodium.Bytes = c
// res, err := cp.SecretBoxOpen(sodium.SecretBoxNonce{Bytes: n}, sodium.SecretBoxKey{Bytes: k})
// return res, err
//}
func SecretBoxOpenBase64(cipher string, nonce string, k []byte) ([]byte, error) {
return SecretBoxOpen(encoding.DecodeBase64(cipher), encoding.DecodeBase64(nonce), k)
}
func SecretBoxOpen(c []byte, n []byte, k []byte) ([]byte, error) {
// Check for valid lengths of nonce and key
if len(n) != 24 || len(k) != 32 {
return nil, ErrOpenBox
}
var nonce [24]byte
var key [32]byte
copy(nonce[:], n)
copy(key[:], k)
// Decrypt the message using Go's nacl/secretbox
decrypted, ok := secretbox.Open(nil, c, &nonce, &key)
if !ok {
return nil, ErrOpenBox
}
return decrypted, nil
}
//func SealedBoxOpenLib(cipherText []byte, publicKey, masterSecret []byte) ([]byte, error) {
// var cp sodium.Bytes = cipherText
// om, err := cp.SealedBoxOpen(sodium.BoxKP{
// PublicKey: sodium.BoxPublicKey{Bytes: publicKey},
// SecretKey: sodium.BoxSecretKey{Bytes: masterSecret},
// })
// if err != nil {
// return nil, fmt.Errorf("failed to open sealed box: %v", err)
// }
// return om, nil
//}
func SealedBoxOpen(cipherText, publicKey, masterSecret []byte) ([]byte, error) {
if len(cipherText) < BoxSealBytes {
return nil, ErrOpenBox
}
// Extract ephemeral public key from the ciphertext
var ephemeralPublicKey [32]byte
copy(ephemeralPublicKey[:], publicKey[:32])
// Extract ephemeral public key from the ciphertext
var masterKey [32]byte
copy(masterKey[:], masterSecret[:32])
// Decrypt the message using nacl/box
decrypted, ok := box.OpenAnonymous(nil, cipherText, &ephemeralPublicKey, &masterKey)
if !ok {
return nil, ErrOpenBox
}
return decrypted, nil
}
func DecryptFile(encryptedFilePath string, decryptedFilePath string, key, nonce []byte) error {
inputFile, err := os.Open(encryptedFilePath)
if err != nil {
return err
}
defer inputFile.Close()
outputFile, err := os.Create(decryptedFilePath)
if err != nil {
return err
}
defer outputFile.Close()
reader := bufio.NewReader(inputFile)
writer := bufio.NewWriter(outputFile)
decryptor, err := NewDecryptor(key, nonce)
if err != nil {
return err
}
buf := make([]byte, decryptionBufferSize+XChaCha20Poly1305IetfABYTES)
for {
readCount, err := reader.Read(buf)
if err != nil && err != io.EOF {
log.Println("Failed to read from input file", err)
return err
}
if readCount == 0 {
break
}
n, tag, errErr := decryptor.Pull(buf[:readCount])
if errErr != nil && errErr != io.EOF {
log.Println("Failed to read from decoder", errErr)
return errErr
}
if _, err := writer.Write(n); err != nil {
log.Println("Failed to write to output file", err)
return err
}
if errErr == io.EOF {
break
}
if tag == TagFinal {
break
}
}
if err := writer.Flush(); err != nil {
log.Println("Failed to flush writer", err)
return err
}
return nil
}
//func DecryptFileLib(encryptedFilePath string, decryptedFilePath string, key, nonce []byte) error {
// inputFile, err := os.Open(encryptedFilePath)
// if err != nil {
// return err
// }
// defer inputFile.Close()
//
// outputFile, err := os.Create(decryptedFilePath)
// if err != nil {
// return err
// }
// defer outputFile.Close()
//
// reader := bufio.NewReader(inputFile)
// writer := bufio.NewWriter(outputFile)
//
// header := sodium.SecretStreamXCPHeader{Bytes: nonce}
// decoder, err := sodium.MakeSecretStreamXCPDecoder(
// sodium.SecretStreamXCPKey{Bytes: key},
// reader,
// header)
// if err != nil {
// log.Println("Failed to make secret stream decoder", err)
// return err
// }
//
// buf := make([]byte, decryptionBufferSize)
// for {
// n, errErr := decoder.Read(buf)
// if errErr != nil && errErr != io.EOF {
// log.Println("Failed to read from decoder", errErr)
// return errErr
// }
// if n == 0 {
// break
// }
// if _, err := writer.Write(buf[:n]); err != nil {
// log.Println("Failed to write to output file", err)
// return err
// }
// if errErr == io.EOF {
// break
// }
// }
// if err := writer.Flush(); err != nil {
// log.Println("Failed to flush writer", err)
// return err
// }
// return nil
//}