feat(db): 添加对达梦数据库的支持
- 在应用程序中新增对达梦数据库(DM)的配置和连接支持 - 实现 SetDmDB 函数以配置达梦数据库连接 - 更新数据库操作逻辑,支持达梦特有的 SQL 语法和功能 - 在相关文件中添加达梦数据库的处理逻辑,包括表创建、数据插入和查询 - 更新 go.mod 和 go.sum 文件以引入达梦数据库驱动 - 增强文档,详细说明达梦数据库的配置和使用方法
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
// This is a mirror of golang.org/x/crypto/internal/subtle.
|
||||
package security
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// AnyOverlap reports whether x and y share memory at any (not necessarily
|
||||
// corresponding) index. The memory beyond the slice length is ignored.
|
||||
func AnyOverlap(x, y []byte) bool {
|
||||
return len(x) > 0 && len(y) > 0 &&
|
||||
uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
|
||||
uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
|
||||
}
|
||||
|
||||
// InexactOverlap reports whether x and y share memory at any non-corresponding
|
||||
// index. The memory beyond the slice length is ignored. Note that x and y can
|
||||
// have different lengths and still not have any inexact overlap.
|
||||
//
|
||||
// InexactOverlap can be used to implement the requirements of the crypto/cipher
|
||||
// AEAD, Block, BlockMode and Stream interfaces.
|
||||
func InexactOverlap(x, y []byte) bool {
|
||||
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
|
||||
return false
|
||||
}
|
||||
return AnyOverlap(x, y)
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
type Cipher interface {
|
||||
Encrypt(plaintext []byte, genDigest bool) []byte
|
||||
Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error)
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type dhGroup struct {
|
||||
p *big.Int
|
||||
g *big.Int
|
||||
}
|
||||
|
||||
func newDhGroup(prime, generator *big.Int) *dhGroup {
|
||||
return &dhGroup{
|
||||
p: prime,
|
||||
g: generator,
|
||||
}
|
||||
}
|
||||
|
||||
func (dg *dhGroup) P() *big.Int {
|
||||
p := new(big.Int)
|
||||
p.Set(dg.p)
|
||||
return p
|
||||
}
|
||||
|
||||
func (dg *dhGroup) G() *big.Int {
|
||||
g := new(big.Int)
|
||||
g.Set(dg.g)
|
||||
return g
|
||||
}
|
||||
|
||||
// 生成本地公私钥
|
||||
func (dg *dhGroup) GeneratePrivateKey(randReader io.Reader) (key *DhKey, err error) {
|
||||
if randReader == nil {
|
||||
randReader = rand.Reader
|
||||
}
|
||||
// 0 < x < p
|
||||
x, err := rand.Int(randReader, dg.p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
zero := big.NewInt(0)
|
||||
for x.Cmp(zero) == 0 {
|
||||
x, err = rand.Int(randReader, dg.p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
key = new(DhKey)
|
||||
key.x = x
|
||||
|
||||
// y = g ^ x mod p
|
||||
key.y = new(big.Int).Exp(dg.g, x, dg.p)
|
||||
key.group = dg
|
||||
return
|
||||
}
|
||||
|
||||
func (dg *dhGroup) ComputeKey(pubkey *DhKey, privkey *DhKey) (kye *DhKey, err error) {
|
||||
if dg.p == nil {
|
||||
err = errors.New("DH: invalid group")
|
||||
return
|
||||
}
|
||||
if pubkey.y == nil {
|
||||
err = errors.New("DH: invalid public key")
|
||||
return
|
||||
}
|
||||
if pubkey.y.Sign() <= 0 || pubkey.y.Cmp(dg.p) >= 0 {
|
||||
err = errors.New("DH parameter out of bounds")
|
||||
return
|
||||
}
|
||||
if privkey.x == nil {
|
||||
err = errors.New("DH: invalid private key")
|
||||
return
|
||||
}
|
||||
k := new(big.Int).Exp(pubkey.y, privkey.x, dg.p)
|
||||
key := new(DhKey)
|
||||
key.y = k
|
||||
key.group = dg
|
||||
return
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import "math/big"
|
||||
|
||||
type DhKey struct {
|
||||
x *big.Int
|
||||
y *big.Int
|
||||
group *dhGroup
|
||||
}
|
||||
|
||||
func newPublicKey(s []byte) *DhKey {
|
||||
key := new(DhKey)
|
||||
key.y = new(big.Int).SetBytes(s)
|
||||
return key
|
||||
}
|
||||
|
||||
func (dk *DhKey) GetX() *big.Int {
|
||||
x := new(big.Int)
|
||||
x.Set(dk.x)
|
||||
return x
|
||||
}
|
||||
|
||||
func (dk *DhKey) GetY() *big.Int {
|
||||
y := new(big.Int)
|
||||
y.Set(dk.y)
|
||||
return y
|
||||
}
|
||||
|
||||
func (dk *DhKey) GetYBytes() []byte {
|
||||
if dk.y == nil {
|
||||
return nil
|
||||
}
|
||||
if dk.group != nil {
|
||||
blen := (dk.group.p.BitLen() + 7) / 8
|
||||
ret := make([]byte, blen)
|
||||
copyWithLeftPad(ret, dk.y.Bytes())
|
||||
return ret
|
||||
}
|
||||
return dk.y.Bytes()
|
||||
}
|
||||
|
||||
func (dk *DhKey) GetYString() string {
|
||||
if dk.y == nil {
|
||||
return ""
|
||||
}
|
||||
return dk.y.String()
|
||||
}
|
||||
|
||||
func (dk *DhKey) IsPrivateKey() bool {
|
||||
return dk.x != nil
|
||||
}
|
||||
|
||||
func copyWithLeftPad(dest, src []byte) {
|
||||
numPaddingBytes := len(dest) - len(src)
|
||||
for i := 0; i < numPaddingBytes; i++ {
|
||||
dest[i] = 0
|
||||
}
|
||||
copy(dest[:numPaddingBytes], src)
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
// go官方没有实现ecb加密模式
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
)
|
||||
|
||||
type ecb struct {
|
||||
b cipher.Block
|
||||
blockSize int
|
||||
}
|
||||
|
||||
func newECB(b cipher.Block) *ecb {
|
||||
return &ecb{
|
||||
b: b,
|
||||
blockSize: b.BlockSize(),
|
||||
}
|
||||
}
|
||||
|
||||
type ecbEncrypter ecb
|
||||
|
||||
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("dm/security: input not full blocks")
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("dm/security: output smaller than input")
|
||||
}
|
||||
if InexactOverlap(dst[:len(src)], src) {
|
||||
panic("dm/security: invalid buffer overlap")
|
||||
}
|
||||
for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs+x.blockSize, be+x.blockSize {
|
||||
x.b.Encrypt(dst[bs:be], src[bs:be])
|
||||
}
|
||||
}
|
||||
|
||||
type ecbDecrypter ecb
|
||||
|
||||
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("dm/security: input not full blocks")
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("dm/security: output smaller than input")
|
||||
}
|
||||
if InexactOverlap(dst[:len(src)], src) {
|
||||
panic("dm/security: invalid buffer overlap")
|
||||
}
|
||||
for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs+x.blockSize, be+x.blockSize {
|
||||
x.b.Decrypt(dst[bs:be], src[bs:be])
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const (
|
||||
DH_KEY_LENGTH int = 64
|
||||
/* 低7位用于保存分组加密算法中的工作模式 */
|
||||
WORK_MODE_MASK int = 0x007f
|
||||
ECB_MODE int = 0x1
|
||||
CBC_MODE int = 0x2
|
||||
CFB_MODE int = 0x4
|
||||
OFB_MODE int = 0x8
|
||||
/* 高位保存加密算法 */
|
||||
ALGO_MASK int = 0xff80
|
||||
DES int = 0x0080
|
||||
DES3 int = 0x0100
|
||||
AES128 int = 0x0200
|
||||
AES192 int = 0x0400
|
||||
AES256 int = 0x0800
|
||||
RC4 int = 0x1000
|
||||
MD5 int = 0x1100
|
||||
|
||||
// 用户名密码加密算法
|
||||
DES_CFB int = 132
|
||||
// 消息加密摘要长度
|
||||
MD5_DIGEST_SIZE int = 16
|
||||
|
||||
MIN_EXTERNAL_CIPHER_ID int = 5000
|
||||
)
|
||||
|
||||
var dhParaP = "C009D877BAF5FAF416B7F778E6115DCB90D65217DCC2F08A9DFCB5A192C593EBAB02929266B8DBFC2021039FDBD4B7FDE2B996E00008F57AE6EFB4ED3F17B6D3"
|
||||
var dhParaG = "5"
|
||||
var defaultIV = []byte{0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
|
||||
0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
|
||||
0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x20}
|
||||
var p *big.Int
|
||||
var g *big.Int
|
||||
|
||||
func NewClientKeyPair() (key *DhKey, err error) {
|
||||
p, _ = new(big.Int).SetString(dhParaP, 16)
|
||||
g, _ = new(big.Int).SetString(dhParaG, 16)
|
||||
dhGroup := newDhGroup(p, g)
|
||||
key, err = dhGroup.GeneratePrivateKey(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func ComputeSessionKey(clientPrivKey *DhKey, serverPubKey []byte) []byte {
|
||||
serverKeyX := bytes2Bn(serverPubKey)
|
||||
clientPrivKeyX := clientPrivKey.GetX()
|
||||
sessionKeyBN := serverKeyX.Exp(serverKeyX, clientPrivKeyX, p)
|
||||
return Bn2Bytes(sessionKeyBN, 0)
|
||||
}
|
||||
|
||||
func bytes2Bn(bnBytesSrc []byte) *big.Int {
|
||||
if bnBytesSrc == nil {
|
||||
return nil
|
||||
}
|
||||
if bnBytesSrc[0] == 0 {
|
||||
return new(big.Int).SetBytes(bnBytesSrc)
|
||||
}
|
||||
validBytesCount := len(bnBytesSrc) + 1
|
||||
bnBytesTo := make([]byte, validBytesCount)
|
||||
bnBytesTo[0] = 0
|
||||
copy(bnBytesTo[1:validBytesCount], bnBytesSrc)
|
||||
return new(big.Int).SetBytes(bnBytesTo)
|
||||
}
|
||||
|
||||
func Bn2Bytes(bn *big.Int, bnLen int) []byte {
|
||||
var bnBytesSrc, bnBytesTemp, bnBytesTo []byte
|
||||
var leading_zero_count int
|
||||
validBytesCount := 0
|
||||
if bn == nil {
|
||||
return nil
|
||||
}
|
||||
bnBytesSrc = bn.Bytes()
|
||||
|
||||
// 去除首位0
|
||||
if bnBytesSrc[0] != 0 {
|
||||
bnBytesTemp = bnBytesSrc
|
||||
validBytesCount = len(bnBytesTemp)
|
||||
} else {
|
||||
validBytesCount = len(bnBytesSrc) - 1
|
||||
bnBytesTemp = make([]byte, validBytesCount)
|
||||
copy(bnBytesTemp, bnBytesSrc[1:validBytesCount+1])
|
||||
}
|
||||
|
||||
if bnLen == 0 {
|
||||
leading_zero_count = 0
|
||||
} else {
|
||||
leading_zero_count = bnLen - validBytesCount
|
||||
}
|
||||
// 如果位数不足DH_KEY_LENGTH则在前面补0
|
||||
if leading_zero_count > 0 {
|
||||
bnBytesTo = make([]byte, DH_KEY_LENGTH)
|
||||
i := 0
|
||||
for i = 0; i < leading_zero_count; i++ {
|
||||
bnBytesTo[i] = 0
|
||||
}
|
||||
copy(bnBytesTo[i:i+validBytesCount], bnBytesTemp)
|
||||
} else {
|
||||
bnBytesTo = bnBytesTemp
|
||||
}
|
||||
return bnBytesTo
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/md5"
|
||||
"crypto/rc4"
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type SymmCipher struct {
|
||||
encryptCipher interface{} //cipher.BlockMode | cipher.Stream
|
||||
decryptCipher interface{} //cipher.BlockMode | cipher.Stream
|
||||
key []byte
|
||||
block cipher.Block // 分组加密算法
|
||||
algorithmType int
|
||||
workMode int
|
||||
needPadding bool
|
||||
}
|
||||
|
||||
func NewSymmCipher(algorithmID int, key []byte) (SymmCipher, error) {
|
||||
var sc SymmCipher
|
||||
var err error
|
||||
sc.key = key
|
||||
sc.algorithmType = algorithmID & ALGO_MASK
|
||||
sc.workMode = algorithmID & WORK_MODE_MASK
|
||||
switch sc.algorithmType {
|
||||
case AES128:
|
||||
if sc.block, err = aes.NewCipher(key[:16]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
case AES192:
|
||||
if sc.block, err = aes.NewCipher(key[:24]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
case AES256:
|
||||
if sc.block, err = aes.NewCipher(key[:32]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
case DES:
|
||||
if sc.block, err = des.NewCipher(key[:8]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
case DES3:
|
||||
var tripleDESKey []byte
|
||||
tripleDESKey = append(tripleDESKey, key[:16]...)
|
||||
tripleDESKey = append(tripleDESKey, key[:8]...)
|
||||
if sc.block, err = des.NewTripleDESCipher(tripleDESKey); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
case RC4:
|
||||
if sc.encryptCipher, err = rc4.NewCipher(key[:16]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
if sc.decryptCipher, err = rc4.NewCipher(key[:16]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
return sc, nil
|
||||
default:
|
||||
return sc, errors.New("invalidCipher")
|
||||
}
|
||||
blockSize := sc.block.BlockSize()
|
||||
if sc.encryptCipher, err = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
if sc.decryptCipher, err = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil {
|
||||
return sc, err
|
||||
}
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
func (sc SymmCipher) Encrypt(plaintext []byte, genDigest bool) []byte {
|
||||
// 执行过加密后,IV值变了,需要重新初始化encryptCipher对象(因为没有类似resetIV的方法)
|
||||
if sc.algorithmType != RC4 {
|
||||
sc.encryptCipher, _ = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()])
|
||||
} else {
|
||||
sc.encryptCipher, _ = rc4.NewCipher(sc.key[:16])
|
||||
}
|
||||
// 填充
|
||||
var paddingtext = make([]byte, len(plaintext))
|
||||
copy(paddingtext, plaintext)
|
||||
if sc.needPadding {
|
||||
paddingtext = pkcs5Padding(paddingtext)
|
||||
}
|
||||
|
||||
ret := make([]byte, len(paddingtext))
|
||||
|
||||
if v, ok := sc.encryptCipher.(cipher.Stream); ok {
|
||||
v.XORKeyStream(ret, paddingtext)
|
||||
} else if v, ok := sc.encryptCipher.(cipher.BlockMode); ok {
|
||||
v.CryptBlocks(ret, paddingtext)
|
||||
}
|
||||
|
||||
// md5摘要
|
||||
if genDigest {
|
||||
digest := md5.Sum(plaintext)
|
||||
encrypt := ret
|
||||
ret = make([]byte, len(encrypt)+len(digest))
|
||||
copy(ret[:len(encrypt)], encrypt)
|
||||
copy(ret[len(encrypt):], digest[:])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (sc SymmCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) {
|
||||
// 执行过解密后,IV值变了,需要重新初始化decryptCipher对象(因为没有类似resetIV的方法)
|
||||
if sc.algorithmType != RC4 {
|
||||
sc.decryptCipher, _ = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()])
|
||||
} else {
|
||||
sc.decryptCipher, _ = rc4.NewCipher(sc.key[:16])
|
||||
}
|
||||
var ret []byte
|
||||
if checkDigest {
|
||||
var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:]
|
||||
ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE]
|
||||
ret = sc.decrypt(ret)
|
||||
var msgDigest = md5.Sum(ret)
|
||||
if !reflect.DeepEqual(msgDigest[:], digest) {
|
||||
return nil, errors.New("Decrypt failed/Digest not match\n")
|
||||
}
|
||||
} else {
|
||||
ret = sc.decrypt(ciphertext)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (sc SymmCipher) decrypt(ciphertext []byte) []byte {
|
||||
ret := make([]byte, len(ciphertext))
|
||||
if v, ok := sc.decryptCipher.(cipher.Stream); ok {
|
||||
v.XORKeyStream(ret, ciphertext)
|
||||
} else if v, ok := sc.decryptCipher.(cipher.BlockMode); ok {
|
||||
v.CryptBlocks(ret, ciphertext)
|
||||
}
|
||||
// 去除填充
|
||||
if sc.needPadding {
|
||||
ret = pkcs5UnPadding(ret)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (sc *SymmCipher) getEncrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) {
|
||||
switch workMode {
|
||||
case ECB_MODE:
|
||||
ret = NewECBEncrypter(block)
|
||||
sc.needPadding = true
|
||||
case CBC_MODE:
|
||||
ret = cipher.NewCBCEncrypter(block, iv)
|
||||
sc.needPadding = true
|
||||
case CFB_MODE:
|
||||
ret = cipher.NewCFBEncrypter(block, iv)
|
||||
sc.needPadding = false
|
||||
case OFB_MODE:
|
||||
ret = cipher.NewOFB(block, iv)
|
||||
sc.needPadding = false
|
||||
default:
|
||||
err = errors.New("invalidCipherMode")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sc *SymmCipher) getDecrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) {
|
||||
switch workMode {
|
||||
case ECB_MODE:
|
||||
ret = NewECBDecrypter(block)
|
||||
sc.needPadding = true
|
||||
case CBC_MODE:
|
||||
ret = cipher.NewCBCDecrypter(block, iv)
|
||||
sc.needPadding = true
|
||||
case CFB_MODE:
|
||||
ret = cipher.NewCFBDecrypter(block, iv)
|
||||
sc.needPadding = false
|
||||
case OFB_MODE:
|
||||
ret = cipher.NewOFB(block, iv)
|
||||
sc.needPadding = false
|
||||
default:
|
||||
err = errors.New("invalidCipherMode")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 补码
|
||||
func pkcs77Padding(ciphertext []byte, blocksize int) []byte {
|
||||
padding := blocksize - len(ciphertext)%blocksize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
// 去码
|
||||
func pkcs7UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:length-unpadding]
|
||||
}
|
||||
|
||||
// 补码
|
||||
func pkcs5Padding(ciphertext []byte) []byte {
|
||||
return pkcs77Padding(ciphertext, 8)
|
||||
}
|
||||
|
||||
// 去码
|
||||
func pkcs5UnPadding(ciphertext []byte) []byte {
|
||||
return pkcs7UnPadding(ciphertext)
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type ThirdPartCipher struct {
|
||||
encryptType int // 外部加密算法id
|
||||
encryptName string // 外部加密算法名称
|
||||
hashType int
|
||||
key []byte
|
||||
cipherCount int // 外部加密算法个数
|
||||
//innerId int // 外部加密算法内部id
|
||||
blockSize int // 分组块大小
|
||||
khSize int // key/hash大小
|
||||
}
|
||||
|
||||
func NewThirdPartCipher(encryptType int, key []byte, cipherPath string, hashType int) (ThirdPartCipher, error) {
|
||||
var tpc = ThirdPartCipher{
|
||||
encryptType: encryptType,
|
||||
key: key,
|
||||
hashType: hashType,
|
||||
cipherCount: -1,
|
||||
}
|
||||
var err error
|
||||
err = initThirdPartCipher(cipherPath)
|
||||
if err != nil {
|
||||
return tpc, err
|
||||
}
|
||||
tpc.getCount()
|
||||
if err = tpc.getInfo(); err != nil {
|
||||
return tpc, err
|
||||
}
|
||||
return tpc, nil
|
||||
}
|
||||
|
||||
func (tpc *ThirdPartCipher) getCount() int {
|
||||
if tpc.cipherCount == -1 {
|
||||
tpc.cipherCount = cipherGetCount()
|
||||
}
|
||||
return tpc.cipherCount
|
||||
}
|
||||
|
||||
func (tpc *ThirdPartCipher) getInfo() error {
|
||||
var cipher_id, ty, blk_size, kh_size int
|
||||
//var strptr, _ = syscall.UTF16PtrFromString(tpc.encryptName)
|
||||
var strptr *uint16 = new(uint16)
|
||||
for i := 1; i <= tpc.getCount(); i++ {
|
||||
cipherGetInfo(uintptr(i), uintptr(unsafe.Pointer(&cipher_id)), uintptr(unsafe.Pointer(&strptr)),
|
||||
uintptr(unsafe.Pointer(&ty)), uintptr(unsafe.Pointer(&blk_size)), uintptr(unsafe.Pointer(&kh_size)))
|
||||
if tpc.encryptType == cipher_id {
|
||||
tpc.blockSize = blk_size
|
||||
tpc.khSize = kh_size
|
||||
tpc.encryptName = string(uintptr2bytes(uintptr(unsafe.Pointer(strptr))))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("ThirdPartyCipher: cipher id:%d not found", tpc.encryptType)
|
||||
}
|
||||
|
||||
func (tpc ThirdPartCipher) Encrypt(plaintext []byte, genDigest bool) []byte {
|
||||
var tmp_para uintptr
|
||||
cipherEncryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para)
|
||||
|
||||
ciphertextLen := cipherGetCipherTextSize(uintptr(tpc.encryptType), tmp_para, uintptr(len(plaintext)))
|
||||
|
||||
ciphertext := make([]byte, ciphertextLen)
|
||||
ret := cipherEncrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)),
|
||||
uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)))
|
||||
ciphertext = ciphertext[:ret]
|
||||
|
||||
cipherClean(uintptr(tpc.encryptType), tmp_para)
|
||||
// md5摘要
|
||||
if genDigest {
|
||||
digest := md5.Sum(plaintext)
|
||||
encrypt := ciphertext
|
||||
ciphertext = make([]byte, len(encrypt)+len(digest))
|
||||
copy(ciphertext[:len(encrypt)], encrypt)
|
||||
copy(ciphertext[len(encrypt):], digest[:])
|
||||
}
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
func (tpc ThirdPartCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) {
|
||||
var ret []byte
|
||||
if checkDigest {
|
||||
var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:]
|
||||
ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE]
|
||||
ret = tpc.decrypt(ret)
|
||||
var msgDigest = md5.Sum(ret)
|
||||
if !reflect.DeepEqual(msgDigest[:], digest) {
|
||||
return nil, errors.New("Decrypt failed/Digest not match\n")
|
||||
}
|
||||
} else {
|
||||
ret = tpc.decrypt(ciphertext)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (tpc ThirdPartCipher) decrypt(ciphertext []byte) []byte {
|
||||
var tmp_para uintptr
|
||||
|
||||
cipherDecryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para)
|
||||
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
ret := cipherDecrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)),
|
||||
uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)))
|
||||
plaintext = plaintext[:ret]
|
||||
|
||||
cipherClean(uintptr(tpc.encryptType), tmp_para)
|
||||
return plaintext
|
||||
}
|
||||
|
||||
func addBufSize(buf []byte, newCap int) []byte {
|
||||
newBuf := make([]byte, newCap)
|
||||
copy(newBuf, buf)
|
||||
return newBuf
|
||||
}
|
||||
|
||||
func uintptr2bytes(p uintptr) []byte {
|
||||
buf := make([]byte, 64)
|
||||
i := 0
|
||||
for b := (*byte)(unsafe.Pointer(p)); *b != 0; i++ {
|
||||
if i > cap(buf) {
|
||||
buf = addBufSize(buf, i*2)
|
||||
}
|
||||
buf[i] = *b
|
||||
// byte占1字节
|
||||
p++
|
||||
b = (*byte)(unsafe.Pointer(p))
|
||||
}
|
||||
return buf[:i]
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import "plugin"
|
||||
|
||||
var (
|
||||
dmCipherEncryptSo *plugin.Plugin
|
||||
cipherGetCountProc plugin.Symbol
|
||||
cipherGetInfoProc plugin.Symbol
|
||||
cipherEncryptInitProc plugin.Symbol
|
||||
cipherGetCipherTextSizeProc plugin.Symbol
|
||||
cipherEncryptProc plugin.Symbol
|
||||
cipherCleanupProc plugin.Symbol
|
||||
cipherDecryptInitProc plugin.Symbol
|
||||
cipherDecryptProc plugin.Symbol
|
||||
)
|
||||
|
||||
func initThirdPartCipher(cipherPath string) (err error) {
|
||||
if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cipherGetCount() int {
|
||||
ret := cipherGetCountProc.(func() interface{})()
|
||||
return ret.(int)
|
||||
}
|
||||
|
||||
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
|
||||
ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
|
||||
if ret.(int) == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_get_info failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
|
||||
ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
|
||||
if ret.(int) == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
|
||||
ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
|
||||
return ciphertextLen.(uintptr)
|
||||
}
|
||||
|
||||
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
|
||||
ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
|
||||
return ret.(uintptr)
|
||||
}
|
||||
|
||||
func cipherClean(cipherId, cipherPara uintptr) {
|
||||
cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
|
||||
}
|
||||
|
||||
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
|
||||
ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
|
||||
if ret.(int) == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
|
||||
ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
|
||||
return ret.(uintptr)
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import "plugin"
|
||||
|
||||
var (
|
||||
dmCipherEncryptSo *plugin.Plugin
|
||||
cipherGetCountProc plugin.Symbol
|
||||
cipherGetInfoProc plugin.Symbol
|
||||
cipherEncryptInitProc plugin.Symbol
|
||||
cipherGetCipherTextSizeProc plugin.Symbol
|
||||
cipherEncryptProc plugin.Symbol
|
||||
cipherCleanupProc plugin.Symbol
|
||||
cipherDecryptInitProc plugin.Symbol
|
||||
cipherDecryptProc plugin.Symbol
|
||||
)
|
||||
|
||||
func initThirdPartCipher(cipherPath string) (err error) {
|
||||
if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
|
||||
return err
|
||||
}
|
||||
if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cipherGetCount() int {
|
||||
ret := cipherGetCountProc.(func() interface{})()
|
||||
return ret.(int)
|
||||
}
|
||||
|
||||
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
|
||||
ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
|
||||
if ret.(int) == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_get_info failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
|
||||
ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
|
||||
if ret.(int) == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
|
||||
ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
|
||||
return ciphertextLen.(uintptr)
|
||||
}
|
||||
|
||||
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
|
||||
ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
|
||||
return ret.(uintptr)
|
||||
}
|
||||
|
||||
func cipherClean(cipherId, cipherPara uintptr) {
|
||||
cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
|
||||
}
|
||||
|
||||
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
|
||||
ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
|
||||
if ret.(int) == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
|
||||
ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
|
||||
return ret.(uintptr)
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
dmCipherEncryptDLL *syscall.LazyDLL
|
||||
cipherGetCountProc *syscall.LazyProc
|
||||
cipherGetInfoProc *syscall.LazyProc
|
||||
cipherEncryptInitProc *syscall.LazyProc
|
||||
cipherGetCipherTextSizeProc *syscall.LazyProc
|
||||
cipherEncryptProc *syscall.LazyProc
|
||||
cipherCleanupProc *syscall.LazyProc
|
||||
cipherDecryptInitProc *syscall.LazyProc
|
||||
cipherDecryptProc *syscall.LazyProc
|
||||
)
|
||||
|
||||
func initThirdPartCipher(cipherPath string) error {
|
||||
dmCipherEncryptDLL = syscall.NewLazyDLL(cipherPath)
|
||||
if err := dmCipherEncryptDLL.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
cipherGetCountProc = dmCipherEncryptDLL.NewProc("cipher_get_count")
|
||||
cipherGetInfoProc = dmCipherEncryptDLL.NewProc("cipher_get_info")
|
||||
cipherEncryptInitProc = dmCipherEncryptDLL.NewProc("cipher_encrypt_init")
|
||||
cipherGetCipherTextSizeProc = dmCipherEncryptDLL.NewProc("cipher_get_cipher_text_size")
|
||||
cipherEncryptProc = dmCipherEncryptDLL.NewProc("cipher_encrypt")
|
||||
cipherCleanupProc = dmCipherEncryptDLL.NewProc("cipher_cleanup")
|
||||
cipherDecryptInitProc = dmCipherEncryptDLL.NewProc("cipher_decrypt_init")
|
||||
cipherDecryptProc = dmCipherEncryptDLL.NewProc("cipher_decrypt")
|
||||
return nil
|
||||
}
|
||||
|
||||
func cipherGetCount() int {
|
||||
ret, _, _ := cipherGetCountProc.Call()
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
|
||||
ret, _, _ := cipherGetInfoProc.Call(seqno, cipherId, cipherName, _type, blkSize, khSIze)
|
||||
if ret == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_get_info failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
|
||||
ret, _, _ := cipherEncryptInitProc.Call(cipherId, key, keySize, cipherPara)
|
||||
if ret == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
|
||||
ciphertextLen, _, _ := cipherGetCipherTextSizeProc.Call(cipherId, cipherPara, plainTextSize)
|
||||
return ciphertextLen
|
||||
}
|
||||
|
||||
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
|
||||
ret, _, _ := cipherEncryptProc.Call(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
|
||||
return ret
|
||||
}
|
||||
|
||||
func cipherClean(cipherId, cipherPara uintptr) {
|
||||
_, _, _ = cipherCleanupProc.Call(cipherId, cipherPara)
|
||||
}
|
||||
|
||||
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
|
||||
ret, _, _ := cipherDecryptInitProc.Call(cipherId, key, keySize, cipherPara)
|
||||
if ret == 0 {
|
||||
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
|
||||
}
|
||||
}
|
||||
|
||||
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
|
||||
ret, _, _ := cipherDecryptProc.Call(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
|
||||
return ret
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2018, 达梦数据库有限公司.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
package security
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//var dmHome = flag.String("DM_HOME", "", "Where DMDB installed")
|
||||
var flagLock = sync.Mutex{}
|
||||
|
||||
func NewTLSFromTCP(conn net.Conn, sslCertPath string, sslKeyPath string, user string) (*tls.Conn, error) {
|
||||
if sslCertPath == "" && sslKeyPath == "" {
|
||||
// 用户必须手动指定ssl文件和签名(.cert文件)
|
||||
return nil, errors.New("sslCertPath and sslKeyPath can not be empty!")
|
||||
|
||||
}
|
||||
cer, err := tls.LoadX509KeyPair(sslCertPath, sslKeyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
Certificates: []tls.Certificate{cer},
|
||||
}
|
||||
tlsConn := tls.Client(conn, conf)
|
||||
if err := tlsConn.Handshake(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tlsConn, nil
|
||||
}
|
||||
Reference in New Issue
Block a user