Переглянути джерело

服务配置项支持加解密

zhou.xiaoning 1 рік тому
батько
коміт
a0b7934ad5
7 змінених файлів з 432 додано та 13 видалено
  1. 16 2
      busdriver/busdriver.go
  2. 28 2
      config/config.go
  3. 11 6
      config/config.xml
  4. 27 1
      db/mongodb.go
  5. 28 1
      db/mysqldb.go
  6. 306 0
      packet/mcrypto.go
  7. 16 1
      rediscli/rediscli.go

+ 16 - 2
busdriver/busdriver.go

@@ -2,9 +2,11 @@ package busdriver
 
 import (
 	"bytes"
+	"encoding/hex"
 	"errors"
 	"fmt"
 	"mtp2_if/config"
+	"mtp2_if/packet"
 	"time"
 
 	"github.com/streadway/amqp"
@@ -50,10 +52,22 @@ func (t *TestProc) process(topic string, queuename string, msg *string) {
 
 // MqConnect 连接到rabbitMQ
 func MqConnect() error {
-	url := config.SerCfg.MqCfg.Url
+	// 尝试解密
+	var url []byte
+	ciphertext, _ := hex.DecodeString(config.SerCfg.MqCfg.Url)
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		url, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if url == nil {
+			url = []byte(config.SerCfg.MqCfg.Url)
+		}
+	} else {
+		url = []byte(config.SerCfg.MqCfg.Url)
+	}
+
 	var err error
 	if MqChannel == nil || MqConn.IsClosed() {
-		MqConn, err = amqp.Dial(url)
+		MqConn, err = amqp.Dial(string(url))
 		if err != nil {
 			fmt.Printf("rabbitmq connect failed:%s\n", err)
 			return err

+ 28 - 2
config/config.go

@@ -1,8 +1,10 @@
 package config
 
 import (
+	"encoding/hex"
 	"errors"
 	"fmt"
+	"mtp2_if/packet"
 	"strconv"
 
 	"github.com/beevik/etree"
@@ -525,9 +527,33 @@ func (c *ServiceConfig) GetDbDriver() string {
 }
 
 func (c *ServiceConfig) GetDbSource() string {
+	// 尝试解密
+	var dbUser []byte
+	ciphertext, _ := hex.DecodeString(SerCfg.DbCfg.DbUser)
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbUser, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbUser == nil {
+			dbUser = []byte(SerCfg.DbCfg.DbUser)
+		}
+	} else {
+		dbUser = []byte(SerCfg.DbCfg.DbUser)
+	}
+	var dbPwd []byte
+	ciphertext, _ = hex.DecodeString(SerCfg.DbCfg.DbPwd)
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbPwd, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbPwd == nil {
+			dbPwd = []byte(SerCfg.DbCfg.DbPwd)
+		}
+	} else {
+		dbPwd = []byte(SerCfg.DbCfg.DbPwd)
+	}
+
 	dbsource := fmt.Sprintf("%s/%s@%s:%s/%s",
-		SerCfg.DbCfg.DbUser,
-		SerCfg.DbCfg.DbPwd,
+		string(dbUser),
+		string(dbPwd),
 		SerCfg.DbCfg.DbAddress,
 		SerCfg.DbCfg.DbPort,
 		SerCfg.DbCfg.DbName)

+ 11 - 6
config/config.xml

@@ -15,6 +15,7 @@
     <DbAddress value="192.168.31.88"/>
     <DbName value="orcl"/>
     <DbPort value="1521"/>
+    <!-- DbUser DbPwd 支持明文密文 -->
     <DbUser value="mtp2_test202"/>
     <DbPwd value="muchinfo"/>
   </DbSetting>
@@ -24,9 +25,11 @@
     <Timeout value="3"/>
     <ConnNum value="1"/>
     <DbNum value="0"/>
+    <!-- Pwd 支持明文密文 -->
     <Pwd value=""/>
   </RedisSetting>
   <MqSetting>
+    <!-- Url 支持明文密文 -->
     <Url value="amqp://guest:guest@192.168.31.202:5020/test"/>
     <Exchange value="entry"/>
   </MqSetting>
@@ -34,6 +37,7 @@
     <HostName value="192.168.31.202"/>
     <Port value="5025"/>
     <DBName value="HistoryQuote"/>
+    <!-- Username Password 支持明文密文 -->
     <Username value="quote_test01"/>
     <Password value="123456"/>
   </MongoDBSetting>
@@ -41,6 +45,7 @@
     <Host value="192.168.30.72"/>
     <Port value="3306"/>
     <DBName value="historyquote_test202"/>
+    <!-- Username Password 支持明文密文 -->
     <Username value="quote_test202"/>
     <Password value="123456"/>
   </MySQLSetting>
@@ -57,10 +62,10 @@
     <SignKey value="EB49C115EEDE44049F11495F6EA7526F"/>
   </Tencent>
   <Asign>
-  <Url value="https://prev.asign.cn"/>
-  <AppId value="896210645"/>
-  <PrivateKey value="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqmByEbXbqqq+FYxD1+mJzqrVxG/7xNF3iZJV9q0PqOVwWPEtND8nNuB2FeAwHc5+W7dZwXheVaQqWXvV6lnWp3KaQ9S4CbeOX7zKKF0j42JMj4Adknid9X6OlULZeVoXcQsdQ2h9xpfJhwLka4aOX5p1eP6WocXMrkAVRXEA8aNAlTUHBWhrbiJpKdL4KIDs6hwh0QqLbnt8i7t02wq6qubGW0hYvdY3MQL2GfbNoIZUbYezp5eCyHm/8cFT/WTt1sGSg4hD8JbUn0GTMcrh4rrQLmcJbjStNUOyjqouASTK1A2QQxSS5p2Y7AC4yut3MIqyr7ByAX9/85HtHrdX3AgMBAAECggEAFWRBnzGCyeZhYB6OD+o30j1Dx001aNWiODNYs4t4VrSeoYMqBh3Gtm8x9HybNYwAJRLp4ulJl8i2NSjvK1IWqxgqIt87x74z3ed2tO46jknKGaOMCcfzN7t4b9BxLd83pekRyUewzbV7cVqTW5WTyAZ5EUp14Wtof7vtjsg8ndZp1C0LzJrsQ63LWJAWsfkiRwNwbjkIKTl12xwe3ctZD/PmxYVgWGog+32OiiiTuSf4O1ddp3y2kth66dSIO06VPCqgu8gLwG5epgHmy0Y1ugunpZINN2D7FCH7aaE+H+aQ4nltNIxpQV20grtQG546oDilfPCQLxeW1HUipq2wkQKBgQDyqo180/lJ4wSNFU/hNqLfs2629vU9MH9aSjG5nQpchkTgBxUhAE5RkKgQHLJHJTfPx7vkx2xkI3qddwsWzvt8lNs5NQNxh+LyXQEgy9FCfpopijy2epLpzd2WT+0Y9WK5oB7O32s2YW/6fm0ahu3EJnvBlp1M23FzuRfrV7gu5QKBgQCz98MyV0UAnP3x+Gq5/0siVGPInzYlfTfYcEI3qhlMfqPVkRqqHdGGsiQL70YJlTlZkLeh3r2UvoR956nV9lZgh37aWnaHw7FAYcA5z4FYEFdmpLK/8znaKn/fxypr9xkJtw5V1QgCeaSUCFbt0xp41LaAvwSDBfFqdOTzQMFHqwKBgEyZN4YypxsClPovwwI1K95vFkCc3baN63VFvEJ55r5kB7OrqKi9HvuyLMrBNCku/1oQEyhZJsbJSDgSTqbJeSrPFhANwuOAYEveva9rhsd1jRYVs6pqMJuqxwpeeloJgztS5saoUYBd62nnpGreMolbGG94KnkLP9mmkH1SOCpdAoGAbheD3ljKilx/cLVxvIRy1vZe8EyNGBPoxMuvhlPVFBloae5RLH3/PfHd4TsnUhdqNOM1op0axlJhxI+iMpR2NKjOrg6m8diBpwvlRrgsvM2KWe0ouAm3e0GCZkd1KQTI2UuVRmaCdtkpF7GeU/BPAlnFpy6zON+61k/Z+wDC++8CgYEA54xmJqIr19BpKkcHAxE2pzDrj6ssu2qObKLfsS27o4RevBnrhoY9kPwn8kUKpngoCTd7tM42y9fcpAdUDv+lENAcIF/kz4u+zkyRGR+SpirgAsCYzxZN3GfRNDHBaFEiTkyL6NFdPGV2GTPcd0b6JGf82Thb0JJCxB/J3hVnDIs="/>
-  <NotifyUrl value="http://218.17.158.45:15105/api/Asign/HandleASignCompleted"/>
-  <OpenApiUrl value="http://192.168.31.202:5015/mtp2-onlineopen"/>
-</Asign>
+    <Url value="https://prev.asign.cn"/>
+    <AppId value="896210645"/>
+    <PrivateKey value="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCqmByEbXbqqq+FYxD1+mJzqrVxG/7xNF3iZJV9q0PqOVwWPEtND8nNuB2FeAwHc5+W7dZwXheVaQqWXvV6lnWp3KaQ9S4CbeOX7zKKF0j42JMj4Adknid9X6OlULZeVoXcQsdQ2h9xpfJhwLka4aOX5p1eP6WocXMrkAVRXEA8aNAlTUHBWhrbiJpKdL4KIDs6hwh0QqLbnt8i7t02wq6qubGW0hYvdY3MQL2GfbNoIZUbYezp5eCyHm/8cFT/WTt1sGSg4hD8JbUn0GTMcrh4rrQLmcJbjStNUOyjqouASTK1A2QQxSS5p2Y7AC4yut3MIqyr7ByAX9/85HtHrdX3AgMBAAECggEAFWRBnzGCyeZhYB6OD+o30j1Dx001aNWiODNYs4t4VrSeoYMqBh3Gtm8x9HybNYwAJRLp4ulJl8i2NSjvK1IWqxgqIt87x74z3ed2tO46jknKGaOMCcfzN7t4b9BxLd83pekRyUewzbV7cVqTW5WTyAZ5EUp14Wtof7vtjsg8ndZp1C0LzJrsQ63LWJAWsfkiRwNwbjkIKTl12xwe3ctZD/PmxYVgWGog+32OiiiTuSf4O1ddp3y2kth66dSIO06VPCqgu8gLwG5epgHmy0Y1ugunpZINN2D7FCH7aaE+H+aQ4nltNIxpQV20grtQG546oDilfPCQLxeW1HUipq2wkQKBgQDyqo180/lJ4wSNFU/hNqLfs2629vU9MH9aSjG5nQpchkTgBxUhAE5RkKgQHLJHJTfPx7vkx2xkI3qddwsWzvt8lNs5NQNxh+LyXQEgy9FCfpopijy2epLpzd2WT+0Y9WK5oB7O32s2YW/6fm0ahu3EJnvBlp1M23FzuRfrV7gu5QKBgQCz98MyV0UAnP3x+Gq5/0siVGPInzYlfTfYcEI3qhlMfqPVkRqqHdGGsiQL70YJlTlZkLeh3r2UvoR956nV9lZgh37aWnaHw7FAYcA5z4FYEFdmpLK/8znaKn/fxypr9xkJtw5V1QgCeaSUCFbt0xp41LaAvwSDBfFqdOTzQMFHqwKBgEyZN4YypxsClPovwwI1K95vFkCc3baN63VFvEJ55r5kB7OrqKi9HvuyLMrBNCku/1oQEyhZJsbJSDgSTqbJeSrPFhANwuOAYEveva9rhsd1jRYVs6pqMJuqxwpeeloJgztS5saoUYBd62nnpGreMolbGG94KnkLP9mmkH1SOCpdAoGAbheD3ljKilx/cLVxvIRy1vZe8EyNGBPoxMuvhlPVFBloae5RLH3/PfHd4TsnUhdqNOM1op0axlJhxI+iMpR2NKjOrg6m8diBpwvlRrgsvM2KWe0ouAm3e0GCZkd1KQTI2UuVRmaCdtkpF7GeU/BPAlnFpy6zON+61k/Z+wDC++8CgYEA54xmJqIr19BpKkcHAxE2pzDrj6ssu2qObKLfsS27o4RevBnrhoY9kPwn8kUKpngoCTd7tM42y9fcpAdUDv+lENAcIF/kz4u+zkyRGR+SpirgAsCYzxZN3GfRNDHBaFEiTkyL6NFdPGV2GTPcd0b6JGf82Thb0JJCxB/J3hVnDIs="/>
+    <NotifyUrl value="http://218.17.158.45:15105/api/Asign/HandleASignCompleted"/>
+    <OpenApiUrl value="http://192.168.31.202:5015/mtp2-onlineopen"/>
+  </Asign>
 </Configuration>

+ 27 - 1
db/mongodb.go

@@ -1,8 +1,10 @@
 package db
 
 import (
+	"encoding/hex"
 	"fmt"
 	"mtp2_if/config"
+	"mtp2_if/packet"
 
 	"gopkg.in/mgo.v2"
 )
@@ -22,8 +24,32 @@ func InitMongoDB() error {
 	// 选择DB
 	mongodb = session.DB(config.SerCfg.GetMongoDBDBName())
 
+	// 尝试解密
+	var dbUser []byte
+	ciphertext, _ := hex.DecodeString(config.SerCfg.GetMongoDBUsername())
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbUser, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbUser == nil {
+			dbUser = []byte(config.SerCfg.GetMongoDBUsername())
+		}
+	} else {
+		dbUser = []byte(config.SerCfg.GetMongoDBUsername())
+	}
+	var dbPwd []byte
+	ciphertext, _ = hex.DecodeString(config.SerCfg.GetMongoDBPassword())
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbPwd, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbPwd == nil {
+			dbPwd = []byte(config.SerCfg.GetMongoDBPassword())
+		}
+	} else {
+		dbPwd = []byte(config.SerCfg.GetMongoDBPassword())
+	}
+
 	// 登陆
-	if err := mongodb.Login(config.SerCfg.GetMongoDBUsername(), config.SerCfg.GetMongoDBPassword()); err != nil {
+	if err := mongodb.Login(string(dbUser), string(dbPwd)); err != nil {
 		return err
 	}
 

+ 28 - 1
db/mysqldb.go

@@ -1,9 +1,11 @@
 package db
 
 import (
+	"encoding/hex"
 	"fmt"
 	"mtp2_if/config"
 	"mtp2_if/logger"
+	"mtp2_if/packet"
 
 	"github.com/xormplus/core"
 	"github.com/xormplus/xorm"
@@ -20,7 +22,32 @@ func InitMySQLDbEngine() error {
 	dbname := config.SerCfg.GetMySQLDBName()
 	username := config.SerCfg.GetMySQLUsername()
 	password := config.SerCfg.GetMySQLPassword()
-	dataSourceName := fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8", username, password, host, port, dbname)
+
+	// 尝试解密
+	var dbUser []byte
+	ciphertext, _ := hex.DecodeString(username)
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbUser, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbUser == nil {
+			dbUser = []byte(username)
+		}
+	} else {
+		dbUser = []byte(username)
+	}
+	var dbPwd []byte
+	ciphertext, _ = hex.DecodeString(password)
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbPwd, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbPwd == nil {
+			dbPwd = []byte(password)
+		}
+	} else {
+		dbPwd = []byte(password)
+	}
+
+	dataSourceName := fmt.Sprintf("%s:%s@(%s:%d)/%s?charset=utf8", string(dbUser), string(dbPwd), host, port, dbname)
 
 	var err error
 	MySQLEngine, err = xorm.NewEngine("mysql", dataSourceName)

+ 306 - 0
packet/mcrypto.go

@@ -0,0 +1,306 @@
+package packet
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"encoding/binary"
+	"encoding/hex"
+	"errors"
+)
+
+const AESKey = "F7A72DE7D6264530F01BA49BC73EB873"
+const macKey = "B0FB83E39A5EBFAABE471362A58393FF"
+const macIV = "D951DBE037C82325"
+
+// FIXME: - 为减少内存操作,这里的[]byte应该使用*[]byte
+
+func Encrypt(plaintext []byte, keyHex string, isPacket50 bool) ([]byte, error) {
+	key := []byte(keyHex)
+
+	// 构建密文结构体: 4 byte 明文长度+密文+8 byte MAC检验码
+	result := []byte{}
+	// 明文长度
+	plaintextLen := len(plaintext)
+	plaintextLenData := make([]byte, 4) // 如果写为 []byte{},PutUint32时会报溢出
+	binary.LittleEndian.PutUint32(plaintextLenData, uint32(plaintextLen))
+	result = append(result, plaintextLenData...)
+	// mac校验目标
+	macPlainText := result[:]
+	macPlainText = append(macPlainText, []byte{0, 0, 0, 0}...)
+
+	// 对内容进行加密
+	if isPacket50 {
+		// 5.0 报文
+		ciphertext, err := aesEncrypt(plaintext, key)
+		// ciphertext, err := aesEncrypt(plaintext, key)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, ciphertext...)
+	} else {
+		// 4.0 报文
+
+	}
+
+	// MAC检验码
+	// 注意:由于服务端的错误(遇到\0就停止),原本需要把长度+密文生成校验码,现改由长度4 byte进行校验即可
+	macKeyData, _ := hex.DecodeString(macKey)
+	macIVData, _ := hex.DecodeString(macIV)
+	macData, err := macAnsi(macPlainText, macKeyData, macIVData)
+	if err != nil {
+		return nil, err
+	}
+	result = append(result, macData...)
+
+	return result, nil
+}
+
+func Decrypt(ciphertext []byte, keyHex string, isPacket50 bool) ([]byte, error) {
+	key := []byte(keyHex)
+
+	// 对内容进行加密
+	if isPacket50 {
+		return aesDecrypt(ciphertext, key)
+	} else {
+		return nil, nil
+	}
+}
+
+func aesEncrypt(plaintext, key []byte) ([]byte, error) {
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, errors.New("错误的数据或密钥")
+	}
+	ecb := NewECBEncrypter(block)
+	content := plaintext[:]
+	content = PKCS5Padding(content, block.BlockSize())
+	crypted := make([]byte, len(content))
+	ecb.CryptBlocks(crypted, content)
+
+	return crypted, nil
+}
+
+func aesDecrypt(crypted, key []byte) ([]byte, error) {
+	var err error
+
+	defer func() {
+		if err := recover(); err != nil {
+			return
+		}
+	}()
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+	blockMode := NewECBDecrypter(block)
+	origData := make([]byte, len(crypted))
+	blockMode.CryptBlocks(origData, crypted)
+	origData = PKCS5UnPadding(origData)
+
+	return origData, err
+}
+
+// Des加密
+func desEncrypt(plaintext []byte, key []byte) ([]byte, error) {
+	if len(plaintext) < 1 || len(key) < 1 {
+		return nil, errors.New("错误的数据或密钥")
+	}
+	block, err := des.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	blockSize := block.BlockSize()
+	origData := PKCS5Padding(plaintext, blockSize)
+	out := make([]byte, len(origData))
+	dst := out
+
+	// for len(origData) > 0 {
+	// 	block.Encrypt(dst, origData[:blockSize])
+	// 	origData = origData[blockSize:]
+	// 	dst = dst[blockSize:]
+	// }
+
+	// return out, nil
+
+	block.Encrypt(dst, origData[:blockSize])
+	origData = origData[blockSize:]
+	dst = dst[blockSize:]
+
+	return out[0:8], nil
+}
+
+// Des解密
+func desDecrypt(plaintext []byte, key []byte) ([]byte, error) {
+	if len(plaintext) < 1 || len(key) < 1 {
+		return nil, errors.New("wrong data or key")
+	}
+	block, err := des.NewCipher(key)
+	if err != nil {
+		return nil, err
+	}
+
+	blockSize := block.BlockSize()
+	origData := PKCS5Padding(plaintext, blockSize)
+	out := make([]byte, len(origData))
+	dst := out
+
+	// for len(origData) > 0 {
+	// 	block.Decrypt(dst, origData[:blockSize])
+	// 	origData = origData[blockSize:]
+	// 	dst = dst[blockSize:]
+	// }
+
+	// return out, nil
+
+	block.Decrypt(dst, origData[:blockSize])
+	origData = origData[blockSize:]
+	dst = dst[blockSize:]
+
+	return out[0:8], nil
+}
+
+func macAnsiX99(plainText []byte, key []byte, iv []byte) ([]byte, error) {
+	if len(plainText)%8 != 0 {
+		return nil, errors.New("目标数据长度必须为8的整数倍")
+	}
+	if len(key) != 8 {
+		return nil, errors.New("密钥位数不正确")
+	}
+	if len(iv) != 8 {
+		return nil, errors.New("向量位数不正确")
+	}
+
+	macData := iv[:]
+	xorData := make([]byte, 8)
+	for i := 0; i < len(plainText); i += 8 {
+		// 以8 byte为单位进行异或运算
+		for j := 0; j < 8; j++ {
+			xorData[j] = macData[j] ^ plainText[i+j]
+		}
+
+		// 异或结果的 8 byte 数据进行一次DES加密
+		desData, err := desEncrypt(xorData, key)
+		if err != nil {
+			return nil, err
+		}
+		macData = desData[:]
+	}
+
+	return macData, nil
+}
+
+func macAnsiX919(plainText []byte, key []byte, iv []byte) ([]byte, error) {
+	if len(plainText)%8 != 0 {
+		return nil, errors.New("目标数据长度必须为8的整数倍")
+	}
+	if len(key) != 16 {
+		return nil, errors.New("密钥位数不正确")
+	}
+	if len(iv) != 8 {
+		return nil, errors.New("向量位数不正确")
+	}
+
+	// 分解密钥
+	keyLeft := key[0:8]
+	keyRight := key[8:16]
+
+	// MAC(L)->R解密->L加密
+	dataLeft, err := macAnsiX99(plainText, keyLeft, iv)
+	if err != nil {
+		return nil, err
+	}
+	dataRight, err := desDecrypt(dataLeft, keyRight)
+	if err != nil {
+		return nil, err
+	}
+	return desEncrypt(dataRight, keyLeft)
+}
+
+func macAnsi(plainText []byte, key []byte, iv []byte) ([]byte, error) {
+	keyLen := len(key)
+	if keyLen == 8 {
+		return macAnsiX99(plainText, key, iv)
+	} else if keyLen == 16 {
+		return macAnsiX919(plainText, key, iv)
+	} else {
+		return nil, errors.New("密钥位数不正确")
+	}
+}
+
+// ECB PKCS5Padding
+func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
+	padding := blockSize - len(ciphertext)%blockSize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+// ECB PKCS5Unpadding
+func PKCS5UnPadding(origData []byte) []byte {
+	length := len(origData)
+	// 去掉最后一个字节 unpadding 次
+	unpadding := int(origData[length-1])
+	if unpadding > unpadding {
+		return []byte{}
+	}
+	return origData[:(length - unpadding)]
+}
+
+type ecb struct {
+	b         cipher.Block
+	blockSize int
+}
+
+func newECB(b cipher.Block) *ecb {
+	return &ecb{
+		b:         b,
+		blockSize: b.BlockSize(),
+	}
+}
+
+type ecbEncrypter ecb
+
+// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
+// mode, using the given Block.
+func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
+	return (*ecbEncrypter)(newECB(b))
+}
+func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
+func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	for len(src) > 0 {
+		x.b.Encrypt(dst, src[:x.blockSize])
+		src = src[x.blockSize:]
+		dst = dst[x.blockSize:]
+	}
+}
+
+type ecbDecrypter ecb
+
+// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
+// mode, using the given Block.
+func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
+	return (*ecbDecrypter)(newECB(b))
+}
+func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
+func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("crypto/cipher: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("crypto/cipher: output smaller than input")
+	}
+	for len(src) > 0 {
+		x.b.Decrypt(dst, src[:x.blockSize])
+		src = src[x.blockSize:]
+		dst = dst[x.blockSize:]
+	}
+}

+ 16 - 1
rediscli/rediscli.go

@@ -1,9 +1,11 @@
 package rediscli
 
 import (
+	"encoding/hex"
 	"fmt"
 
 	"mtp2_if/config"
+	"mtp2_if/packet"
 
 	"github.com/go-redis/redis"
 )
@@ -11,9 +13,22 @@ import (
 var RedisCli *redis.Client
 
 func InitRedisCli() error {
+	// 尝试解密
+	var dbPwd []byte
+	ciphertext, _ := hex.DecodeString(config.SerCfg.GetRedisPwd())
+	if len(ciphertext) > 8 {
+		ciphertext = ciphertext[4 : len(ciphertext)-8]
+		dbPwd, _ = packet.Decrypt(ciphertext, packet.AESKey, true)
+		if dbPwd == nil {
+			dbPwd = []byte(config.SerCfg.GetRedisPwd())
+		}
+	} else {
+		dbPwd = []byte(config.SerCfg.GetRedisPwd())
+	}
+
 	RedisCli = redis.NewClient(&redis.Options{
 		Addr:     config.SerCfg.GetRedisAddress(),
-		Password: config.SerCfg.GetRedisPwd(),
+		Password: string(dbPwd),
 		DB:       config.SerCfg.GetRedisDbNum(),
 		PoolSize: config.SerCfg.GetRedisConnNum(),
 	})