package common import ( "bytes" "crypto/cipher" "crypto/des" "crypto/md5" "crypto/rand" "encoding/hex" "errors" "fmt" ) // PasswordUtil 对应 Java 类的常量 const ( // DefaultSalt 对应 Java 中的 SALT = "63293188" DefaultSalt = "63293188" // IterationCount 对应 Java 中的 ITERATIONCOUNT = 1000 IterationCount = 1000 ) // GetSalt 生成 8 字节的随机盐 func GetSalt() ([]byte, error) { salt := make([]byte, 8) _, err := rand.Read(salt) if err != nil { return nil, err } return salt, nil } // GetStaticSalt 获取静态盐 func GetStaticSalt() []byte { return []byte(DefaultSalt) } // Encrypt 加密 // plaintext: 明文 // password: 密码 // salt: 盐 (传入 string, 对应 Java 的 salt 参数) func Encrypt(plaintext, password, salt string) (string, error) { // 1. 生成 Key 和 IV key, iv := deriveKeyAndIV(password, salt, IterationCount) // 2. 创建 DES Cipher block, err := des.NewCipher(key) if err != nil { return "", err } // 3. 处理数据 (UTF-8 转 bytes 并填充) data := []byte(plaintext) data = pkcs5Padding(data, block.BlockSize()) // 4. 加密 (CBC 模式) blockMode := cipher.NewCBCEncrypter(block, iv) crypted := make([]byte, len(data)) blockMode.CryptBlocks(crypted, data) // 5. 转十六进制字符串 (对应 Java 的 bytesToHexString) // Java 的 Integer.toHexString 产生的是小写,这里保持一致, // 但通常十六进制可以互通。 return hex.EncodeToString(crypted), nil } // Decrypt 解密 // ciphertext: 密文 (Hex 字符串) // password: 密码 // salt: 盐 func Decrypt(ciphertext, password, salt string) (string, error) { // 1. 生成 Key 和 IV key, iv := deriveKeyAndIV(password, salt, IterationCount) // 2. Hex 字符串转 bytes decodedBytes, err := hex.DecodeString(ciphertext) if err != nil { return "", err } // 3. 创建 DES Cipher block, err := des.NewCipher(key) if err != nil { return "", err } // 4. 解密 (CBC 模式) blockMode := cipher.NewCBCDecrypter(block, iv) // 密文长度检查 if len(decodedBytes)%block.BlockSize() != 0 { return "", errors.New("ciphertext is not a multiple of the block size") } origData := make([]byte, len(decodedBytes)) blockMode.CryptBlocks(origData, decodedBytes) // 5. 去除填充 origData, err = pkcs5UnPadding(origData) if err != nil { return "", err } return string(origData), nil } // deriveKeyAndIV 模拟 Java PBEWithMD5AndDES 的密钥派生逻辑 // 逻辑:MD5(password || salt) -> 迭代 -> 结果前8字节是Key,后8字节是IV func deriveKeyAndIV(password, salt string, iterations int) ([]byte, []byte) { // Java PBEKeySpec 处理 password 为 char[],通常转 byte 时依赖编码, // 此处假设使用 UTF-8 兼容(Java 默认行为通常如此,或者 ASCII) passBytes := []byte(password) saltBytes := []byte(salt) // 第一次迭代: Hash(pass + salt) hash := md5.New() hash.Write(passBytes) hash.Write(saltBytes) derived := hash.Sum(nil) // 后续迭代: Hash(prev_hash) for i := 1; i < iterations; i++ { hash.Reset() hash.Write(derived) derived = hash.Sum(nil) } // MD5 结果是 16 字节 // DES Key 需要 8 字节,IV 需要 8 字节 // 正好平分 key := derived[:8] iv := derived[8:] return key, iv } // pkcs5Padding 填充 func pkcs5Padding(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...) } // pkcs5UnPadding 去除填充 func pkcs5UnPadding(origData []byte) ([]byte, error) { length := len(origData) if length == 0 { return nil, errors.New("decryption error: output length is zero") } unpadding := int(origData[length-1]) if length < unpadding { return nil, errors.New("decryption error: invalid padding") } return origData[:(length - unpadding)], nil } // --- 测试主函数 --- func main() { // 测试数据 plaintext := "admin" password := "Wang5322570" //salt := DefaultSalt salt := "RCGTeGiH" fmt.Println("原文:", plaintext) fmt.Println("密码:", password) fmt.Println("盐值:", salt) // 加密 encrypted, err := Encrypt(plaintext, password, salt) if err != nil { fmt.Println("加密失败:", err) return } // Java代码可能输出小写或手动处理,这里使用 hex.EncodeToString (小写) // 如果需要大写可以使用 strings.ToUpper(encrypted) fmt.Println("加密密文 (Hex):", encrypted) // 解密 decrypted, err := Decrypt(encrypted, password, salt) if err != nil { fmt.Println("解密失败:", err) return } fmt.Println("解密原文:", decrypted) // 验证一致性 if plaintext == decrypted { fmt.Println(">> 测试通过!Go版本与逻辑一致。") } else { fmt.Println(">> 测试失败!") } }