Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
chore: styles
  • Loading branch information
nimish-ks committed Oct 29, 2024
commit 8670263deb76e10b3031d9ef1a75395bd20538e4
191 changes: 95 additions & 96 deletions phase/crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,19 @@ func EncryptAsymmetric(plaintext, publicKeyHex string) (string, error) {
return "", err
}

// Spin up ephemeral X25519 keys
// Spin up ephemeral X25519 keys
kp, err := RandomKeyPair()
if err != nil {
return "", err
}

// Perform a DHKA
// Perform a DHKA
sessionKeys, err := ClientSessionKeys(kp, recipientPubKeyBytes)
if err != nil {
return "", err
}

// Encrypt data with XChaCha20-poly1305
// Encrypt data with XChaCha20-poly1305
ciphertext, err := EncryptB64(plaintext, sessionKeys.Tx)
if err != nil {
return "", err
Expand All @@ -145,93 +145,93 @@ func EncryptAsymmetric(plaintext, publicKeyHex string) (string, error) {
}

func DecryptAsymmetric(ciphertextString, privateKeyHex, publicKeyHex string) (string, error) {
segments := strings.Split(ciphertextString, ":")

version := segments[1]
if version != "v1" {
err := fmt.Errorf("unsupported version: %s", version)
log.Println(err)
return "", err
}

ephemeralPublicKeyBytes, err := hex.DecodeString(segments[2])
if err != nil {
log.Printf("Failed to decode ephemeral public key hex: %v\n", err)
return "", err
}

privateKeyBytes, err := hex.DecodeString(privateKeyHex)
if err != nil {
log.Printf("Failed to decode private key hex: %v\n", err)
return "", err
}

publicKeyBytes, err := hex.DecodeString(publicKeyHex)
if err != nil {
log.Printf("Failed to decode public key hex: %v\n", err)
return "", err
}

kp := sodium.KXKP{
PublicKey: sodium.KXPublicKey{Bytes: publicKeyBytes},
SecretKey: sodium.KXSecretKey{Bytes: privateKeyBytes},
}

// Perform DHKA
sessionKeys, err := ServerSessionKeys(kp, ephemeralPublicKeyBytes)
if err != nil {
return "", err
}

// Extract ciphertext from ph.
ciphertextB64 := segments[3]

// Decrypt data with XChaCha20-poly1305
plaintext, err := DecryptB64(ciphertextB64, sessionKeys.Rx)
if err != nil {
log.Printf("Failed to decrypt asymmetrically: %v\n", err)
return "", err
}
return plaintext, nil
segments := strings.Split(ciphertextString, ":")

version := segments[1]
if version != "v1" {
err := fmt.Errorf("unsupported version: %s", version)
log.Println(err)
return "", err
}

ephemeralPublicKeyBytes, err := hex.DecodeString(segments[2])
if err != nil {
log.Printf("Failed to decode ephemeral public key hex: %v\n", err)
return "", err
}

privateKeyBytes, err := hex.DecodeString(privateKeyHex)
if err != nil {
log.Printf("Failed to decode private key hex: %v\n", err)
return "", err
}

publicKeyBytes, err := hex.DecodeString(publicKeyHex)
if err != nil {
log.Printf("Failed to decode public key hex: %v\n", err)
return "", err
}

kp := sodium.KXKP{
PublicKey: sodium.KXPublicKey{Bytes: publicKeyBytes},
SecretKey: sodium.KXSecretKey{Bytes: privateKeyBytes},
}

// Perform DHKA
sessionKeys, err := ServerSessionKeys(kp, ephemeralPublicKeyBytes)
if err != nil {
return "", err
}

// Extract ciphertext from ph.
ciphertextB64 := segments[3]

// Decrypt data with XChaCha20-poly1305
plaintext, err := DecryptB64(ciphertextB64, sessionKeys.Rx)
if err != nil {
log.Printf("Failed to decrypt asymmetrically: %v\n", err)
return "", err
}
return plaintext, nil
}

// decryptSecret decrypts a secret's key, value, and optional comment using asymmetric decryption.
func DecryptSecret(secret map[string]interface{}, privateKeyHex, publicKeyHex string) (decryptedKey string, decryptedValue string, decryptedComment string, err error) {
// Decrypt the key
key, ok := secret["key"].(string)
if !ok {
err = fmt.Errorf("key is not a string")
return
}
decryptedKey, err = DecryptAsymmetric(key, privateKeyHex, publicKeyHex)
if err != nil {
log.Printf("Failed to decrypt key: %v\n", err)
return
}

// Decrypt the value
value, ok := secret["value"].(string)
if !ok {
err = fmt.Errorf("value is not a string")
return
}
decryptedValue, err = DecryptAsymmetric(value, privateKeyHex, publicKeyHex)
if err != nil {
log.Printf("Failed to decrypt value: %v\n", err)
return
}

// Decrypt the comment if it exists
comment, ok := secret["comment"].(string)
if ok && comment != "" {
decryptedComment, err = DecryptAsymmetric(comment, privateKeyHex, publicKeyHex)
if err != nil {
log.Printf("Failed to decrypt comment: %v\n", err)
err = nil
}
}

return decryptedKey, decryptedValue, decryptedComment, nil
// Decrypt the key
key, ok := secret["key"].(string)
if !ok {
err = fmt.Errorf("key is not a string")
return
}
decryptedKey, err = DecryptAsymmetric(key, privateKeyHex, publicKeyHex)
if err != nil {
log.Printf("Failed to decrypt key: %v\n", err)
return
}

// Decrypt the value
value, ok := secret["value"].(string)
if !ok {
err = fmt.Errorf("value is not a string")
return
}
decryptedValue, err = DecryptAsymmetric(value, privateKeyHex, publicKeyHex)
if err != nil {
log.Printf("Failed to decrypt value: %v\n", err)
return
}

// Decrypt the comment if it exists
comment, ok := secret["comment"].(string)
if ok && comment != "" {
decryptedComment, err = DecryptAsymmetric(comment, privateKeyHex, publicKeyHex)
if err != nil {
log.Printf("Failed to decrypt comment: %v\n", err)
err = nil
}
}

return decryptedKey, decryptedValue, decryptedComment, nil
}

// Decrypt decrypts the provided ciphertext using the Phase encryption mechanism.
Expand Down Expand Up @@ -293,24 +293,23 @@ func GenerateEnvKeyPair(seed string) (publicKeyHex, privateKeyHex string, err er
return "", "", fmt.Errorf("incorrect seed length: expected 32 bytes, got %d", len(seedBytes))
}

// Prepare the seed as KXSeed
var seedKX sodium.KXSeed
copy(seedKX.Bytes[:], seedBytes)
// Prepare the seed as KXSeed
var seedKX sodium.KXSeed
copy(seedKX.Bytes[:], seedBytes)

// Allocate slice if KXSeed.Bytes is a slice
seedKX.Bytes = make([]byte, len(seedBytes))
copy(seedKX.Bytes, seedBytes)

// Generate key pair from seed
keyPair := sodium.SeedKXKP(seedKX)
// Generate key pair from seed
keyPair := sodium.SeedKXKP(seedKX)

publicKeyHex = hex.EncodeToString(keyPair.PublicKey.Bytes[:])
privateKeyHex = hex.EncodeToString(keyPair.SecretKey.Bytes[:])
publicKeyHex = hex.EncodeToString(keyPair.PublicKey.Bytes[:])
privateKeyHex = hex.EncodeToString(keyPair.SecretKey.Bytes[:])

return publicKeyHex, privateKeyHex, nil
return publicKeyHex, privateKeyHex, nil
}


// Blake2bDigest generates a BLAKE2b hash of the input string with a salt using the sodium library.
func Blake2bDigest(inputStr, salt string) (string, error) {
hashSize := 32 // 32 bytes (256 bits) as an example
Expand Down Expand Up @@ -370,4 +369,4 @@ func ReconstructSecret(share1, share2 string) (string, error) {

// Encode the reconstructed secret back to a hex string.
return hex.EncodeToString(reconstructedSecret), nil
}
}
57 changes: 28 additions & 29 deletions phase/misc/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,57 @@ import (
)

const (
Version = "1.0.1"
PhVersion = "v1"
Version = "1.0.1"
PhVersion = "v1"
PhaseCloudAPIHost = "https://console.phase.dev"
)

var (
VerifySSL = false
PhaseDebug = false
VerifySSL = false
PhaseDebug = false
)

var (

// Compiled regex patterns
PssUserPattern = regexp.MustCompile(`^pss_user:v(\d+):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64})$`)
PssServicePattern = regexp.MustCompile(`^pss_service:v(\d+):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64}):([a-fA-F0-9]{64})$`)
// CrossEnvPattern = regexp.MustCompile(`\$\{(.+?)\.(.+?)\}`)

// CrossEnvPattern = regexp.MustCompile(`\$\{(.+?)\.(.+?)\}`)
// LocalRefPattern = regexp.MustCompile(`\$\{([^.]+?)\}`)

// Regex to identify secret references
SecretRefRegex = regexp.MustCompile(`\$\{([^}]+)\}`)
)

// Regex to identify secret references
SecretRefRegex = regexp.MustCompile(`\$\{([^}]+)\}`)
)

type Environment struct {
ID string `json:"id"`
Name string `json:"name"`
EnvType string `json:"env_type"`
ID string `json:"id"`
Name string `json:"name"`
EnvType string `json:"env_type"`
}

type EnvironmentKey struct {
ID string `json:"id"`
Environment Environment `json:"environment"`
IdentityKey string `json:"identity_key"`
WrappedSeed string `json:"wrapped_seed"`
WrappedSalt string `json:"wrapped_salt"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
DeletedAt *string `json:"deleted_at"`
User *string `json:"user"`
ID string `json:"id"`
Environment Environment `json:"environment"`
IdentityKey string `json:"identity_key"`
WrappedSeed string `json:"wrapped_seed"`
WrappedSalt string `json:"wrapped_salt"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
DeletedAt *string `json:"deleted_at"`
User *string `json:"user"`
}

type App struct {
ID string `json:"id"`
Name string `json:"name"`
Encryption string `json:"encryption"`
EnvironmentKeys []EnvironmentKey `json:"environment_keys"`
ID string `json:"id"`
Name string `json:"name"`
Encryption string `json:"encryption"`
EnvironmentKeys []EnvironmentKey `json:"environment_keys"`
}

type AppKeyResponse struct {
WrappedKeyShare string `json:"wrapped_key_share"`
Apps []App `json:"apps"`
WrappedKeyShare string `json:"wrapped_key_share"`
Apps []App `json:"apps"`
}

type GetContextOptions struct {
Expand All @@ -69,4 +68,4 @@ type FindEnvironmentKeyOptions struct {
EnvName string
AppName string
AppID string
}
}
22 changes: 11 additions & 11 deletions phase/misc/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ func FindEnvironmentKey(userData AppKeyResponse, opts FindEnvironmentKeyOptions)
lcAppName := strings.ToLower(opts.AppName)

for _, app := range userData.Apps {
if (opts.AppID != "" && app.ID == opts.AppID) ||
(opts.AppName != "" && (opts.AppName == "" || strings.Contains(strings.ToLower(app.Name), lcAppName))) {
if (opts.AppID != "" && app.ID == opts.AppID) ||
(opts.AppName != "" && (opts.AppName == "" || strings.Contains(strings.ToLower(app.Name), lcAppName))) {
for _, envKey := range app.EnvironmentKeys {
if strings.Contains(strings.ToLower(envKey.Environment.Name), lcEnvName) {
return &envKey, nil
Expand All @@ -39,17 +39,17 @@ func FindEnvironmentKey(userData AppKeyResponse, opts FindEnvironmentKeyOptions)

// normalizeTag replaces underscores with spaces and converts the string to lower case.
func normalizeTag(tag string) string {
return strings.ToLower(strings.Replace(tag, "_", " ", -1))
return strings.ToLower(strings.Replace(tag, "_", " ", -1))
}

// tagMatches checks if the user-provided tag partially matches any of the secret tags.
func TagMatches(secretTags []string, userTag string) bool {
normalizedUserTag := normalizeTag(userTag)
for _, tag := range secretTags {
normalizedSecretTag := normalizeTag(tag)
if strings.Contains(normalizedSecretTag, normalizedUserTag) {
return true
}
}
return false
normalizedUserTag := normalizeTag(userTag)
for _, tag := range secretTags {
normalizedSecretTag := normalizeTag(tag)
if strings.Contains(normalizedSecretTag, normalizedUserTag) {
return true
}
}
return false
}
Loading