Skip to content

Commit

Permalink
feat(encrypter): Added an Encrypter. (#65)
Browse files Browse the repository at this point in the history
Signed-off-by: Flc゛ <[email protected]>
  • Loading branch information
flc1125 authored Jan 8, 2024
1 parent 80fd696 commit 30efabe
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
18 changes: 18 additions & 0 deletions encrypter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Encrypter

## Usage

```go
package main

import "github.com/go-kratos-ecosystem/components/v2/encrypter"

func main() {
e := encrypter.New("EAFBSPAXDCIOGRUVNERQGXPYGPNKYATM")

ciphertext, _ := e.Encrypt("test")
plaintext, _ := e.Decrypt(ciphertext)

println(ciphertext, plaintext) // I-UVz6tds3MlRX-1afR36cLcmMw= test
}
```
80 changes: 80 additions & 0 deletions encrypter/encrypter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package encrypter

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)

type Encrypter struct {
key []byte
cipher cipher.Block
}

func New(key string) *Encrypter {
return &Encrypter{
key: []byte(key),
}
}

func (e *Encrypter) Encrypt(value string) (string, error) {
plaintext := []byte(value)

block, err := e.getBlock()
if err != nil {
return "", err
}

ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}

stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

return base64.URLEncoding.EncodeToString(ciphertext), nil
}

func (e *Encrypter) Decrypt(value string) (string, error) {
ciphertext, err := base64.URLEncoding.DecodeString(value)
if err != nil {
return "", err
}

block, err := e.getBlock()
if err != nil {
return "", err
}

if len(ciphertext) < aes.BlockSize {
return "", fmt.Errorf("ciphertext too short")
}

iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]

stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)

return string(ciphertext), nil
}

func (e *Encrypter) getBlock() (cipher.Block, error) {
if e.cipher != nil {
return e.cipher, nil
}

c, err := aes.NewCipher(e.key)
if err != nil {
return nil, err
}

e.cipher = c

return c, nil
}
46 changes: 46 additions & 0 deletions encrypter/encrypter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package encrypter

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestNew(t *testing.T) {
assert.Equal(t, &Encrypter{
key: []byte("test"),
}, New("test"))
}

func TestEncrypter(t *testing.T) {
e := New("EAFBSPAXDCIOGRUVNERQGXPYGPNKYATM")

ciphertext, _ := e.Encrypt("test")
plaintext, _ := e.Decrypt(ciphertext)

println(ciphertext, plaintext)

assert.NotNil(t, ciphertext)
assert.NotNil(t, plaintext)
assert.Equal(t, "test", plaintext)
}

func TestEncrypter_Error(t *testing.T) {
e := New("test")

_, err1 := e.Encrypt("test")
assert.Error(t, err1)

_, err2 := e.Decrypt("test")
assert.Error(t, err2)
}

func TestEncrypter_Decrypt_Error(t *testing.T) {
e := New("EAFBSPAXDCIOGRUVNERQGXPYGPNKYATM")

_, err1 := e.Decrypt("j9_mcZXKVlInk8bbpBqJOpmDp")
assert.Error(t, err1)

_, err2 := e.Decrypt("MQ==")
assert.Error(t, err2)
}

0 comments on commit 30efabe

Please sign in to comment.