Skip to content

Commit

Permalink
优化cbc的逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
yumaojun03 committed Nov 30, 2024
1 parent fea8488 commit ca99f7e
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 87 deletions.
118 changes: 54 additions & 64 deletions crypto/cbc/cbc.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,75 @@
package cbc

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"errors"
"io"
)

func pkcs7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
func NewAESCBCCihper(key []byte) *AESCBCCihper {
return &AESCBCCihper{
key: key,
encode: DATA_ENCODE_TYPE_HEX,
}
}

func pkcs7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
type AESCBCCihper struct {
key []byte
encode DATA_ENCODE_TYPE
}

// aesCBCEncrypt aes加密,填充秘钥key的16位,24,32分别对应AES-128, AES-192, or AES-256.
func aesCBCEncrypt(rawData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
func (c *AESCBCCihper) EncryptToString(rawData []byte) (string, error) {
cipherData, err := c.Encrypt(rawData)
if err != nil {
return "", err
}
switch c.encode {
case DATA_ENCODE_TYPE_BASE64:
return base64.StdEncoding.EncodeToString(cipherData), nil
default:
return hex.EncodeToString(cipherData), nil
}
}

func (c *AESCBCCihper) DecryptFromString(cipherText string) (string, error) {
var (
cipherData []byte
err error
)
switch c.encode {
case DATA_ENCODE_TYPE_BASE64:
cipherData, err = base64.StdEncoding.DecodeString(cipherText)
default:
cipherData, err = hex.DecodeString(cipherText)
}
if err != nil {
return "", err
}

planData, err := c.Decrypt(cipherData)
if err != nil {
return "", err
}
return string(planData), nil
}

func (c *AESCBCCihper) EncryptFromString(rawString string) (string, error) {
return c.EncryptToString([]byte(rawString))
}

func (c *AESCBCCihper) Encrypt(rawData []byte) ([]byte, error) {
block, err := aes.NewCipher(c.key)
if err != nil {
return nil, err
}

//填充原文
blockSize := block.BlockSize()
rawData = pkcs7Padding(rawData, blockSize)
rawData = PKCS7Padding(rawData, blockSize)
//初始向量IV必须是唯一,但不需要保密
cipherText := make([]byte, blockSize+len(rawData))
//block大小 16
Expand All @@ -52,8 +89,8 @@ func aesCBCEncrypt(rawData, key []byte) ([]byte, error) {
return cipherText, nil
}

func aesCBCDecrypt(encryptData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
func (c *AESCBCCihper) Decrypt(encryptData []byte) ([]byte, error) {
block, err := aes.NewCipher(c.key)
if err != nil {
return nil, err
}
Expand All @@ -76,53 +113,6 @@ func aesCBCDecrypt(encryptData, key []byte) ([]byte, error) {
// CryptBlocks can work in-place if the two arguments are the same.
mode.CryptBlocks(encryptData, encryptData)
//解填充
encryptData = pkcs7UnPadding(encryptData)
encryptData = PKCS7Unpadding(encryptData)
return encryptData, nil
}

// 采用hmac进行2次hash, 取32位
func sha1Hash2(key []byte) []byte {
h := sha1.New()
h.Write(key)
hashData := h.Sum(nil)
keyBuffer := bytes.NewBuffer(hashData)

h.Reset()
h.Write(hashData)
keyBuffer.Write(h.Sum(nil))

return keyBuffer.Bytes()[:32]
}

// Encrypt aes cbc加密
func Encrypt(data, key []byte) ([]byte, error) {
return aesCBCEncrypt(data, sha1Hash2(key))
}

// Decrypt aes cbc解密
func Decrypt(data, key []byte) ([]byte, error) {
return aesCBCDecrypt(data, sha1Hash2(key))
}

// Encrypt aes cbc加密
func EncryptToString(plan string, key []byte) (string, error) {
data, err := aesCBCEncrypt([]byte(plan), sha1Hash2(key))
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(data), nil
}

// Decrypt aes cbc解密
func DecryptFromString(encrypt string, key []byte) (string, error) {
data, err := base64.StdEncoding.DecodeString(encrypt)
if err != nil {
return "", err
}

plan, err := aesCBCDecrypt(data, sha1Hash2(key))
if err != nil {
return "", err
}
return string(plan), nil
}
31 changes: 8 additions & 23 deletions crypto/cbc/cbc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,21 @@ import (
"github.com/infraboard/mcube/v2/crypto/cbc"
)

func TestAESCBC(t *testing.T) {
data := []byte("abcdefg")
key := []byte("123456")

should := require.New(t)

cipherData, err := cbc.Encrypt(data, key)
should.NoError(err)
t.Logf("cipher data: %s", cipherData)

rawData, err := cbc.Decrypt(cipherData, key)
should.NoError(err)
t.Logf("raw data: %s", rawData)

should.Equal(data, []byte(rawData))
}

func TestEncryptString(t *testing.T) {
data := "abcdefg"
key := []byte("123456")
var (
data = "abcdefg"
key = cbc.MustGenRandomKey(cbc.AES_KEY_LEN_32)
cipher = cbc.NewAESCBCCihper(key)
)

func TestAESCBC(t *testing.T) {
should := require.New(t)

cipherData, err := cbc.EncryptToString(data, key)
cipherData, err := cipher.EncryptFromString(data)
should.NoError(err)
t.Logf("cipher data: %s", cipherData)

rawData, err := cbc.DecryptFromString(cipherData, key)
rawData, err := cipher.DecryptFromString(cipherData)
should.NoError(err)
t.Logf("raw data: %s", rawData)

should.Equal(data, rawData)
}
8 changes: 8 additions & 0 deletions crypto/cbc/enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cbc

type DATA_ENCODE_TYPE int

const (
DATA_ENCODE_TYPE_HEX DATA_ENCODE_TYPE = iota
DATA_ENCODE_TYPE_BASE64
)
43 changes: 43 additions & 0 deletions crypto/cbc/key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cbc

import (
"bytes"
"crypto/rand"
"crypto/sha1"
)

// aesCBCEncrypt aes加密,填充秘钥key的16位,24,32分别对应AES-128, AES-192, or AES-256.
type AES_KEY_LEN int

const (
AES_KEY_LEN_16 AES_KEY_LEN = 16
AES_KEY_LEN_24 AES_KEY_LEN = 24
AES_KEY_LEN_32 AES_KEY_LEN = 32
)

// 采用hmac进行2次hash, 取32位, 这样对key没有长度要求
func GenKeyBySHA1Hash2(key string, keyLen AES_KEY_LEN) []byte {
h := sha1.New()
h.Write([]byte(key))
hashData := h.Sum(nil)
keyBuffer := bytes.NewBuffer(hashData)

h.Reset()
h.Write(hashData)
keyBuffer.Write(h.Sum(nil))
return keyBuffer.Bytes()[:keyLen]
}

func GenRandomKey(keyLen AES_KEY_LEN) ([]byte, error) {
key := make([]byte, keyLen)
if _, err := rand.Read(key); err != nil {
return nil, err
}

return key, nil
}

func MustGenRandomKey(keyLen AES_KEY_LEN) []byte {
v, _ := GenRandomKey(keyLen)
return v
}
17 changes: 17 additions & 0 deletions crypto/cbc/key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cbc_test

import (
"testing"

"github.com/infraboard/mcube/v2/crypto/cbc"
)

func TestGenKeyBySHA1Hash2(t *testing.T) {
aesCihperKey := cbc.GenKeyBySHA1Hash2("test", cbc.AES_KEY_LEN_32)
t.Log(aesCihperKey)
}

func TestMustGenRandomKey(t *testing.T) {
aesCihperKey := cbc.MustGenRandomKey(cbc.AES_KEY_LEN_32)
t.Log(aesCihperKey)
}
22 changes: 22 additions & 0 deletions crypto/cbc/padding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cbc

import "bytes"

// PKCS7 Padding 和 PKCS5 Padding 都是用于对称加密中填充数据的方式,但它们之间有一些细微的区别:
// 填充块大小:
// PKCS5:只适用于块大小为 8 字节的加密算法(如 DES)。它的填充方式是将填充字节的值设为填充的字节数。
// PKCS7:可以用于块大小为 1 到 255 字节的加密算法(如 AES,块大小为 16 字节)。它的填充方式与 PKCS#5 类似,但适用于更广泛的块大小。

// PKCS7Padding 对数据进行 PKCS#7 填充
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}

// PKCS7Unpadding 对数据进行 PKCS#7 去填充
func PKCS7Unpadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
21 changes: 21 additions & 0 deletions crypto/cbc/padding_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cbc_test

import (
"fmt"
"testing"

"github.com/infraboard/mcube/v2/crypto/cbc"
)

func TestPKCS7Padding(t *testing.T) {
data := []byte("Hello World!")
blockSize := 16 // PKCS#7 适用于 1 到 255 字节的块,这里以 16 字节为例

// 填充
paddedData := cbc.PKCS7Padding(data, blockSize)
fmt.Printf("Padded Data (PKCS#7): %x\n", paddedData)

// 去填充
unpaddedData := cbc.PKCS7Unpadding(paddedData)
fmt.Printf("Unpadded Data: %x, %s\n", unpaddedData, unpaddedData)
}
52 changes: 52 additions & 0 deletions docs/ioc/cron.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<mxfile host="65bd71144e">
<diagram id="BEsFAiTLR5EbDN4ZmuPq" name="第 1 页">
<mxGraphModel dx="1181" dy="657" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" value="app" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="70" y="180" width="170" height="100" as="geometry"/>
</mxCell>
<mxCell id="3" value="" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
<mxGeometry x="100" y="390" width="130" height="60" as="geometry"/>
</mxCell>
<mxCell id="4" value="app" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="80" y="190" width="170" height="100" as="geometry"/>
</mxCell>
<mxCell id="5" value="app&lt;br&gt;&lt;br&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="90" y="200" width="170" height="100" as="geometry"/>
</mxCell>
<mxCell id="7" value="" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
<mxGeometry x="610" y="420" width="130" height="60" as="geometry"/>
</mxCell>
<mxCell id="9" value="app" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="570" y="240" width="170" height="100" as="geometry"/>
</mxCell>
<mxCell id="10" value="app" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="580" y="250" width="170" height="100" as="geometry"/>
</mxCell>
<mxCell id="22" style="edgeStyle=orthogonalEdgeStyle;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="11" target="7">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="11" value="app&lt;br&gt;&lt;br&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="590" y="260" width="170" height="100" as="geometry"/>
</mxCell>
<mxCell id="16" value="cron" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="180" y="200" width="80" height="30" as="geometry"/>
</mxCell>
<mxCell id="20" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="17" target="19">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="17" value="cron" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="570" y="40" width="170" height="60" as="geometry"/>
</mxCell>
<mxCell id="21" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="19" target="9">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="19" value="gw" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="570" y="140" width="170" height="60" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
1 change: 1 addition & 0 deletions ioc/config/lock/lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func TryLockTest(number int, g *sync.WaitGroup) {
fmt.Println(number, err)
return
}
defer m.UnLock(ctx)
fmt.Println(number, "obtained lock")
}

Expand Down

0 comments on commit ca99f7e

Please sign in to comment.