aboutsummaryrefslogtreecommitdiff
path: root/internal/cryptoutil
diff options
context:
space:
mode:
Diffstat (limited to 'internal/cryptoutil')
-rw-r--r--internal/cryptoutil/aes.go56
-rw-r--r--internal/cryptoutil/aes_test.go34
-rw-r--r--internal/cryptoutil/md5.go22
-rw-r--r--internal/cryptoutil/md5_test.go27
4 files changed, 139 insertions, 0 deletions
diff --git a/internal/cryptoutil/aes.go b/internal/cryptoutil/aes.go
new file mode 100644
index 00000000..ec037b64
--- /dev/null
+++ b/internal/cryptoutil/aes.go
@@ -0,0 +1,56 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package cryptoutil
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "errors"
+)
+
+// AESGCMEncrypt encrypts plaintext with the given key using AES in GCM mode.
+func AESGCMEncrypt(key, plaintext []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ nonce := make([]byte, gcm.NonceSize())
+ if _, err := rand.Read(nonce); err != nil {
+ return nil, err
+ }
+
+ ciphertext := gcm.Seal(nil, nonce, plaintext, nil)
+ return append(nonce, ciphertext...), nil
+}
+
+// AESGCMDecrypt decrypts ciphertext with the given key using AES in GCM mode.
+func AESGCMDecrypt(key, ciphertext []byte) ([]byte, error) {
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return nil, err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return nil, err
+ }
+
+ size := gcm.NonceSize()
+ if len(ciphertext)-size <= 0 {
+ return nil, errors.New("ciphertext is empty")
+ }
+
+ nonce := ciphertext[:size]
+ ciphertext = ciphertext[size:]
+
+ return gcm.Open(nil, nonce, ciphertext, nil)
+}
diff --git a/internal/cryptoutil/aes_test.go b/internal/cryptoutil/aes_test.go
new file mode 100644
index 00000000..0e34bcb0
--- /dev/null
+++ b/internal/cryptoutil/aes_test.go
@@ -0,0 +1,34 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package cryptoutil
+
+import (
+ "crypto/rand"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAESGCM(t *testing.T) {
+ key := make([]byte, 16) // AES-128
+ _, err := rand.Read(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ plaintext := []byte("this will be encrypted")
+
+ encrypted, err := AESGCMEncrypt(key, plaintext)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ decrypted, err := AESGCMDecrypt(key, encrypted)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ assert.Equal(t, plaintext, decrypted)
+}
diff --git a/internal/cryptoutil/md5.go b/internal/cryptoutil/md5.go
new file mode 100644
index 00000000..249f3ed5
--- /dev/null
+++ b/internal/cryptoutil/md5.go
@@ -0,0 +1,22 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package cryptoutil
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+)
+
+// MD5 encodes string to hexadecimal of MD5 checksum.
+func MD5(str string) string {
+ return hex.EncodeToString(MD5Bytes(str))
+}
+
+// MD5Bytes encodes string to MD5 checksum.
+func MD5Bytes(str string) []byte {
+ m := md5.New()
+ _, _ = m.Write([]byte(str))
+ return m.Sum(nil)
+}
diff --git a/internal/cryptoutil/md5_test.go b/internal/cryptoutil/md5_test.go
new file mode 100644
index 00000000..d3986a32
--- /dev/null
+++ b/internal/cryptoutil/md5_test.go
@@ -0,0 +1,27 @@
+// Copyright 2020 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package cryptoutil
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestMD5(t *testing.T) {
+ tests := []struct {
+ input string
+ output string
+ }{
+ {input: "", output: "d41d8cd98f00b204e9800998ecf8427e"},
+ {input: "The quick brown fox jumps over the lazy dog", output: "9e107d9d372bb6826bd81d3542a419d6"},
+ {input: "The quick brown fox jumps over the lazy dog.", output: "e4d909c290d0fb1ca068ffaddf22cbd0"},
+ }
+ for _, test := range tests {
+ t.Run(test.input, func(t *testing.T) {
+ assert.Equal(t, test.output, MD5(test.input))
+ })
+ }
+}