github.com/NBISweden/sda-cli@v0.1.2-0.20240506070033-4c8af88918df/decrypt/decrypt_test.go (about)

     1  package decrypt
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"testing"
    10  
    11  	createKey "github.com/NBISweden/sda-cli/create_key"
    12  	"github.com/NBISweden/sda-cli/encrypt"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/suite"
    15  )
    16  
    17  type DecryptTests struct {
    18  	suite.Suite
    19  	tempDir     string
    20  	fileContent []byte
    21  	testFile    *os.File
    22  }
    23  
    24  func TestDecryptTestSuite(t *testing.T) {
    25  	suite.Run(t, new(DecryptTests))
    26  }
    27  
    28  func (suite *DecryptTests) SetupTest() {
    29  	var err error
    30  	// Create a temporary directory for our files
    31  	suite.tempDir, err = os.MkdirTemp(os.TempDir(), "sda-cli-test-")
    32  	assert.NoError(suite.T(), err)
    33  
    34  	// create a test file...
    35  	suite.testFile, err = os.CreateTemp(suite.tempDir, "testfile-")
    36  	assert.NoError(suite.T(), err)
    37  
    38  	// ... create some content ...
    39  	suite.fileContent = []byte("This is some fine content right here.")
    40  	// ... and write the known content to it
    41  	err = os.WriteFile(suite.testFile.Name(), suite.fileContent, 0600)
    42  	assert.NoError(suite.T(), err)
    43  }
    44  
    45  func (suite *DecryptTests) TearDownTest() {
    46  	os.Remove(suite.tempDir)
    47  }
    48  
    49  func (suite *DecryptTests) TestreadPrivateKeyFile() {
    50  	testKeyFile := filepath.Join(suite.tempDir, "testkey")
    51  	// generate key files
    52  	err := createKey.GenerateKeyPair(testKeyFile, "test")
    53  	assert.NoError(suite.T(), err)
    54  
    55  	// Test reading a non-existent key
    56  	_, err = readPrivateKeyFile(testKeyFile, "")
    57  	assert.EqualError(suite.T(), err, fmt.Sprintf("private key file %s doesn't exist", testKeyFile))
    58  
    59  	// Test reading something that isn't a key
    60  	_, err = readPrivateKeyFile(suite.testFile.Name(), "")
    61  	assert.ErrorContains(suite.T(), err, fmt.Sprintf("file: %s", suite.testFile.Name()))
    62  
    63  	// Test reading a public key
    64  	_, err = readPrivateKeyFile(fmt.Sprintf("%s.pub.pem", testKeyFile), "")
    65  	assert.ErrorContains(suite.T(), err, "private key format not supported")
    66  
    67  	// Test reading a real key with wrong passphrase
    68  	_, err = readPrivateKeyFile(fmt.Sprintf("%s.sec.pem", testKeyFile), "wrong")
    69  	assert.ErrorContains(suite.T(), err, "chacha20poly1305: message authentication failed")
    70  
    71  	// Test reading a real key
    72  	_, err = readPrivateKeyFile(fmt.Sprintf("%s.sec.pem", testKeyFile), "test")
    73  	assert.NoError(suite.T(), err)
    74  }
    75  
    76  func (suite *DecryptTests) Testdecrypt() {
    77  	testKeyFile := filepath.Join(suite.tempDir, "testkey")
    78  	encryptedFile := fmt.Sprintf("%s.c4gh", suite.testFile.Name())
    79  	decryptedFile := filepath.Join(suite.tempDir, "decrypted_file")
    80  
    81  	// generate key files
    82  	err := createKey.GenerateKeyPair(testKeyFile, "")
    83  	assert.NoError(suite.T(), err)
    84  	// and read the private key
    85  	privateKey, err := readPrivateKeyFile(fmt.Sprintf("%s.sec.pem", testKeyFile), "")
    86  	assert.NoError(suite.T(), err)
    87  
    88  	// Encrypt a file using the encrypt module. change to the test directory to
    89  	// make sure that the checksum files end up there.
    90  	cwd, err := os.Getwd()
    91  	assert.NoError(suite.T(), err)
    92  	err = os.Chdir(suite.tempDir)
    93  	assert.NoError(suite.T(), err)
    94  	encryptArgs := []string{"encrypt", "-key", fmt.Sprintf("%s.pub.pem", testKeyFile), suite.testFile.Name()}
    95  	err = encrypt.Encrypt(encryptArgs)
    96  	assert.NoError(suite.T(), err, "encrypting file for testing failed")
    97  	err = os.Chdir(cwd)
    98  	assert.NoError(suite.T(), err)
    99  
   100  	// Test decrypting a non-existent file
   101  	msg := "no such file or directory"
   102  	if runtime.GOOS == "windows" {
   103  		msg = "The system cannot find the file specified."
   104  	}
   105  	err = decryptFile(filepath.Join(suite.tempDir, "non-existent"), "output_file", *privateKey)
   106  	assert.ErrorContains(suite.T(), err, msg)
   107  
   108  	// Test decryption with malformed key
   109  	fakeKey := [32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
   110  	err = decryptFile(encryptedFile, decryptedFile, fakeKey)
   111  	assert.EqualError(suite.T(), err, "could not create cryp4gh reader: could not find matching public key header, decryption failed")
   112  
   113  	// Test decrypting with the real key
   114  	err = decryptFile(encryptedFile, decryptedFile, *privateKey)
   115  	assert.NoError(suite.T(), err)
   116  
   117  	// Check content of the decrypted file
   118  	inFile, err := os.Open(decryptedFile)
   119  	assert.NoError(suite.T(), err, "unable to open decrypted file")
   120  	fileData, err := io.ReadAll(inFile)
   121  	assert.NoError(suite.T(), err, "unable to read decrypted file")
   122  	assert.Equal(suite.T(), fileData, suite.fileContent)
   123  }
   124  
   125  func (suite *DecryptTests) TestDecrypt() {
   126  	testKeyFile := filepath.Join(suite.tempDir, "testkey")
   127  	err := createKey.GenerateKeyPair(testKeyFile, "")
   128  	assert.NoError(suite.T(), err)
   129  
   130  	// Encrypt a file using the encrypt module. change to the test directory to
   131  	// make sure that the checksum files end up there.
   132  	cwd, err := os.Getwd()
   133  	assert.NoError(suite.T(), err)
   134  	err = os.Chdir(suite.tempDir)
   135  	assert.NoError(suite.T(), err)
   136  	encryptArgs := []string{"encrypt", "-key", fmt.Sprintf("%s.pub.pem", testKeyFile), suite.testFile.Name()}
   137  	assert.NoError(suite.T(), encrypt.Encrypt(encryptArgs), "encrypting file for testing failed")
   138  	assert.NoError(suite.T(), os.Chdir(cwd))
   139  	os.Setenv("C4GH_PASSWORD", "")
   140  	if runtime.GOOS != "windows" {
   141  		assert.NoError(suite.T(), os.Remove(suite.testFile.Name()))
   142  		os.Args = []string{"decrypt", "-key", fmt.Sprintf("%s.sec.pem", testKeyFile), fmt.Sprintf("%s.c4gh", suite.testFile.Name())}
   143  		err = Decrypt(os.Args)
   144  		assert.NoError(suite.T(), err, "decrypt failed unexpectedly")
   145  
   146  		// Check content of the decrypted file
   147  		inFile, err := os.Open(suite.testFile.Name())
   148  		assert.NoError(suite.T(), err, "unable to open decrypted file")
   149  		fileData, err := io.ReadAll(inFile)
   150  		assert.NoError(suite.T(), err, "unable to read decrypted file")
   151  		assert.Equal(suite.T(), string(suite.fileContent), string(fileData))
   152  	}
   153  
   154  	os.Args = []string{"decrypt", "-key", fmt.Sprintf("%s.sec.pem", testKeyFile), "--force-overwrite", fmt.Sprintf("%s.c4gh", suite.testFile.Name())}
   155  	err = Decrypt(os.Args)
   156  	assert.NoError(suite.T(), err, "decrypt failed unexpectedly")
   157  	os.Args = nil
   158  }