diff --git a/crypto/aes.go b/crypto/aes.go new file mode 100644 index 0000000..237d043 --- /dev/null +++ b/crypto/aes.go @@ -0,0 +1,70 @@ +package crypto + +import ( + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "errors" +) + +// AesEncrypt function +// original The original password, salt is an optional variable. +// If the salt exists, the passed variable is used. +// If it does not exist, the system default salt value is used. +func (e *Crypto) AesEncrypt(original string, key ...string) (string, error) { + var saltValue = defaultAesKey + if len(key) > 0 { + saltValue = key[0] + } + + // Convert to byte array + origData := []byte(original) + k := []byte(saltValue) + if len(k) != 16 && len(k) != 24 && len(k) != 32 { + return "", errors.New("The length of the key should be 16 or 24 or 32") + } + // group key + block, _ := aes.NewCipher(k) + // Get the length of the key block + blockSize := block.BlockSize() + // Completion code + origData = pKCS7Padding(origData, blockSize) + // encryption mode + blockMode := cipher.NewCBCEncrypter(block, k[:blockSize]) + // create array + crated := make([]byte, len(origData)) + // encryption + blockMode.CryptBlocks(crated, origData) + return base64.StdEncoding.EncodeToString(crated), nil + +} + +// AesDecrypt function +// original The original password, salt is an optional variable. +// If the salt exists, the passed variable is used. +// If it does not exist, the system default salt value is used. +func (e *Crypto) AesDecrypt(crated string, salt ...string) (string, error) { + var saltValue = defaultAesKey + if len(salt) > 0 { + saltValue = salt[0] + } + // Convert to byte array + cratedByte, _ := base64.StdEncoding.DecodeString(crated) + k := []byte(saltValue) + if len(k) != 16 && len(k) != 24 && len(k) != 32 { + return "", errors.New("The length of the key should be 16 or 24 or 32") + } + // group key + block, _ := aes.NewCipher(k) + // Get the length of the key block + blockSize := block.BlockSize() + // encryption mode + blockMode := cipher.NewCBCDecrypter(block, k[:blockSize]) + // create array + orig := make([]byte, len(cratedByte)) + // decrypt + blockMode.CryptBlocks(orig, cratedByte) + // to complete the code + orig = pKCS7UnPadding(orig) + return string(orig), nil +} diff --git a/crypto/aes_test.go b/crypto/aes_test.go new file mode 100644 index 0000000..5c135ae --- /dev/null +++ b/crypto/aes_test.go @@ -0,0 +1,20 @@ +package crypto + +import ( + "fmt" + "testing" +) + +func TestCrypto_AesEncrypt(t *testing.T) { + fmt.Println(cryptoTool.AesEncrypt("xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy")) + //8xSzAOz2WjeZXfaxbW4ARKB63ta9EOeGp/wvmzHfUvA4Gd8AG32SeTlqqmEsinNO + fmt.Println(cryptoTool.AesEncrypt("xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy", "1234567812345678")) + //XCbjg7uyoIVeBvW0Wbt6vhtCgHFY3fFscbgkL8Ff7ZnbRduIT6qd/nw/qHsF1TEA + +} + +func TestCrypto_AesDecrypt(t *testing.T) { + fmt.Println(cryptoTool.AesDecrypt("XCbjg7uyoIVeBvW0Wbt6vhtCgHFY3fFscbgkL8Ff7ZnbRduIT6qd/nw/qHsF1TEA", "1234567812345678")) + //xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy + +} diff --git a/crypto/des.go b/crypto/des.go new file mode 100644 index 0000000..c764bfc --- /dev/null +++ b/crypto/des.go @@ -0,0 +1,72 @@ +package crypto + +import ( + "crypto/des" + "encoding/hex" + "errors" +) + +// DesEncrypt des encrypted function +// salt The parameter is the salt value of encryption and decryption, and the maximum +// length is 8. If the length is exceeded, the corresponding exception will be thrown +func (*Crypto) DesEncrypt(text string, key ...string) (string, error) { + k := []byte(defaultDesKey) + if len(key) > 0 { + k = []byte(key[0]) + if len(k) > 8 { + return "", errors.New("DES The maximum length of the encrypted salt value is 8") + } + } + src := []byte(text) + block, err := des.NewCipher(k) + if err != nil { + return "", err + } + bs := block.BlockSize() + src = zeroPadding(src, bs) + if len(src)%bs != 0 { + return "", errors.New("What is required is an integer multiple of the size") + } + out := make([]byte, len(src)) + dst := out + for len(src) > 0 { + block.Encrypt(dst, src[:bs]) + src = src[bs:] + dst = dst[bs:] + } + return hex.EncodeToString(out), nil +} + +// DesDecrypt des encrypted function +// salt The parameter is the salt value of encryption and decryption, and the maximum +// length is 8. If the length is exceeded, the corresponding exception will be thrown +func (*Crypto) DesDecrypt(decrypted string, key ...string) (string, error) { + k := []byte(defaultDesKey) + if len(key) > 0 { + if len(key[0]) > 8 { + return "", errors.New("DES The maximum length of the encrypted salt value is 8") + } + k = []byte(key[0]) + } + src, err := hex.DecodeString(decrypted) + if err != nil { + return "", err + } + block, err := des.NewCipher(k) + if err != nil { + return "", err + } + out := make([]byte, len(src)) + dst := out + bs := block.BlockSize() + if len(src)%bs != 0 { + return "", errors.New("crypto/cipher: input not full blocks") + } + for len(src) > 0 { + block.Decrypt(dst, src[:bs]) + src = src[bs:] + dst = dst[bs:] + } + out = zeroUnPadding(out) + return string(out), nil +} diff --git a/crypto/des_test.go b/crypto/des_test.go new file mode 100644 index 0000000..d657943 --- /dev/null +++ b/crypto/des_test.go @@ -0,0 +1,19 @@ +package crypto + +import ( + "fmt" + "testing" +) + +func TestCrypto_DesEncrypt(t *testing.T) { + fmt.Println(cryptoTool.DesEncrypt("xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy")) + //42002eb4f920ed0f228c833c3d54ab3d7c7e1dd8999306ede9e2cfd9c5d5b7356c2951efbc920e68 + fmt.Println(cryptoTool.DesEncrypt("xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy", "12345678")) + //276b7af582c1aa7b99ef89bf9aac3b62dee2179b2e58208af0225d6094cd99d93d7595a98bff809d + + fmt.Println(cryptoTool.DesDecrypt("42002eb4f920ed0f228c833c3d54ab3d7c7e1dd8999306ede9e2cfd9c5d5b7356c2951efbc920e68")) + //xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy + fmt.Println(cryptoTool.DesDecrypt("276b7af582c1aa7b99ef89bf9aac3b62dee2179b2e58208af0225d6094cd99d93d7595a98bff809d", "12345678")) + //xZwKptMh5VdCv_6gAnoO9b4YgwE8J6dy + +} diff --git a/crypto/entry.go b/crypto/entry.go index bf26c89..5befc91 100644 --- a/crypto/entry.go +++ b/crypto/entry.go @@ -1,4 +1,38 @@ package crypto +import "bytes" + type Crypto struct { } + +const defaultAesKey = "wVQvqtER8xzTLKB0f9Y4S_30ZF0rEDAN" //8 16 32 +const defaultDesKey = "Xj9UnbYA" //max 8 + +// complement method +func pKCS7Padding(ciphertext []byte, blocksize int) []byte { + padding := blocksize - len(ciphertext)%blocksize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(ciphertext, padtext...) +} + +// to code method +func pKCS7UnPadding(origData []byte) []byte { + length := len(origData) + unpadding := int(origData[length-1]) + return origData[:(length - unpadding)] +} + +// zeroPadding zero padding function +func zeroPadding(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + padtext := bytes.Repeat([]byte{0}, padding) + return append(ciphertext, padtext...) +} + +// zeroUnPadding zero unPadding function +func zeroUnPadding(origData []byte) []byte { + return bytes.TrimFunc(origData, + func(r rune) bool { + return r == rune(0) + }) +} diff --git a/rand/init.go b/rand/init.go new file mode 100644 index 0000000..c218f62 --- /dev/null +++ b/rand/init.go @@ -0,0 +1,11 @@ +package rand + +import ( + "math/rand" + "time" +) + +func init() { + rand.Seed(time.Now().UnixNano()) // 纳秒时间戳 + +} diff --git a/rand/password.go b/rand/password.go index 6708a81..1eb6c04 100644 --- a/rand/password.go +++ b/rand/password.go @@ -3,39 +3,44 @@ package rand import ( "bytes" "math/rand" - "time" ) func (rr *Rand) randomGetSomeChar(str string, l int) string { bytes := []byte(str) - result := []byte{} - r := rand.New(rand.NewSource(time.Now().UnixNano())) + var result []byte + //r := rand.New(rand.NewSource(time.Now().UnixNano())) for i := 0; i < l; i++ { - result = append(result, bytes[r.Intn(len(bytes))]) + //result = append(result, bytes[r.Intn(len(bytes))]) + result = append(result, bytes[rand.Intn(len(bytes))]) } return string(result) } -func (r *Rand) GetPassword(len int) string { - base_num := "023456789" - base_char_low := "abcdefghijkmnpqrstuvwxyz" - base_char_high := "ABCDEFGHJKLMNOPQRSTUVWXYZ" - base_sign_spec := "_" +// 长度选填 默认32位 +func (rr *Rand) GetPassword(length ...int) string { + baseNum := "023456789" + baseCharLow := "abcdefghijkmnpqrstuvwxyz" + baseCharHigh := "ABCDEFGHJKLMNOPQRSTUVWXYZ" + baseSignSpec := "_" str := "023456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ_" var stringBuilder bytes.Buffer - if len < 5 { - len = 5 + lenPassword := 32 + if len(length) > 0 { + lenPassword = length[0] } - stringBuilder.WriteString(r.randomGetSomeChar(base_sign_spec, 1)) - stringBuilder.WriteString(r.randomGetSomeChar(base_num, 1)) - stringBuilder.WriteString(r.randomGetSomeChar(base_char_low, 1)) - stringBuilder.WriteString(r.randomGetSomeChar(base_char_high, 1)) - stringBuilder.WriteString(r.randomGetSomeChar(str, len-4)) - str_result := stringBuilder.String() - arr_result := []byte(str_result) + if lenPassword < 5 { + lenPassword = 5 + } + stringBuilder.WriteString(rr.randomGetSomeChar(baseSignSpec, 1)) + stringBuilder.WriteString(rr.randomGetSomeChar(baseNum, 1)) + stringBuilder.WriteString(rr.randomGetSomeChar(baseCharLow, 1)) + stringBuilder.WriteString(rr.randomGetSomeChar(baseCharHigh, 1)) + stringBuilder.WriteString(rr.randomGetSomeChar(str, lenPassword-4)) + strResult := stringBuilder.String() + arrResult := []byte(strResult) for i := 0; i < 4; i++ { - num := rand.Intn(len - 1) - arr_result[i], arr_result[num] = arr_result[num], arr_result[i] + num := rand.Intn(lenPassword - 1) + arrResult[i], arrResult[num] = arrResult[num], arrResult[i] } - return string(arr_result) + return string(arrResult) } diff --git a/rand/password_test.go b/rand/password_test.go index e41b6e8..bc1bf9c 100644 --- a/rand/password_test.go +++ b/rand/password_test.go @@ -9,5 +9,6 @@ var randTool Rand func TestRand_GetPassword(t *testing.T) { fmt.Println(randTool.GetPassword(32)) + fmt.Println(randTool.GetPassword()) } diff --git a/rand/random.go b/rand/random.go index 0c5f03e..9f261aa 100644 --- a/rand/random.go +++ b/rand/random.go @@ -3,15 +3,14 @@ package rand import ( "math/rand" "strconv" - "time" ) // 包含大小写和数字 -func (r *Rand) RandomString(n int) string { +func (rr *Rand) RandomString(n int) string { letters := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789") //var letters = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789") result := make([]byte, n) - rand.Seed(time.Now().Unix()) + //rand.Seed(time.Now().Unix()) for i := range result { result[i] = letters[rand.Intn(len(letters))] } @@ -21,11 +20,11 @@ func (r *Rand) RandomString(n int) string { } // 生成指定位数的数字字符串,第一位不为0 -func (r *Rand) RandomCode(n int) string { +func (rr *Rand) RandomCode(n int) string { numbers := []byte("0123456789") numbers_no_zero := []byte("123456789") result := make([]byte, n) - rand.Seed(time.Now().Unix()) + //rand.Seed(time.Now().Unix()) //code := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000)) for i := range result { result[i] = numbers[rand.Intn(len(numbers))] @@ -41,10 +40,10 @@ func (r *Rand) RandomCode(n int) string { } // 6位随机验证码 -func (r *Rand) GetNum6() string { +func (rr *Rand) GetNum6() string { //deltaNumber := exponent(10,6) //baseNumber := exponent(10,7) - rand.Seed(time.Now().UnixNano()) + //rand.Seed(time.Now().UnixNano()) code := rand.Intn(899999) + 100000 //code := rand.Intn(baseNumber-baseNumber-1) + deltaNumber res := strconv.Itoa(code) //转字符串返回