Minor refactor

This commit is contained in:
Neeraj Gupta 2023-10-20 11:34:07 +05:30
parent ccb8a5834c
commit 5f029fc12f
6 changed files with 182 additions and 169 deletions

9
go.mod
View file

@ -6,7 +6,9 @@ require (
github.com/go-resty/resty/v2 v2.7.0
github.com/google/uuid v1.3.1
github.com/jamesruan/sodium v1.0.14
golang.org/x/crypto v0.13.0
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1
github.com/pkg/errors v0.9.1
golang.org/x/crypto v0.14.0
)
require (
@ -18,7 +20,6 @@ require (
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/zalando/go-keyring v0.2.3 // indirect
go.artemisc.eu/godium v0.0.0-20201014025004-f08c318a71b3 // indirect
)
@ -41,8 +42,8 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

7
go.sum
View file

@ -165,6 +165,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -223,6 +224,8 @@ golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -351,9 +354,13 @@ golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View file

@ -1,18 +1,10 @@
package crypto
import (
"bufio"
"bytes"
"cli-go/utils/encoding"
"encoding/base64"
"encoding/binary"
"fmt"
blake2b "github.com/minio/blake2b-simd"
"io"
"log"
"os"
"github.com/jamesruan/sodium"
"github.com/minio/blake2b-simd"
"golang.org/x/crypto/argon2"
)
@ -23,6 +15,12 @@ const (
decryptionBufferSize = 4 * 1024 * 1024
)
const (
cryptoKDFBlake2bBytesMin = 16
cryptoKDFBlake2bBytesMax = 64
cryptoGenerichashBlake2bSaltBytes = 16
cryptoGenerichashBlake2bPersonalBytes = 16
)
// DeriveArgonKey generates a 32-bit cryptographic key using the Argon2id algorithm.
// Parameters:
@ -52,75 +50,6 @@ func DeriveArgonKey(password, salt string, memLimit, opsLimit int) ([]byte, erro
return key, 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 DecryptChaCha20poly1305(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 DecryptChaChaBase64(data string, key []byte, nonce string) (string, []byte, error) {
// Decode data from base64
dataBytes, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return "", nil, fmt.Errorf("invalid data: %v", err)
}
// Decode nonce from base64
nonceBytes, err := base64.StdEncoding.DecodeString(nonce)
if err != nil {
return "", nil, fmt.Errorf("invalid nonce: %v", err)
}
// Decrypt data
decryptedData, err := DecryptChaCha20poly1305(dataBytes, key, nonceBytes)
if err != nil {
return "", nil, fmt.Errorf("failed to decrypt data: %v", err)
}
return base64.StdEncoding.EncodeToString(decryptedData), decryptedData, 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) {
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
}
// DeriveLoginKey derives a login key from the given key encryption key.
// This loginKey act as user provided password during SRP authentication.
// Parameters: keyEncKey: This is the keyEncryptionKey that is derived from the user's password.
@ -130,13 +59,6 @@ func DeriveLoginKey(keyEncKey []byte) []byte {
return subKey[:16]
}
const (
cryptoKDFBlake2bBytesMin = 16
cryptoKDFBlake2bBytesMax = 64
cryptoGenerichashBlake2bSaltBytes = 16
cryptoGenerichashBlake2bPersonalBytes = 16
)
func deriveSubKey(masterKey []byte, context string, subKeyID uint64, subKeyLength uint32) ([]byte, error) {
if subKeyLength < cryptoKDFBlake2bBytesMin || subKeyLength > cryptoKDFBlake2bBytesMax {
return nil, fmt.Errorf("subKeyLength out of bounds")
@ -162,81 +84,3 @@ func deriveSubKey(masterKey []byte, context string, subKeyID uint64, subKeyLengt
hasher.Write(nil) // No data, just using key, salt, and personalization
return hasher.Sum(nil), nil
}
func SecretBoxOpen(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) {
var cp sodium.Bytes = encoding.DecodeBase64(cipher)
out, err := cp.SecretBoxOpen(sodium.SecretBoxNonce{Bytes: encoding.DecodeBase64(nonce)}, sodium.SecretBoxKey{Bytes: k})
if err != nil {
return nil, err
}
return out, nil
}
func SealedBoxOpen(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 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)
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
}

View file

@ -0,0 +1,161 @@
package crypto
import (
"bufio"
"bytes"
"cli-go/utils/encoding"
"encoding/base64"
"fmt"
"github.com/jamesruan/sodium"
"io"
"log"
"os"
)
// 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) {
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
}
// 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 decryptChaCha20poly1305(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 DecryptChaChaBase64(data string, key []byte, nonce string) (string, []byte, error) {
// Decode data from base64
dataBytes, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return "", nil, fmt.Errorf("invalid data: %v", err)
}
// Decode nonce from base64
nonceBytes, err := base64.StdEncoding.DecodeString(nonce)
if err != nil {
return "", nil, fmt.Errorf("invalid nonce: %v", err)
}
// Decrypt data
decryptedData, err := decryptChaCha20poly1305(dataBytes, key, nonceBytes)
if err != nil {
return "", nil, fmt.Errorf("failed to decrypt data: %v", err)
}
return base64.StdEncoding.EncodeToString(decryptedData), decryptedData, nil
}
func SecretBoxOpen(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) {
var cp sodium.Bytes = encoding.DecodeBase64(cipher)
out, err := cp.SecretBoxOpen(sodium.SecretBoxNonce{Bytes: encoding.DecodeBase64(nonce)}, sodium.SecretBoxKey{Bytes: k})
if err != nil {
return nil, err
}
return out, nil
}
func SealedBoxOpen(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 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)
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
}

View file

@ -43,7 +43,7 @@ func TestDecryptChaCha20poly1305(t *testing.T) {
t.Fatalf("Failed to decode cipher nonce: %v", err)
}
decryptedText, err := DecryptChaCha20poly1305(decodedCipherText, derivedKey, decodedCipherNonce)
decryptedText, err := decryptChaCha20poly1305(decodedCipherText, derivedKey, decodedCipherNonce)
if err != nil {
t.Fatalf("Failed to decrypt: %v", err)
}

View file

@ -23,7 +23,7 @@ func MakeEncString(plainTextBytes []byte, key []byte) *EncString {
}
func (e *EncString) MustDecrypt(key []byte) []byte {
plainBytes, err := crypto.DecryptChaCha20poly1305(encoding.DecodeBase64(e.CipherText), key, encoding.DecodeBase64(e.Nonce))
_, plainBytes, err := crypto.DecryptChaChaBase64(e.CipherText, key, e.Nonce)
if err != nil {
panic(err)
}