今天接了个内部外包需求,要接中广协的 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 271 天前 via Android 如果是想问为啥是公钥解密,硬想一个可以是用于认证这个数据是官方给出的 |
![]() | 3 ma46 271 天前 就字面意思啊, 用公钥来解密对方发来的数据, 如果你不知道公钥是什么就找对方要 |