You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复Go语言自定义Base64风格编码解码器的不匹配问题

自定义Base64风格编解码器的修复方案

问题背景

现有一个不可修改的Go语言自定义编码器(类似Base64),需要修复配套解码器,使其能正确还原原始输入字节。

给定的编码器代码

func shuffle(input rune) rune {
    return input + 59
}

func customEncode(input []byte) string {
    inputLen := len(input)
    output := make([]rune, 0, inputLen*4/3*4)

    for i := 0; i < inputLen; i += 3 {
        chunk := uint32(0)
        for j := 0; j < 3; j++ {
            if i+j < inputLen {
                chunk |= uint32(input[i+j]) << (8 * (2 - j))
            }
        }

        for shift := 18; shift >= 0; shift -= 6 {
            group := (chunk >> shift) & 63
            output = append(output, shuffle(rune(group)))
        }
    }

    switch inputLen % 3 {
    case 1:
        output = output[:len(output)-2]
    case 2:
        output = output[:len(output)-1]
    }

    return string(output)
}

当前错误的解码器代码

func unshuffle(input rune) rune {
    switch {
    case input > 96:
        return input - 59
    case input > 64:
        return input - 53
    case input > 47:
        return input - 46
    default:
        return input - 45
    }
}

func customDecode(encoded string) []byte {
    output := make([]byte, 0, len(encoded))
    for i := 0; i < len(encoded); i += 4 {
        chunk := uint32(0)
        for j := 0; j < 4 && i+j < len(encoded); j++ {
            chunk |= uint32(unshuffle(rune(encoded[i+j]))) << (18 - j*6)
        }

        output = append(output,
            byte((chunk>>16)&0xFF),
            byte((chunk>>8)&0xFF),
            byte(chunk&0xFF),
        )
    }
    
    if len(encoded)%4 == 3 {
        output = output[:len(output)-1]
    } else if len(encoded)%4 == 2 {
        output = output[:len(output)-2]
    }

    return output
}

测试代码及错误结果

func TestEncoding(t *testing.T) {
    input := "Lorem ipsum"
    encoded := customEncode([]byte(input))

    decoded := customDecode(encoded)

    fmt.Println(fmt.Sprintf("Encoded: %s", encoded))

    fmt.Println([]byte(input))
    fmt.Println(decoded)
    if !bytes.Equal([]byte(input), decoded) {
        t.Fail()
    }
}

// 错误输出:
// Encoded: [符合group+59规则的字符串,而非测试中给出的H4xmNKoUOL_nRKo]
// [76 111 114 101 109 32 105 112 115 117 109]
// [76 111 114 101 109 32 105 122 179 117 109]

错误原因分析

核心问题是**unshuffle函数与编码器的shuffle逻辑不匹配**:
编码器的shuffle是直接将0-63的group值加59,而当前解码器的unshuffle错误地分情况减去不同数值,导致group值还原错误,进而生成错误的原始字节。

此外,输出切片的初始容量预估不合理,可优化为更符合Base64类编码的比例。


修改后的解码器代码

func unshuffle(input rune) rune {
    // 与编码器shuffle完全逆操作:直接减59
    return input - 59
}

func customDecode(encoded string) []byte {
    // 优化初始容量:4个编码字符对应3个原始字节
    output := make([]byte, 0, len(encoded)*3/4)
    for i := 0; i < len(encoded); i += 4 {
        chunk := uint32(0)
        for j := 0; j < 4 && i+j < len(encoded); j++ {
            group := unshuffle(rune(encoded[i+j]))
            // 对应编码器的shift顺序:18,12,6,0
            chunk |= uint32(group) << (18 - j*6)
        }

        // 提取三个原始字节
        output = append(output,
            byte((chunk>>16)&0xFF),
            byte((chunk>>8)&0xFF),
            byte(chunk&0xFF),
        )
    }
    
    // 根据编码长度调整输出,与编码器逻辑对应
    switch len(encoded) % 4 {
    case 2:
        // 对应输入长度%3=1,解码后去掉最后2个无效字节
        output = output[:len(output)-2]
    case 3:
        // 对应输入长度%3=2,解码后去掉最后1个无效字节
        output = output[:len(output)-1]
    }

    return output
}

修改说明

  1. 修复unshuffle逻辑:直接返回input-59,与编码器的shuffle函数完全对应,确保group值正确还原。
  2. 优化初始容量:使用len(encoded)*3/4作为输出切片的初始容量,更贴合编码比例,减少内存扩容开销。
  3. 保留正确的移位与长度调整逻辑:这部分逻辑原本与编码器匹配,无需修改。

修改后,解码器可正确还原所有输入字节,测试将通过。

注:当前测试中给出的Encoded字符串(H4xmNKoUOL_nRKo)与给定的编码器代码不兼容(包含小于59的ASCII字符,无法通过group+59生成),推测是混淆了不同版本的编码器代码,需以给定的编码器代码为准进行测试。

内容的提问来源于stack exchange,提问作者Jake Evans

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:04:50