mirror of https://gitee.com/godoos/godoos.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
319 lines
8.3 KiB
319 lines
8.3 KiB
package libs
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"crypto/md5"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"strings"
|
|
)
|
|
|
|
func GetEncryptedCode(data string) (string, error) {
|
|
// 检查是否以 @ 开头
|
|
if !strings.HasPrefix(data, "@") {
|
|
return "", fmt.Errorf("invalid input format")
|
|
}
|
|
// 去掉开头的 @
|
|
data = data[1:]
|
|
// 分割加密的私钥和加密的文本
|
|
parts := strings.SplitN(data, "@", 2)
|
|
if len(parts) != 2 {
|
|
return "", fmt.Errorf("invalid input format")
|
|
}
|
|
return parts[0], nil
|
|
}
|
|
func IsEncryptedFile(data string) bool {
|
|
if len(data) < 2 {
|
|
return false
|
|
}
|
|
// 检查是否以 @ 开头
|
|
if !strings.HasPrefix(data, "@") {
|
|
return false
|
|
}
|
|
// 去掉开头的 @
|
|
data = data[1:]
|
|
// 分割加密的私钥和加密的文本
|
|
parts := strings.SplitN(data, "@", 2)
|
|
if len(parts) != 2 {
|
|
return false
|
|
}
|
|
// 检查加密私钥和加密文本是否都不为空
|
|
hexEncodedPrivateKey := parts[0]
|
|
// 检查十六进制字符串是否有效
|
|
base64Str, err := hex.DecodeString(hexEncodedPrivateKey)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
// 尝试将 Base64 字符串解码为字节切片
|
|
_, err = base64.URLEncoding.DecodeString(string(base64Str))
|
|
return err == nil
|
|
}
|
|
|
|
// EncodeFile 加密文件
|
|
func EncodeFile(password string, longText string) (string, error) {
|
|
privateKey, publicKey, err := GenerateRSAKeyPair(1024)
|
|
if err != nil {
|
|
fmt.Println("生成RSA密钥对失败:", err)
|
|
return "", err
|
|
}
|
|
// 使用公钥加密
|
|
encryptedText := ""
|
|
if len(longText) > 0 {
|
|
encryptedText, err = EncryptLongText(longText, publicKey)
|
|
if err != nil {
|
|
return "", fmt.Errorf("加密失败:%v", err)
|
|
}
|
|
}
|
|
|
|
pwd, err := hashAndMD5(password)
|
|
if err != nil {
|
|
return "", fmt.Errorf("加密密码失败:%v", err)
|
|
}
|
|
encryptedPrivateKey, err := EncryptPrivateKey(privateKey, pwd)
|
|
if err != nil {
|
|
fmt.Println("加密私钥失败:", err)
|
|
return "", fmt.Errorf("加密私钥失败")
|
|
}
|
|
|
|
// 对 encryptedPrivateKey 进行 Base64 编码
|
|
base64EncryptedPrivateKey := base64.URLEncoding.EncodeToString([]byte(encryptedPrivateKey))
|
|
|
|
// 将 Base64 编码后的字符串转换为十六进制字符串
|
|
hexEncodedPrivateKey := hex.EncodeToString([]byte(base64EncryptedPrivateKey))
|
|
|
|
return "@" + hexEncodedPrivateKey + "@" + encryptedText, nil
|
|
}
|
|
|
|
// DecodeFile 解密文件
|
|
func DecodeFile(password string, encryptedData string) (string, error) {
|
|
// 去掉开头的@
|
|
// log.Printf("encryptedData: %s", encryptedData)
|
|
if !strings.HasPrefix(encryptedData, "@") {
|
|
return "", fmt.Errorf("无效的加密数据格式")
|
|
}
|
|
encryptedData = encryptedData[1:]
|
|
|
|
// 分割加密的私钥和加密的文本
|
|
parts := strings.SplitN(encryptedData, "@", 2)
|
|
log.Printf("parts:%v", parts)
|
|
if len(parts) == 1 {
|
|
return "", nil
|
|
}
|
|
if len(parts) != 2 {
|
|
return "", fmt.Errorf("无效的加密数据格式")
|
|
}
|
|
|
|
hexEncodedPrivateKey := parts[0]
|
|
encryptedText := parts[1]
|
|
if len(encryptedText) == 0 {
|
|
return "", nil
|
|
}
|
|
|
|
// 将十六进制字符串转换回 Base64 编码字符串
|
|
base64DecodedPrivateKey, err := hex.DecodeString(hexEncodedPrivateKey)
|
|
if err != nil {
|
|
return "", fmt.Errorf("十六进制字符串解码失败:%v", err)
|
|
}
|
|
|
|
// 将 Base64 编码字符串解码回原始的 encryptedPrivateKey
|
|
encryptedPrivateKey, err := base64.URLEncoding.DecodeString(string(base64DecodedPrivateKey))
|
|
if err != nil {
|
|
return "", fmt.Errorf("Base64字符串解码失败:%v", err)
|
|
}
|
|
|
|
pwd, err := hashAndMD5(password)
|
|
if err != nil {
|
|
return "", fmt.Errorf("加密密码失败:%v", err)
|
|
}
|
|
|
|
// 解密私钥
|
|
privateKey, err := DecryptPrivateKey(string(encryptedPrivateKey), pwd)
|
|
if err != nil {
|
|
return "", fmt.Errorf("解密私钥失败:%v", err)
|
|
}
|
|
|
|
// 解密文本
|
|
decryptedText, err := DecryptLongText(encryptedText, privateKey)
|
|
if err != nil {
|
|
return "", fmt.Errorf("解密文本失败:%v", err)
|
|
}
|
|
|
|
return decryptedText, nil
|
|
}
|
|
|
|
// GenerateRSAKeyPair 生成RSA密钥对
|
|
func GenerateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
|
|
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
publicKey := &privateKey.PublicKey
|
|
|
|
return privateKey, publicKey, nil
|
|
}
|
|
func GenertePrivateKey(password string, privateKey *rsa.PrivateKey) (*rsa.PrivateKey, error) {
|
|
encryptedPrivateKey, err := EncryptPrivateKey(privateKey, password)
|
|
if err != nil {
|
|
fmt.Println("加密私钥失败:", err)
|
|
return nil, fmt.Errorf("加密私钥失败")
|
|
}
|
|
decryptedPrivateKey, err := DecryptPrivateKey(encryptedPrivateKey, password)
|
|
if err != nil {
|
|
fmt.Println("解密私钥失败:", err)
|
|
return nil, fmt.Errorf("加密私钥失败")
|
|
}
|
|
return decryptedPrivateKey, nil
|
|
}
|
|
|
|
// EncryptWithPublicKey 使用公钥加密数据
|
|
func EncryptWithPublicKey(data []byte, publicKey *rsa.PublicKey) (string, error) {
|
|
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, publicKey, data, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return base64.URLEncoding.EncodeToString(ciphertext), nil
|
|
}
|
|
|
|
// DecryptWithPrivateKey 使用私钥解密数据
|
|
func DecryptWithPrivateKey(encryptedData string, privateKey *rsa.PrivateKey) ([]byte, error) {
|
|
ciphertext, err := base64.URLEncoding.DecodeString(encryptedData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privateKey, ciphertext, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return plaintext, nil
|
|
}
|
|
|
|
// hashAndMD5 使用 MD5 哈希密码
|
|
func hashAndMD5(password string) (string, error) {
|
|
hasher := md5.New()
|
|
_, err := hasher.Write([]byte(password))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(hasher.Sum(nil)), nil
|
|
}
|
|
|
|
// EncryptLongText 使用公钥加密长文本
|
|
func EncryptLongText(longText string, publicKey *rsa.PublicKey) (string, error) {
|
|
// 分块加密
|
|
blockSize := publicKey.N.BitLen()/8 - 2*sha256.Size - 2
|
|
chunks := splitIntoChunks([]byte(longText), blockSize)
|
|
|
|
var encryptedChunks []string
|
|
for _, chunk := range chunks {
|
|
encryptedChunk, err := EncryptWithPublicKey(chunk, publicKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
encryptedChunks = append(encryptedChunks, encryptedChunk)
|
|
}
|
|
|
|
return strings.Join(encryptedChunks, ":"), nil
|
|
}
|
|
|
|
// DecryptLongText 使用私钥解密长文本
|
|
func DecryptLongText(encryptedLongText string, privateKey *rsa.PrivateKey) (string, error) {
|
|
// 分块解密
|
|
encryptedChunks := strings.Split(encryptedLongText, ":")
|
|
|
|
var decryptedChunks [][]byte
|
|
for _, encryptedChunk := range encryptedChunks {
|
|
decryptedChunk, err := DecryptWithPrivateKey(encryptedChunk, privateKey)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
decryptedChunks = append(decryptedChunks, decryptedChunk)
|
|
}
|
|
|
|
return string(bytes.Join(decryptedChunks, nil)), nil
|
|
}
|
|
|
|
// splitIntoChunks 将数据分割成指定大小的块
|
|
func splitIntoChunks(data []byte, chunkSize int) [][]byte {
|
|
var chunks [][]byte
|
|
for i := 0; i < len(data); i += chunkSize {
|
|
end := i + chunkSize
|
|
if end > len(data) {
|
|
end = len(data)
|
|
}
|
|
chunks = append(chunks, data[i:end])
|
|
}
|
|
return chunks
|
|
}
|
|
|
|
// EncryptPrivateKey 使用AES加密RSA私钥
|
|
func EncryptPrivateKey(privateKey *rsa.PrivateKey, password string) (string, error) {
|
|
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
|
|
key := []byte(password)
|
|
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
gcm, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
nonce := make([]byte, gcm.NonceSize())
|
|
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
ciphertext := gcm.Seal(nonce, nonce, privateKeyBytes, nil)
|
|
return base64.URLEncoding.EncodeToString(ciphertext), nil
|
|
}
|
|
|
|
// DecryptPrivateKey 使用AES解密RSA私钥
|
|
func DecryptPrivateKey(encryptedPrivateKey string, password string) (*rsa.PrivateKey, error) {
|
|
ciphertext, err := base64.URLEncoding.DecodeString(encryptedPrivateKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
key := []byte(password)
|
|
|
|
block, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
gcm, err := cipher.NewGCM(block)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nonceSize := gcm.NonceSize()
|
|
if len(ciphertext) < nonceSize {
|
|
return nil, fmt.Errorf("ciphertext too short")
|
|
}
|
|
|
|
nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:]
|
|
privateKeyBytes, err := gcm.Open(nil, nonce, ciphertext, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return privateKey, nil
|
|
}
|
|
|