问题描述
我正在围绕JWT的创建和验证编写一些单元和集成测试。我正在使用我使用openssl创建的真实(具有良好自签名)证书来共同整理一个快速的JWKS页面,我一直在做饭,直到找到一个非常简单的问题:
“ E”值为65537,但在JWKS中,假定为AQAB。经过很长时间在墙上敲打我的头,我终于在纸上弄清楚了。
https://tools.ietf.org/html/rfc7518#section-6.3.1.2
65537是 0000 0001:0000 0000:0000 0001
如果将base64的位数转换为6位,则会得到
000000 010000 000000 000001
哪个是A Q A B
https://en.wikipedia.org/wiki/Base64#Base64_table
因此,我尝试编写一些快速代码。但是事实证明这不是很迅速。我在想,一定有更简单的方法。我尝试的所有base64编码都给了我3个以上的字节。
任何有自尊心的编码器也会这样做...我看到每个人都使用65537,所以我对那个傻逼进行了硬编码,然后继续前进,但是它一直困扰着我。我讨厌让我烦恼的问题。
我最接近的是:
bs := make([]byte,4)
binary.BigEndian.PutUint32(bs,65537)
fmt.Println(bs)
fmt.Println(base64.URLEncoding.EncodetoString(bs))
哪个制作的:
[0 1 0 1]
AAEAAQ==
我的快速数学说的是,base64输出是为什么超过3个字节的原因:D
解决方法
您使用base64编码4个二进制字节:
bs := make([]byte,4) // `AAEAAQ==`
将会产生6(4*8/6
)个base64字符-加上==
填充。
您要编码三个二进制字节-这将产生4(3*8/6
)个base64字符。
bs := []byte{1,1}
fmt.Println(bs)
fmt.Println(base64.URLEncoding.EncodeToString(bs)) // `AQAB`
https://play.golang.org/p/gDviu06pftR
编辑
因此,您只需要低3个字节(如果使用BigEndian,则在最后)。
因此您可以使用原始代码:
bs := make([]byte,4)
binary.BigEndian.PutUint32(bs,65537)
bs = bs[1:] // drop most significant byte - leaving least-significant 3-bytes
fmt.Println(base64.URLEncoding.EncodeToString(bs)) // `AQAB`
或者,如果您查看binary.BigEndian.PutUint32的来源,您会发现它是如何从uint32
提取4个字节的-并对3个字节执行相同的操作:
bs := make([]byte,3)
v := 65537
bs[0] = byte(v >> 16)
bs[1] = byte(v >> 8)
bs[2] = byte(v)
fmt.Println(base64.URLEncoding.EncodeToString(bs)) // `AQAB`