解决 PHP & JAVA 使用 SHA512 配合 Base64 签名不一致的问题
本文最后更新于:2023年4月25日 晚上
描述
最近女朋友对接的 OpenAPI 是使用 SHA512 加密 + Base64 编码的签名进行鉴权,Demo 是用 JAVA 写的,PHP 得到的签名总是和 JAVA Demo 得到的不一致
问题分析
- 首先,字符串是固定顺序拼接的,所以不存在排序问题。
- 个人用 Go 语言实现了一下,结果与 JAVA 一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14package main
import (
"crypto/sha512"
"encoding/base64"
"fmt"
)
func main() {
s := `example str`
h := sha512.New()
h.Write([]byte(s))
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h.Sum(nil)))
} - 首先排查下是不是 PHP SHA512 的问题,先用 PHP 进行 SHA512 然后和 Go 进行 SHA512 得到的计算结果对比,结果一致
排除掉 sha512 加密方法本身的问题
- 使用 Go 直接进行 Base64 编码 SHA512 加密的字符串,发现结果和 PHP 一致
排除掉 Base64 编码方法本身的问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package main
import (
"crypto/sha512"
"encoding/base64"
"fmt"
)
func main() {
s := `example str`
h := sha512.New()
h.Write([]byte(s))
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(h.Sum(nil)))
// 这个字符串是 SHA512 加密后打印出来的
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString([]byte("8c4e3bb6304fa823b33dd008fb1bb5e9f400f0fad03870b5f248a9158f5cb4e4e5eca10b4f490d43590a2138886ca5a066ff27ba41c1b19dd7629175b9b01eca")))
}
问题原因
PHP 本身的 SHA512 和 Base64 都没有问题,但是由于 PHP 没有 byte 类型导致进行 SHA512 加密之后会把字符串编码成 16 进制用于显示,这时候对编码成 16 进制的字符串在进行 Base64 ,签名肯定是不一致的,所以需要进行 hex2bin 解码之后再进行签名。
解决方案实现
1 |
|
解决 PHP & JAVA 使用 SHA512 配合 Base64 签名不一致的问题
https://agopher.com/2020/09/24/tech/2020_sign/