跳过正文

golang base64编解码问题

·398 字
tech Go

由于业务需要,go 服务需要调用 java 服务接口,其中需要对参数进行 base64 编解码

encoded := base64.URLEncoding.EncodeToString(data)

java 侧错误日志如下,提示 base64 字符串末尾有无效字符

org.bouncycastle.util.encoders.DecoderException: exception decoding URL safe base64 string: invalid characters encountered at end of base64 data

切换为 base64.RawURLEncoding 编码后,报错如下,提示字符串长度错误

org.bouncycastle.util.encoders.DecoderException: exception decoding URL safe base64 string: 107

BouncyCastle base64 编码与 go 的对比

特性Java BouncyCastle UrlBase64Go
替换 + 为 -自动处理base64.URLEncoding 自动处理
替换 / 为 _自动处理base64.URLEncoding 自动处理
填充符号“.“作为填充符号base64.URLEncoding 默认”=“作为填充符号
换行处理无换行默认无换行
解码灵活性严格RawURLEncoding 处理无填充情况

go URLEncoding 与 RawURLEncoding 区别

特性URLEncodingRawURLEncoding
填充字符使用 = 填充不使用填充
输出长度总是 4 的倍数(因为有填充)可能不是 4 的倍数(无填充)
兼容性与标准 Base64 解码器兼容更好更紧凑,但可能不兼容某些解码器

base64.URLEncoding.WithPadding(base64.NoPadding) 与 base64.RawURLEncoding 效果一样

原来 java bouncycastle 库中 base64 编码是带填充的,会以.符号进行填充,所以 go 服务应该带填充的方式进行编解码

package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    // 编码
    data := []byte("Hello, World!")
    encoded := base64.URLEncoding.WithPadding('.').EncodeToString(data)
    fmt.Println("Encoded:", encoded)
    // 解码
    decoded, err := base64.URLEncoding.WithPadding('.').DecodeString(encoded)
    if err != nil {
        fmt.Println("Error decoding:", err)
        return
    }
    fmt.Println("Decoded:", string(decoded))
}