Skip to content

Commit 47c472a

Browse files
lafrikslunny
authored andcommitted
Add AES GCM encryption provider
1 parent 6b24ada commit 47c472a

File tree

5 files changed

+180
-4
lines changed

5 files changed

+180
-4
lines changed

cmd/generate.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,13 @@ func runGenerateMasterKey(c *cli.Context) error {
142142
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(secret))
143143
}
144144
}
145-
fmt.Println("Setting changes required:")
146-
fmt.Println("[secrets]")
145+
147146
if providerType == secrets.MasterKeyProviderTypePlain && len(scrts) == 1 {
148-
fmt.Printf("MASTER_KEY = %s\n", base64.StdEncoding.EncodeToString(scrts[0]))
147+
fmt.Printf("%s", base64.StdEncoding.EncodeToString(scrts[0]))
148+
149+
if isatty.IsTerminal(os.Stdout.Fd()) {
150+
fmt.Printf("\n")
151+
}
149152
}
150153

151154
return nil

services/secrets/encryption.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package secrets
6+
7+
// EncryptionProvider encrypts and decrypts secrets
8+
type EncryptionProvider interface {
9+
Encrypt(secret, key []byte) ([]byte, error)
10+
11+
EncryptString(secret string, key []byte) (string, error)
12+
13+
Decrypt(enc, key []byte) ([]byte, error)
14+
15+
DecryptString(enc string, key []byte) (string, error)
16+
}

services/secrets/encryption_aes.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package secrets
6+
7+
import (
8+
"crypto/aes"
9+
"crypto/cipher"
10+
"crypto/rand"
11+
"encoding/base64"
12+
"fmt"
13+
"io"
14+
)
15+
16+
type aesEncryptionProvider struct {
17+
}
18+
19+
func NewAesEncryptionProvider() EncryptionProvider {
20+
return &aesEncryptionProvider{}
21+
}
22+
23+
func (e *aesEncryptionProvider) Encrypt(secret, key []byte) ([]byte, error) {
24+
block, err := aes.NewCipher(key)
25+
if err != nil {
26+
return nil, err
27+
}
28+
29+
c, err := cipher.NewGCM(block)
30+
if err != nil {
31+
return nil, err
32+
}
33+
34+
nonce := make([]byte, c.NonceSize(), c.NonceSize()+c.Overhead()+len(secret))
35+
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
36+
return nil, err
37+
}
38+
out := c.Seal(nil, nonce, secret, nil)
39+
40+
return append(nonce, out...), nil
41+
}
42+
43+
func (e *aesEncryptionProvider) EncryptString(secret string, key []byte) (string, error) {
44+
out, err := e.Encrypt([]byte(secret), key)
45+
if err != nil {
46+
return "", err
47+
}
48+
return base64.StdEncoding.EncodeToString(out), nil
49+
}
50+
51+
func (e *aesEncryptionProvider) Decrypt(enc, key []byte) ([]byte, error) {
52+
block, err := aes.NewCipher(key)
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
c, err := cipher.NewGCM(block)
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
if len(enc) < c.NonceSize() {
63+
return nil, fmt.Errorf("encrypted value too short")
64+
}
65+
66+
nonce := enc[:c.NonceSize()]
67+
ciphertext := enc[c.NonceSize():]
68+
69+
out, err := c.Open(nil, nonce, ciphertext, nil)
70+
if err != nil {
71+
return nil, err
72+
}
73+
74+
return out, nil
75+
}
76+
77+
func (e *aesEncryptionProvider) DecryptString(enc string, key []byte) (string, error) {
78+
encb, err := base64.StdEncoding.DecodeString(enc)
79+
if err != nil {
80+
return "", err
81+
}
82+
83+
out, err := e.Encrypt(encb, key)
84+
if err != nil {
85+
return "", err
86+
}
87+
88+
return string(out), nil
89+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package secrets
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestNopMasterKey_IsSealed(t *testing.T) {
10+
k := NewNopMasterKeyProvider()
11+
assert.False(t, k.IsSealed())
12+
}

services/secrets/secrets.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const (
2020
)
2121

2222
var (
23-
masterKey MasterKeyProvider
23+
masterKey MasterKeyProvider
24+
encProvider EncryptionProvider
2425
)
2526

2627
// Init initializes master key provider based on settings
@@ -33,10 +34,65 @@ func Init() error {
3334
default:
3435
return fmt.Errorf("invalid master key provider %v", setting.MasterKeyProvider)
3536
}
37+
38+
encProvider = NewAesEncryptionProvider()
39+
3640
return nil
3741
}
3842

3943
// GenerateMasterKey generates a new master key and returns secret or secrets for unsealing
4044
func GenerateMasterKey() ([][]byte, error) {
4145
return masterKey.GenerateMasterKey()
4246
}
47+
48+
func Encrypt(secret []byte) ([]byte, error) {
49+
key, err := masterKey.GetMasterKey()
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
if len(key) == 0 {
55+
return secret, nil
56+
}
57+
58+
return encProvider.Encrypt(secret, key)
59+
}
60+
61+
func EncryptString(secret string) (string, error) {
62+
key, err := masterKey.GetMasterKey()
63+
if err != nil {
64+
return "", err
65+
}
66+
67+
if len(key) == 0 {
68+
return secret, nil
69+
}
70+
71+
return encProvider.EncryptString(secret, key)
72+
}
73+
74+
func Decrypt(enc []byte) ([]byte, error) {
75+
key, err := masterKey.GetMasterKey()
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
if len(key) == 0 {
81+
return enc, nil
82+
}
83+
84+
return encProvider.Decrypt(enc, key)
85+
}
86+
87+
func DecryptString(enc string) (string, error) {
88+
key, err := masterKey.GetMasterKey()
89+
if err != nil {
90+
return "", err
91+
}
92+
93+
if len(key) == 0 {
94+
return enc, nil
95+
}
96+
97+
return encProvider.DecryptString(enc, key)
98+
}

0 commit comments

Comments
 (0)