diff --git a/encrypt/aes.go b/encrypt/aes.go new file mode 100644 index 0000000..36cf29b --- /dev/null +++ b/encrypt/aes.go @@ -0,0 +1,73 @@ +package encrypt + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/base64" +) + +// AESEncrypt Aes加密 key: 24个字符 +func AESEncrypt(orig string, key string) (string, error) { + // 转成字节数组 + origData := []byte(orig) + k := []byte(key) + // 分组秘钥 + // NewCipher该函数限制了输入k的长度必须为16, 24或者32 + block, err := aes.NewCipher(k) + if err != nil { + return "", err + } + // 获取秘钥块的长度 + blockSize := block.BlockSize() + // 补全码 + origData = PKCS7Padding(origData, blockSize) + // 加密模式 + blockMode := cipher.NewCBCEncrypter(block, k[:blockSize]) + // 创建数组 + cryted := make([]byte, len(origData)) + // 加密 + blockMode.CryptBlocks(cryted, origData) + return base64.StdEncoding.EncodeToString(cryted), nil +} + +// AESDecrypt Aes解密 key: 24个字符 +func AESDecrypt(crypt string, key string) (string, error) { + // 转成字节数组 + cryptByte, err := base64.StdEncoding.DecodeString(crypt) + if err != nil { + return "", err + } + k := []byte(key) + // 分组秘钥 + block, err := aes.NewCipher(k) + if err != nil { + return "", err + } + // 获取秘钥块的长度 + blockSize := block.BlockSize() + // 加密模式 + blockMode := cipher.NewCBCDecrypter(block, k[:blockSize]) + // 创建数组 + orig := make([]byte, len(cryptByte)) + // 解密 + blockMode.CryptBlocks(orig, cryptByte) + // 去补全码 + orig = PKCS7UnPadding(orig) + return string(orig), nil +} + +// PKCS7Padding 补码 +// AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。 +func PKCS7Padding(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + paddingText := bytes.Repeat([]byte{byte(padding)}, padding) + return append(ciphertext, paddingText...) +} + +// PKCS7UnPadding 去码 +func PKCS7UnPadding(origData []byte) []byte { + length := len(origData) + unPadding := int(origData[length-1]) + return origData[:(length - unPadding)] +} diff --git a/encrypt/base64.go b/encrypt/base64.go new file mode 100644 index 0000000..d46db6c --- /dev/null +++ b/encrypt/base64.go @@ -0,0 +1,15 @@ +package encrypt + +import "encoding/base64" + +// Base64Encrypt Base64加密 +func Base64Encrypt(str string) string { + data := []byte(str) + return base64.StdEncoding.EncodeToString(data) +} + +// Base64Decrypt Base64解密 +func Base64Decrypt(str string) (string, error) { + decodeBytes, err := base64.StdEncoding.DecodeString(str) + return string(decodeBytes), err +} diff --git a/encrypt/des.go b/encrypt/des.go new file mode 100644 index 0000000..837e0f8 --- /dev/null +++ b/encrypt/des.go @@ -0,0 +1,91 @@ +package encrypt + +import ( + "bytes" + "crypto/cipher" + "crypto/des" + "encoding/base64" +) + +// DESEncrypt DES加密 key:8位 +func DESEncrypt(origData, key []byte) string { + //将字节秘钥转换成block快 + block, _ := des.NewCipher(key) + //对明文先进行补码操作 + origData = PKCS5Padding(origData, block.BlockSize()) + //设置加密方式 + blockMode := cipher.NewCBCEncrypter(block, key) + //创建明文长度的字节数组 + crypted := make([]byte, len(origData)) + //加密明文,加密后的数据放到数组中 + blockMode.CryptBlocks(crypted, origData) + return base64.StdEncoding.EncodeToString(crypted) +} + +// DESDecrypt DES解密 key:8位 +func DESDecrypt(data string, key []byte) string { + //倒叙执行一遍加密方法 + //将字符串转换成字节数组 + crypted, _ := base64.StdEncoding.DecodeString(data) + //将字节秘钥转换成block快 + block, _ := des.NewCipher(key) + //设置解密方式 + blockMode := cipher.NewCBCDecrypter(block, key) + //创建密文大小的数组变量 + origData := make([]byte, len(crypted)) + //解密密文到数组origData中 + blockMode.CryptBlocks(origData, crypted) + //去补码 + origData = PKCS5UnPadding(origData) + + return string(origData) +} + +// PKCS5Padding 实现明文的补码 +func PKCS5Padding(ciphertext []byte, blockSize int) []byte { + //计算出需要补多少位 + padding := blockSize - len(ciphertext)%blockSize + //Repeat()函数的功能是把参数一 切片复制 参数二count个,然后合成一个新的字节切片返回 + // 需要补padding位的padding值 + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + //把补充的内容拼接到明文后面 + return append(ciphertext, padtext...) +} + +// PKCS5UnPadding 去除补码 +func PKCS5UnPadding(origData []byte) []byte { + length := len(origData) + // 去掉最后一个字节 unpadding 次 + unpadding := int(origData[length-1]) + //解密去补码时需取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文 + return origData[:(length - unpadding)] +} + +// TripleDESEncrypt 3DES加密 key:24位 +func TripleDESEncrypt(origData, key []byte) ([]byte, error) { + block, err := des.NewTripleDESCipher(key) + if err != nil { + return nil, err + } + origData = PKCS5Padding(origData, block.BlockSize()) + // origData = ZeroPadding(origData, block.BlockSize()) + blockMode := cipher.NewCBCEncrypter(block, key[:8]) + crypted := make([]byte, len(origData)) + blockMode.CryptBlocks(crypted, origData) + return crypted, nil +} + +// TripleDESDecrypt 3DES解密 key:24位 +func TripleDESDecrypt(crypted, key []byte) ([]byte, error) { + block, err := des.NewTripleDESCipher(key) + if err != nil { + return nil, err + } + blockMode := cipher.NewCBCDecrypter(block, key[:8]) + origData := make([]byte, len(crypted)) + // origData := crypted + blockMode.CryptBlocks(origData, crypted) + origData = PKCS5UnPadding(origData) + // origData = ZeroUnPadding(origData) + return origData, nil +} diff --git a/encrypt/md5.go b/encrypt/md5.go new file mode 100644 index 0000000..2caccc2 --- /dev/null +++ b/encrypt/md5.go @@ -0,0 +1,12 @@ +package encrypt + +import ( + "crypto/md5" + "encoding/hex" +) + +func MD5(value string) string { + m := md5.New() + m.Write([]byte(value)) + return hex.EncodeToString(m.Sum(nil)) +} diff --git a/encrypt/password.go b/encrypt/password.go new file mode 100644 index 0000000..cc96854 --- /dev/null +++ b/encrypt/password.go @@ -0,0 +1,72 @@ +package encrypt + +import ( + "crypto/rand" + "encoding/hex" + "fmt" + "strings" + + "golang.org/x/crypto/bcrypt" + "golang.org/x/crypto/scrypt" +) + +// ******************** scrypt ******************** + +// ScryptHashPassword scrypt 加密 +// password 原始密码 +func ScryptHashPassword(password string) (string, error) { + // example for making salt - https://play.golang.org/p/_Aw6WeWC42I + salt := make([]byte, 32) + _, err := rand.Read(salt) + if err != nil { + return "", err + } + + // using recommended cost parameters from - https://godoc.org/golang.org/x/crypto/scrypt + shash, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) + if err != nil { + return "", err + } + + // return hex-encoded string with salt appended to password + hashedPW := fmt.Sprintf("%s.%s", hex.EncodeToString(shash), hex.EncodeToString(salt)) + + return hashedPW, nil +} + +// ScryptComparePassword 判断密码是否正确 +// storedPassword 加密密码 +// suppliedPassword 原始密码 +func ScryptComparePassword(storedPassword string, suppliedPassword string) (bool, error) { + pwsalt := strings.Split(storedPassword, ".") + + // check supplied password salted with hash + salt, err := hex.DecodeString(pwsalt[1]) + + if err != nil { + return false, fmt.Errorf("unable to verify user password") + } + + shash, err := scrypt.Key([]byte(suppliedPassword), salt, 32768, 8, 1, 32) + + return hex.EncodeToString(shash) == pwsalt[0], nil +} + +// ******************** bcrypt ******************** + +// BcryptHashPassword bcrypt 加密 +// password 原始密码 +func BcryptHashPassword(password string) (string, error) { + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", fmt.Errorf("failed to hash password: %w", err) + } + return string(hashedPassword), nil +} + +// BcryptComparePassword 判断密码是否正确 +// hashedPassword 加密密码 +// password 原始密码 +func BcryptComparePassword(hashedPassword string, password string) error { + return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) +} diff --git a/encrypt/rsa.go b/encrypt/rsa.go new file mode 100644 index 0000000..e5aab0b --- /dev/null +++ b/encrypt/rsa.go @@ -0,0 +1,64 @@ +package encrypt + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" +) + +// RSAEncrypt 加密 +func RSAEncrypt(origData []byte) ([]byte, error) { + block, _ := pem.Decode(publicKey) + if block == nil { + return nil, errors.New("public key error") + } + pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return nil, err + } + pub := pubInterface.(*rsa.PublicKey) + return rsa.EncryptPKCS1v15(rand.Reader, pub, origData) +} + +// RSADecrypt 解密 +func RSADecrypt(ciphertext []byte) ([]byte, error) { + block, _ := pem.Decode(privateKey) + if block == nil { + return nil, errors.New("private key error!") + } + priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + return nil, err + } + return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext) +} + +// 公钥和私钥可以从文件中读取 +var privateKey = []byte(` +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDZsfv1qscqYdy4vY+P4e3cAtmvppXQcRvrF1cB4drkv0haU24Y +7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0DgacdwYWd/7PeCELyEipZJL07Vro7 +Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NLAUeJ6PeW+DAkmJWF6QIDAQAB +AoGBAJlNxenTQj6OfCl9FMR2jlMJjtMrtQT9InQEE7m3m7bLHeC+MCJOhmNVBjaM +ZpthDORdxIZ6oCuOf6Z2+Dl35lntGFh5J7S34UP2BWzF1IyyQfySCNexGNHKT1G1 +XKQtHmtc2gWWthEg+S6ciIyw2IGrrP2Rke81vYHExPrexf0hAkEA9Izb0MiYsMCB +/jemLJB0Lb3Y/B8xjGjQFFBQT7bmwBVjvZWZVpnMnXi9sWGdgUpxsCuAIROXjZ40 +IRZ2C9EouwJBAOPjPvV8Sgw4vaseOqlJvSq/C/pIFx6RVznDGlc8bRg7SgTPpjHG +4G+M3mVgpCX1a/EU1mB+fhiJ2LAZ/pTtY6sCQGaW9NwIWu3DRIVGCSMm0mYh/3X9 +DAcwLSJoctiODQ1Fq9rreDE5QfpJnaJdJfsIJNtX1F+L3YceeBXtW0Ynz2MCQBI8 +9KP274Is5FkWkUFNKnuKUK4WKOuEXEO+LpR+vIhs7k6WQ8nGDd4/mujoJBr5mkrw +DPwqA3N5TMNDQVGv8gMCQQCaKGJgWYgvo3/milFfImbp+m7/Y3vCptarldXrYQWO +AQjxwc71ZGBFDITYvdgJM1MTqc8xQek1FXn1vfpy2c6O +-----END RSA PRIVATE KEY----- +`) + +var publicKey = []byte(` +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZsfv1qscqYdy4vY+P4e3cAtmv +ppXQcRvrF1cB4drkv0haU24Y7m5qYtT52Kr539RdbKKdLAM6s20lWy7+5C0Dgacd +wYWd/7PeCELyEipZJL07Vro7Ate8Bfjya+wltGK9+XNUIHiumUKULW4KDx21+1NL +AUeJ6PeW+DAkmJWF6QIDAQAB +-----END PUBLIC KEY----- +`) diff --git a/encrypt/sha.go b/encrypt/sha.go new file mode 100644 index 0000000..af2104f --- /dev/null +++ b/encrypt/sha.go @@ -0,0 +1,33 @@ +package encrypt + +import ( + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "fmt" + "io" +) + +// Sha1 加密 +func Sha1(str string) string { + data := []byte(str) + has := sha1.Sum(data) + return fmt.Sprintf("%x", has) +} + +// Sha256 加密 +func Sha256(str string) string { + w := sha256.New() + io.WriteString(w, str) + bw := w.Sum(nil) + return hex.EncodeToString(bw) +} + +// Sha512 加密 +func Sha512(str string) string { + w := sha512.New() + io.WriteString(w, str) + bw := w.Sum(nil) + return hex.EncodeToString(bw) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..fbff08f --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/zhang2092/go-encrpyt + +go 1.20 + +require golang.org/x/crypto v0.7.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..28865b0 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=