-
Notifications
You must be signed in to change notification settings - Fork 560
/
Copy pathcrypt.go
159 lines (136 loc) · 4.27 KB
/
crypt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package utils
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"github.com/diggerhq/digger/backend/models"
)
// Encrypt encrypts a plaintext string using AES-256-GCM
func AESEncrypt(key []byte, plaintext string) (string, error) {
// Create cipher block
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("failed to create cipher block: %v", err)
}
// Create GCM mode
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM: %v", err)
}
// Create nonce
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", fmt.Errorf("failed to create nonce: %v", err)
}
// Encrypt data
ciphertext := gcm.Seal(nonce, nonce, []byte(plaintext), nil)
// Return base64 encoded string
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
// Decrypt decrypts a base64 encoded ciphertext using AES-256-GCM
func AESDecrypt(key []byte, encodedCiphertext string) (string, error) {
// Decode base64 string
ciphertext, err := base64.StdEncoding.DecodeString(encodedCiphertext)
if err != nil {
return "", fmt.Errorf("failed to decode base64: %v", err)
}
// Create cipher block
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("failed to create cipher block: %v", err)
}
// Create GCM mode
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM: %v", err)
}
// Extract nonce size
nonceSize := gcm.NonceSize()
if len(ciphertext) < nonceSize {
return "", fmt.Errorf("ciphertext too short")
}
// Split nonce and ciphertext
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
// Decrypt data
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return "", fmt.Errorf("failed to decrypt: %v", err)
}
return string(plaintext), nil
}
// represents a decrypted record
type DecryptedVCSConnection struct {
GithubId int64
ClientID string
ClientSecret string
WebhookSecret string
PrivateKey string
PrivateKeyBase64 string
Org string
Name string
GithubAppUrl string
OrganisationID uint
BitbucketAccessToken string
BitbucketWebhookSecret string
}
func DecryptConnection(g *models.VCSConnection, key []byte) (*DecryptedVCSConnection, error) {
// Create decrypted version
decrypted := &DecryptedVCSConnection{
GithubId: g.GithubId,
ClientID: g.ClientID,
Org: g.Org,
Name: g.Name,
GithubAppUrl: g.GithubAppUrl,
OrganisationID: g.OrganisationID,
}
// Decrypt ClientSecret
if g.ClientSecretEncrypted != "" {
clientSecret, err := AESDecrypt(key, g.ClientSecretEncrypted)
if err != nil {
return nil, fmt.Errorf("failed to decrypt client secret: %w", err)
}
decrypted.ClientSecret = clientSecret
}
// Decrypt WebhookSecret
if g.WebhookSecretEncrypted != "" {
webhookSecret, err := AESDecrypt(key, g.WebhookSecretEncrypted)
if err != nil {
return nil, fmt.Errorf("failed to decrypt webhook secret: %w", err)
}
decrypted.WebhookSecret = webhookSecret
}
// Decrypt PrivateKey
if g.PrivateKeyEncrypted != "" {
privateKey, err := AESDecrypt(key, g.PrivateKeyEncrypted)
if err != nil {
return nil, fmt.Errorf("failed to decrypt private key: %w", err)
}
decrypted.PrivateKey = privateKey
}
// Decrypt PrivateKeyBase64
if g.PrivateKeyBase64Encrypted != "" {
privateKeyBase64, err := AESDecrypt(key, g.PrivateKeyBase64Encrypted)
if err != nil {
return nil, fmt.Errorf("failed to decrypt private key base64: %w", err)
}
decrypted.PrivateKeyBase64 = privateKeyBase64
}
if g.BitbucketAccessTokenEncrypted != "" {
bitbucketAccessToken, err := AESDecrypt(key, g.BitbucketAccessTokenEncrypted)
if err != nil {
return nil, fmt.Errorf("failed to decrypt private key base64: %w", err)
}
decrypted.BitbucketAccessToken = bitbucketAccessToken
}
if g.BitbucketWebhookSecretEncrypted != "" {
bitbucketWebhookSecret, err := AESDecrypt(key, g.BitbucketWebhookSecretEncrypted)
if err != nil {
return nil, fmt.Errorf("failed to decrypt private key base64: %w", err)
}
decrypted.BitbucketWebhookSecret = bitbucketWebhookSecret
}
return decrypted, nil
}