今天接了个内部外包需求,要接中广协的 CAID 。
看了半天没看懂文档里对返回内容用“公钥解密”是什么意思,网络上也没搜到太多信息, 所以把处理方式共享下。
文档里面的例子是 JAVA ,我实现的逻辑是 Go ,关键信息来自 https://stackoverflow.com/questions/68984685/go-rsa-decrypt-using-public-key-implementation-from-java
package caid
import (
"bytes"
"crypto/rsa"
"encoding/base64"
"errors"
"fmt"
"io"
"log"
"math/big"
)
func decrypt(data string) ([]byte, error) {
raw, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, fmt.Errorf("base64 decode %w: %s", err, data)
}
reader := bytes.NewReader(raw)
var writer bytes.Buffer
chunk := make([]byte, maxDecryptBlock)
for {
n, err := io.ReadFull(reader, chunk)
if err != nil && errors.Is(err, io.ErrUnexpectedEOF) {
return nil, fmt.Errorf("read decrypted data: %w", err)
}
if n == 0 {
break
}
decryptChunk(chunk, &writer, pubKey)
}
output := bytes.TrimRight(bytes.TrimLeft(writer.Bytes(), "\x00"), "\n")
if bytes.Count(output, []byte("\x00")) > 0 {
after := bytes.ReplaceAll(output, []byte("\x00"), []byte{})
log.Println("WARN: remove \x00 from caid's response", "before", output, "after", after)
output = after
}
return output, nil
}
func decryptChunk(chunk []byte, writer *bytes.Buffer, pubKey *rsa.PublicKey) {
// Decrypt each signature chunk
ciphertextInt := new(big.Int)
ciphertextInt.SetBytes(chunk)
decryptedPaddedInt := doDecrypt(new(big.Int), pubKey, ciphertextInt)
// Remove padding
decryptedPaddedBytes := make([]byte, pubKey.Size())
decryptedPaddedInt.FillBytes(decryptedPaddedBytes)
start := bytes.Index(decryptedPaddedBytes[1:], []byte{0}) + 1 // // 0001FF...FF00<data>: Find index after 2nd 0x00
decryptedBytes := decryptedPaddedBytes[start:]
// Write decrypted signature chunk
writer.Write(decryptedBytes)
}
func doDecrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int {
// Textbook RSA
e := big.NewInt(int64(pub.E))
c.Exp(m, e, pub.N)
return c
}
1
pandaex 5 天前 via Android
如果是想问为啥是公钥解密,硬想一个可以是用于认证这个数据是官方给出的
|
3
ma46 5 天前
就字面意思啊, 用公钥来解密对方发来的数据, 如果你不知道公钥是什么就找对方要
|
4
sagaxu 5 天前 1
公钥加密,私钥解密。私钥签名,公钥验签。签名是确保发送人不被伪造,加密是为了防止被中间人攻击嗅探数据。
在强安全场景,加密和签名经常一起用。我们也经常看到用非对称加密打包对称加密的密码,提高安全性的同时,减小计算压力,如 SSL 。 如果同时写 Java 和 Go ,一定会遇到 PKCS1 和 PKCS8 格式差异。 |
5
yankebupt 5 天前
虽然公钥是公开的所以私钥处理后并不会赋予秘密属性,但你就说是不是解密算法吧……( doge
|
6
ZRS 5 天前
可以,但比较脱裤子放屁,就当是混淆传输吧
|
7
jocover 5 天前
就是把 d 和 e 换下就行了
// mpz_powm(ct, pt, e, n);//公钥加密 mpz_powm(ct, pt, d, n);//私钥加密 gmp_printf("Encoded: %Zx\n", ct); // mpz_powm(pt, ct, d, n); //私钥解密 mpz_powm(pt, ct, e, n); //公钥解密 gmp_printf("Decoded: %Zx\n", pt); |
8
murmur 4 天前
@ZRS 这是商密还是等保 3 的要求,我也既不清楚了,要求 api 接口不能露路径,body 和 request 都是加密传输
就是类似所有的接口都是/api/entry ,如果碰到什么/user/info 就算你没加密全 |
9
marvin001 3 天前
我测试好像还是不行
|