From 93b420af64c9f34d87c36b9b0ed5fc63c6de64ec Mon Sep 17 00:00:00 2001 From: guzeng Date: Fri, 5 Feb 2021 11:16:22 +0800 Subject: [PATCH] init --- authcode.go | 139 ++++++++++++++++++++++++++++ authcode_test.go | 25 +++++ des.go | 230 ++++++++++++++++++++++++++++++++++++++++++++++ des_test.go | 69 ++++++++++++++ md5.go | 22 +++++ ripemd160.go | 20 ++++ ripemd160_test.go | 15 +++ 7 files changed, 520 insertions(+) create mode 100755 authcode.go create mode 100755 authcode_test.go create mode 100755 des.go create mode 100755 des_test.go create mode 100755 md5.go create mode 100644 ripemd160.go create mode 100644 ripemd160_test.go diff --git a/authcode.go b/authcode.go new file mode 100755 index 0000000..4e7b96a --- /dev/null +++ b/authcode.go @@ -0,0 +1,139 @@ +package crypter + +import ( + "crypto/md5" + "encoding/base64" + "fmt" + "io" + "strconv" + "strings" + "time" +) + +// SSO gxytoken authcode +// btype 加密or解密 bool true:加密 false:解密 默认false +// skey 秘钥 +// text 加/解密内容 + +func AuthCode(text, skey string, btype bool) string { + + isEncode := btype + key := skey + expiry := 0 + cKeyLen := 4 + + timestamp := time.Now().Unix() + // md5加密key + mKey := Md5Sum(key) + // 参与加密的 + keyA := Md5Sum(mKey[0:16]) + // 用于验证数据有效性的 + keyB := Md5Sum(mKey[16:]) + // 动态部分 + var keyC string + if cKeyLen > 0 { + if isEncode { + // 加密的时候,动态获取一个秘钥 + keyC = Md5Sum(fmt.Sprint(timestamp))[32-cKeyLen:] + } else { + // 解密的时候从头部获取动态秘钥部分 + keyC = text[0:cKeyLen] + } + } + // 加入了动态的秘钥 + cryptKey := keyA + Md5Sum(keyA+keyC) + // 秘钥长度 + keyLen := len(cryptKey) + if isEncode { + // 加密 前10位是过期验证字符串 10-26位字符串验证 + var d int64 + if expiry > 0 { + d = timestamp + int64(expiry) + } + text = fmt.Sprintf("%010d%s%s", d, Md5Sum(text + keyB)[0:16], text) + } else { + // 解密 + //res, _ := base64.StdEncoding.DecodeString(text[cKeyLen:]) + res := Base64Decode(text[cKeyLen:]) + text = string(res) + } + // 字符串长度 + textLen := len(text) + if textLen <= 0 { + return "" + } + + // 密匙簿(0-256) + box := make([]int, 0) + for i := 0; i < 256; i++ { + box = append(box, i) + } + + // 对称算法 + var rndKey []int + cryptKeyB := []byte(cryptKey) + for i := 0; i < 256; i++ { + pos := i % keyLen + rndKey = append(rndKey, int(cryptKeyB[pos])) + } + + j := 0 + for i := 0; i < 256; i++ { + j = (j + box[i] + rndKey[i]) % 256 + box[i], box[j] = box[j], box[i] + } + + textB := []byte(text) + a := 0 + j = 0 + var result []byte + for i := 0; i < textLen; i++ { + a = (a + 1) % 256 + j = (j + box[a]) % 256 + box[a], box[j] = box[j], box[a] + result = append(result, byte(int(textB[i])^(box[(box[a]+box[j])%256]))) + } + + if isEncode { + return keyC + strings.Replace(base64.StdEncoding.EncodeToString(result), "=", "", -1) + } + + // 获取前10位,判断过期时间 + d, err := strconv.ParseInt(string(result[0:10]), 10, 64) + if err != nil { + d = 0 + } + fmt.Println(string(result[10:26]), Md5Sum(string(result[26:]) + keyB)[0:16]) + if (d == 0 || d-timestamp > 0) && string(result[10:26]) == Md5Sum(string(result[26:]) + keyB)[0:16] { + return string(result[26:]) + } + + fmt.Println(string(result[26:])) + + return "" +} + +//MD5SUm +func Md5Sum(str string) string { + h := md5.New() + io.WriteString(h, str) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +//Base64Decode +func Base64Decode(str string) []byte { + var sdec []byte + var err error + x := len(str) * 3 % 4 + fmt.Println(x) + switch { + case x == 2: + str += "==" + case x == 1: + str += "=" + } + if sdec, err = base64.StdEncoding.DecodeString(str); err != nil { + return sdec + } + return sdec +} diff --git a/authcode_test.go b/authcode_test.go new file mode 100755 index 0000000..ca76b0d --- /dev/null +++ b/authcode_test.go @@ -0,0 +1,25 @@ +package crypter + +import ( + "fmt" + "testing" +) + +func Test_AuthCodeDec(t *testing.T) { + str := "18175" + key := "1509930887" + isencode := true + + ret := AuthCode(str, key, isencode) + fmt.Println(str, "加密结果 ret:", ret) + +} + +func Test_AuthCodeEnc(t *testing.T) { + str := "1fa9Vsp7e91Pg9z8xorzO55lSbLcHZbNt9z10K8d7TEZZg" + key := "1509930887" + isencode := false + + ret := AuthCode(str, key, isencode) + fmt.Println(str, "解密结果 ret:", ret) +} diff --git a/des.go b/des.go new file mode 100755 index 0000000..2fa6b59 --- /dev/null +++ b/des.go @@ -0,0 +1,230 @@ +// DES、3DES加解密示例, +package crypter + +import ( + "bytes" + "crypto/cipher" + "crypto/des" + "encoding/base64" + "encoding/hex" + "errors" + "log" + "strings" +) + +const KEYS = "gfe023u_sefiel#fi32lf3z!" //必须24位 +/** + * 加密并转换为base64字符串 + */ +func DesEncrypt(args ...string) (string, error) { //origData, key []byte + + code, keyorg, err := getArgs(args) + if err != nil { + return "", err + } + key := keyorg[0:8] + + block, err := des.NewCipher(key) + if err != nil { + return "", err + } + + origData := []byte(code) + origData = PKCS5Padding(origData, block.BlockSize()) + blockMode := cipher.NewCBCEncrypter(block, key) + crypted := make([]byte, len(origData)) + // 根据CryptBlocks方法的说明,如下方式初始化crypted也可以 + // crypted := origData + blockMode.CryptBlocks(crypted, origData) + + encode := base64.StdEncoding.EncodeToString(crypted) + return encode, nil +} + +/** + * 加密并转换为16进制字符串 + */ +func DesEn(code, key string) string { + + block, err := des.NewCipher([]byte(key)) + if err != nil { + return "" + } + + origData := []byte(code) + + origData = PKCS5Padding(origData, block.BlockSize()) + blockMode := cipher.NewCBCEncrypter(block, []byte(key)) + crypted := make([]byte, len(origData)) + // 根据CryptBlocks方法的说明,如下方式初始化crypted也可以 + // crypted := origData + blockMode.CryptBlocks(crypted, origData) + + return strings.ToUpper(hex.EncodeToString(crypted)) +} + +/** + * 解密已转为base64字符串有DES加密 + */ +func DesDecrypt(args ...string) (string, error) { + + decode, keyorg, err := getArgs(args) + if err != nil { + return "", err + } + + key := keyorg[0:8] + crypted, err := base64.StdEncoding.DecodeString(decode) + block, err := des.NewCipher([]byte(key)) + if err != nil { + return "", err + } + + blockMode := cipher.NewCBCDecrypter(block, key) + + if len(crypted)%blockMode.BlockSize() != 0 { + return "", errors.New("error,input not full blocks") + } + origData := make([]byte, len(crypted)) + blockMode.CryptBlocks(origData, crypted) + origData = PKCS5UnPadding(origData) + return string(origData), nil +} + +/** + * 解密已转为16进制字符串有DES加密 + */ +func DesDe(code, key string) string { + + crypted, err := hex.DecodeString(code) + if err != nil { + return "" + } + block, err := des.NewCipher([]byte(key)) + if err != nil { + return "" + } + blockMode := cipher.NewCBCDecrypter(block, []byte(key)) + + if len(crypted)%blockMode.BlockSize() != 0 { + return "" + } + origData := make([]byte, len(crypted)) + blockMode.CryptBlocks(origData, crypted) + origData = PKCS5UnPadding(origData) + return string(origData) +} + +// 3DES加密, 可与php MCRYPT_3DES加密方式对应 +func TripleDesEncrypt(args ...string) (string, error) { + + code, key, err := getArgs(args) + if err != nil { + return "", err + } + if code == "" { + return "", errors.New("加密数据为空") + } + + block, err := des.NewTripleDESCipher(key) + if err != nil { + return "", err + } + + origData := []byte(code) + + origData = PKCS5Padding(origData, block.BlockSize()) + blockMode := cipher.NewCBCEncrypter(block, key[:8]) + crypted := make([]byte, len(origData)) + blockMode.CryptBlocks(crypted, origData) + + encode := base64.StdEncoding.EncodeToString(crypted) + + return encode, nil +} + +// 3DES解密 +func TripleDesDecrypt(args ...string) (string, error) { + + decode, key, err := getArgs(args) + if err != nil { + return "", err + } + + if decode == "" { + return "", errors.New("解密数据为空") + } + + block, err := des.NewTripleDESCipher(key) + if err != nil { + return "", err + } + + crypted, decodeErr := base64.StdEncoding.DecodeString(decode) + + if decodeErr != nil { + return "", decodeErr + } + + blockMode := cipher.NewCBCDecrypter(block, key[:8]) + origData := make([]byte, len(crypted)) + + if len(crypted)%blockMode.BlockSize() != 0 { + log.Println("ERROR", "TripleDesDecrypt: input not full blocks") + return "", errors.New("解密失败") + } + blockMode.CryptBlocks(origData, crypted) + origData = PKCS5UnPadding(origData) + + return string(origData), nil +} + +//获取参数 +func getArgs(args []string) (string, []byte, error) { + if len(args) == 0 { + return "", nil, errors.New("参数不能为空") + } + + origData := args[0] + + var crypt_key string + + if len(args) == 2 { + crypt_key = args[1] + } else { + crypt_key = KEYS + } + + key := []byte(crypt_key) + + return origData, key, nil +} + +func ZeroPadding(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + padtext := bytes.Repeat([]byte{0}, padding) + return append(ciphertext, padtext...) +} + +func ZeroUnPadding(origData []byte) []byte { + return bytes.TrimRightFunc(origData, func(r rune) bool { + return r == rune(0) + }) +} + +func PKCS5Padding(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(ciphertext, padtext...) +} + +func PKCS5UnPadding(origData []byte) []byte { + length := len(origData) + // 去掉最后一个字节 unpadding 次 + unpadding := int(origData[length-1]) + if length < unpadding || unpadding/8 > 3 { + //解密的是错误的数据情况下,是没有填充的 + return []byte("") + } + return origData[:(length - unpadding)] +} diff --git a/des_test.go b/des_test.go new file mode 100755 index 0000000..32747bc --- /dev/null +++ b/des_test.go @@ -0,0 +1,69 @@ +package crypter + +import ( + "fmt" + "testing" +) + +//func Test_DesEncrypt(t *testing.T) { +// str := "123456789" +// key := "DBPHW3K9" + +// ret, err := DesEncrypt(str, key) +// fmt.Println(ret) +// fmt.Println(err) +//} + +//func Test_DesDecrypt(t *testing.T) { +// str := "54291b8fa850aca3fb102569e569718797" +// key := "DBPHW3K9" + +// ret, err := DesDecrypt(str, key) +// fmt.Println("ret:", ret) +// fmt.Println(err) +//} + +//func Test_DesEn(t *testing.T) { +// str := "rdesktop 10.0.66.21 -f -u username" +// key := "2boscl0z" +// en := DesEn(str, key) +// fmt.Println(en) + +// fmt.Println(str) +//} + +//func Test_DesDe(t *testing.T) { + +// str := "CD3A229D828AC38784064B2A1CCDEAD803D859DE60B20AE4FE81D27F59B64D39E3D09545EFDAFBB644C779872E1EB86B14742FE6A267D69AFD5888256F9D11D6D86EAECBCB2F0475E83432721DEF3BC60393C382F74B8BB7" +// fmt.Println(str) +// key := "LD13EY1R" + +// de := DesDe(str, key) +// fmt.Println(" 数据 :", de) +//} + +//func Test_TripleDesEncrypt(t *testing.T) { +// // DogKey := "FP4FSSJ5" +// // key := DogKey + "gi$01Lzy" + DogKey +// kenEncode, err := TripleDesEncrypt("control-hdraydesktop") + +// t.Log(kenEncode) +// t.Log(err) +//} +func Test_TripleDesDecrypt(t *testing.T) { + str := "7fXpywgiF25K" + DogKey := "FP4FSSJ5" + key := DogKey + "gi$01Lzy" + DogKey + de, err := TripleDesDecrypt(str, key) //, "8JTE41BA8JTE41BA8JTE41BA" + fmt.Println(de, err) + t.Log(de) + + de, err = TripleDesDecrypt("n7BCRSXtDUKv/RwRgu1s7j/FRg3v+TG9UFEqx7f+BPTuhl0Nm3GMRxbh/8JDxVH0zwJoQZOLUtnBkuchs2EaM9qNVLpIjF4fsoKMerlCbc1PY4mTKNdszzyTG31Nq/a0yrPrxInzsEBej8zrBLXBY0Ub7fO/aPQSxcEoTXK2/NmJI2r6y/LXfnmUeQ5/nBQuAOkP94mjVvyJi40wqGb0f7ae8Y3PoDONmM1JbGNVl0R0LMLQtLcqK914Ls8YQY3OZRBGmZtRQ5ZDbqyXCBCl6igsuZzmN+q8FyXjyzeAdWtlvbQtW1FROFNXXS3qExYx2a137l+szQGfWUpYvP9Egdx2YixxsIrZNEjQQVQzJkM=") //, "8JTE41BA8JTE41BA8JTE41BA" + fmt.Println(de, err) +} + +//func Test_Md5Password(t *testing.T) { +// str := "123456" +// one := Md5Password(str, "") +// fmt.Println("md5 123456", one) +//} diff --git a/md5.go b/md5.go new file mode 100755 index 0000000..b981f9a --- /dev/null +++ b/md5.go @@ -0,0 +1,22 @@ +/* + * For crypter md5 + */ +package crypter + +import ( + "crypto/md5" + "encoding/hex" +) + +//密码加密 +func Md5Password(password string, rand ...string) string { + if len(rand) > 0 { + password += rand[0] + } + + h := md5.New() + h.Write([]byte(password)) // 需要加密的字符串 + cipher2Str := h.Sum(nil) + sMd5 := hex.EncodeToString(cipher2Str) // 输出加密结果 + return sMd5 +} diff --git a/ripemd160.go b/ripemd160.go new file mode 100644 index 0000000..f75705e --- /dev/null +++ b/ripemd160.go @@ -0,0 +1,20 @@ +package crypter + +import ( + "crypto/hmac" + "fmt" + + "golang.org/x/crypto/ripemd160" +) + +func EncryptedToken(token, key string) string { + + h2 := hmac.New(ripemd160.New, []byte(key)) + + h2.Write([]byte(token)) + + hashBytes := h2.Sum(nil) + hashString := fmt.Sprintf("%x", hashBytes) + + return hashString +} diff --git a/ripemd160_test.go b/ripemd160_test.go new file mode 100644 index 0000000..d5bb982 --- /dev/null +++ b/ripemd160_test.go @@ -0,0 +1,15 @@ +package crypter + +import ( + // "fmt" + "testing" +) + +func Test_EncryptedToken(t *testing.T) { + //2a12d5373e04a96c2e1862f786e9d054464fc13d + // fmt.Println([]byte("2a12d5373e04a96c2e1862f786e9d054464fc13d")) + token := "8d9a0183-ef9c-4ea6-bcf7-ab562ff4ac57" + key := "i3d6o32wo8fvs1fvdpwens" + ret := EncryptedToken(token, key) + t.Log(ret) +}