diff --git a/aufs/crypto/example.go b/aufs/crypto/example.go new file mode 100644 index 0000000..b3a984e --- /dev/null +++ b/aufs/crypto/example.go @@ -0,0 +1,101 @@ +package crypto + +import ( + "fmt" + "os" +) + +// 示例:生成密钥对并存入文件 +func ExampleGenerateAndSaveKeys() { + // 密钥位数 + bits := 2048 + // 用户密码(实际应用中应该从用户输入获取) + password := "your_secure_password" + // 密钥文件保存路径 + privateKeyPath := "private.pem" + publicKeyPath := "public.pem" + + // 生成并保存密钥对 + err := GenerateAndSaveKeysWithPassword(bits, password, privateKeyPath, publicKeyPath) + if err != nil { + fmt.Printf("生成密钥失败: %v\n", err) + return + } + + fmt.Println("密钥生成和保存成功!") +} + +// 示例:读取并解密私钥 +func ExampleReadAndDecryptPrivateKey() { + // 密码和文件路径 + password := "your_secure_password" + privateKeyPath := "private.pem" + + // 读取加密的私钥文件 + data, err := os.ReadFile(privateKeyPath) + if err != nil { + fmt.Printf("读取私钥文件失败: %v\n", err) + return + } + + // 解密私钥 + privateKey, err := DecryptPrivateKey(data, password) + if err != nil { + fmt.Printf("解密私钥失败: %v\n", err) + return + } + + fmt.Println("私钥解密成功!") + fmt.Printf("私钥模数长度: %d 位\n", privateKey.N.BitLen()) +} + +// 主函数示例(如果单独运行这个文件) +func ExampleMain() { + // 生成密钥对 + ExampleGenerateAndSaveKeys() + + // 读取并解密私钥 + ExampleReadAndDecryptPrivateKey() +} + +/* +使用说明: + +1. 生成密钥对: + - 调用GenerateAndSaveKeysWithPassword函数 + - 参数:密钥位数(通常2048或4096)、保护私钥的密码、私钥保存路径、公钥保存路径 + +2. 读取并解密私钥: + - 读取私钥文件 + - 调用DecryptPrivateKey函数用密码解密 + +3. 注意事项: + - 密码应足够复杂且安全存储 + - 私钥文件应妥善保管,建议设置严格的文件权限 + - 密钥位数推荐使用2048位以上以保证安全性 + +示例代码: + +package main + +import ( + "fmt" + "your_project/crypto" +) + +func main() { + // 生成密钥对 + bits := 2048 + password := "your_secure_password" + privateKeyPath := "private.pem" + publicKeyPath := "public.pem" + + err := crypto.GenerateAndSaveKeysWithPassword(bits, password, privateKeyPath, publicKeyPath) + if err != nil { + fmt.Printf("错误: %v\n", err) + return + } + + fmt.Println("密钥生成完成!") +} +*/ \ No newline at end of file diff --git a/aufs/crypto/keygen.go b/aufs/crypto/keygen.go new file mode 100644 index 0000000..67be519 --- /dev/null +++ b/aufs/crypto/keygen.go @@ -0,0 +1,190 @@ +package crypto + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "errors" + "fmt" + "golang.org/x/crypto/bcrypt" + "os" +) + +// KeyPair 表示生成的密钥对 +type KeyPair struct { + PrivateKey *rsa.PrivateKey + PublicKey *rsa.PublicKey +} + +// GenerateRSAKeyPair 生成指定位数的RSA密钥对 +func GenerateRSAKeyPair(bits int) (*KeyPair, error) { + // 生成RSA私钥 + privateKey, err := rsa.GenerateKey(rand.Reader, bits) + if err != nil { + return nil, fmt.Errorf("生成RSA密钥失败: %v", err) + } + + // 验证私钥 + err = privateKey.Validate() + if err != nil { + return nil, fmt.Errorf("验证RSA密钥失败: %v", err) + } + + // 获取公钥 + publicKey := &privateKey.PublicKey + + return &KeyPair{ + PrivateKey: privateKey, + PublicKey: publicKey, + }, nil +} + +// EncryptPrivateKey 使用密码加密私钥 +func EncryptPrivateKey(privateKey *rsa.PrivateKey, password string) ([]byte, error) { + if password == "" { + return nil, errors.New("密码不能为空") + } + + // 将私钥转换为PKCS#1格式 + privDER := x509.MarshalPKCS1PrivateKey(privateKey) + + // 使用密码加密私钥 + block, err := x509.EncryptPEMBlock( + rand.Reader, + "RSA PRIVATE KEY", + privDER, + []byte(password), + x509.PEMCipherAES256, + ) + if err != nil { + return nil, fmt.Errorf("加密私钥失败: %v", err) + } + + // 将加密后的私钥转换为PEM格式 + encprivPEM := pem.EncodeToMemory(block) + + return encprivPEM, nil +} + +// ExportPublicKey 将公钥导出为PEM格式 +func ExportPublicKey(publicKey *rsa.PublicKey) ([]byte, error) { + // 将公钥转换为DER格式 + pubDER, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + return nil, fmt.Errorf("编码公钥失败: %v", err) + } + + // 创建PEM块 + block := &pem.Block{ + Type: "RSA PUBLIC KEY", + Bytes: pubDER, + } + + // 将公钥转换为PEM格式 + pubPEM := pem.EncodeToMemory(block) + + return pubPEM, nil +} + +// HashPassword 对密码进行哈希处理 +func HashPassword(password string) (string, error) { + hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return "", err + } + return string(hash), nil +} + +// CheckPasswordHash 验证密码是否与哈希值匹配 +func CheckPasswordHash(password, hash string) bool { + err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) + return err == nil +} + +// GenerateKeysWithPassword 生成加密的密钥对,返回公钥和加密后的私钥 +func GenerateKeysWithPassword(bits int, password string) (publicKeyPEM []byte, encryptedPrivateKeyPEM []byte, err error) { + // 生成密钥对 + keyPair, err := GenerateRSAKeyPair(bits) + if err != nil { + return nil, nil, err + } + + // 加密私钥 + encryptedPrivateKeyPEM, err = EncryptPrivateKey(keyPair.PrivateKey, password) + if err != nil { + return nil, nil, err + } + + // 导出公钥 + publicKeyPEM, err = ExportPublicKey(keyPair.PublicKey) + if err != nil { + return nil, nil, err + } + + return publicKeyPEM, encryptedPrivateKeyPEM, nil +} + +// DecryptPrivateKey 使用密码解密私钥 +func DecryptPrivateKey(encryptedPrivateKeyPEM []byte, password string) (*rsa.PrivateKey, error) { + if password == "" { + return nil, errors.New("密码不能为空") + } + + // 解码PEM块 + block, _ := pem.Decode(encryptedPrivateKeyPEM) + if block == nil { + return nil, errors.New("无法解码PEM块") + } + + // 解密私钥 + decryptedDER, err := x509.DecryptPEMBlock(block, []byte(password)) + if err != nil { + return nil, fmt.Errorf("解密私钥失败: %v", err) + } + + // 解析私钥 + privateKey, err := x509.ParsePKCS1PrivateKey(decryptedDER) + if err != nil { + return nil, fmt.Errorf("解析私钥失败: %v", err) + } + + return privateKey, nil +} + +// SaveKeyToFile 将密钥数据保存到指定文件 +func SaveKeyToFile(filePath string, keyData []byte) error { + // 写入文件 + err := os.WriteFile(filePath, keyData, 0600) // 仅用户可读写权限 + if err != nil { + return fmt.Errorf("保存密钥到文件失败: %v", err) + } + + fmt.Printf("密钥已成功保存到: %s\n", filePath) + return nil +} + +// GenerateAndSaveKeysWithPassword 生成密钥对并用密码保护私钥,然后保存到文件 +func GenerateAndSaveKeysWithPassword(bits int, password, privateKeyPath, publicKeyPath string) error { + // 生成密钥对 + publicKeyPEM, encryptedPrivateKeyPEM, err := GenerateKeysWithPassword(bits, password) + if err != nil { + return err + } + + // 保存公钥到文件 + err = SaveKeyToFile(publicKeyPath, publicKeyPEM) + if err != nil { + return err + } + + // 保存加密后的私钥到文件 + err = SaveKeyToFile(privateKeyPath, encryptedPrivateKeyPEM) + if err != nil { + return err + } + + fmt.Println("密钥对已成功生成并保存!") + return nil +} \ No newline at end of file diff --git a/aufs/main.go b/aufs/main.go index 6fe612c..a76975e 100644 --- a/aufs/main.go +++ b/aufs/main.go @@ -97,6 +97,8 @@ func main() { os.Exit(1) } + // 初始化 + // args 长度大于4 才有意思 if len(args) > 4 { config.G.Port = args[4]