You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
436 lines
12 KiB
436 lines
12 KiB
package main |
|
|
|
import ( |
|
"bytes" |
|
"crypto/rand" |
|
"crypto/rsa" |
|
"crypto/x509" |
|
"encoding/base64" |
|
"encoding/json" |
|
"encoding/pem" |
|
"errors" |
|
"fmt" |
|
"io" |
|
"io/ioutil" |
|
"log" |
|
"math/big" |
|
) |
|
|
|
const pubKeyBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCk2GwklLJO0m4Z5PffSSRlv7jNkQhFyoESukIu2duXN9YaC9G7SCQQnyHYs1Si/W4z/u5a4OXBE5+jZ9W9zmc1wfVelf2vnzTfKABA6AJhlsUXs2UjPQrxNRCgu4rALQ2TlbobqqLpIWtm5rqboXs3yJpRfgaLlJvAdihxx2XYQIDAQAB" |
|
const maxDecryptBlock = 256 |
|
|
|
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) |
|
} |
|
|
|
// 初始化ViewModel |
|
vm, err := NewViewModel() |
|
if err != nil { |
|
//log.Fatalf("初始化失败: %v", err) |
|
//} |
|
//// 初始化ViewModel |
|
//vm, err := NewViewModel(pubKeyBase64) |
|
//if err != nil { |
|
log.Printf("初始化失败: %v", err) |
|
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 |
|
} |
|
pubKey := vm.publicKey |
|
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 |
|
} |
|
|
|
// ViewModel 处理业务逻辑的视图模型 |
|
type ViewModel struct { |
|
publicKey *rsa.PublicKey |
|
privateKey *rsa.PrivateKey |
|
} |
|
|
|
// NewViewModel 初始化视图模型 |
|
func NewViewModel() (*ViewModel, error) { |
|
pubKeyBytes, err := ioutil.ReadFile("manifest/config/dev_10702/public_for_api.pem") |
|
if err != nil { |
|
fmt.Println(err) |
|
} |
|
fmt.Printf("pubKeyBytes: %s", pubKeyBytes) |
|
block, _ := pem.Decode(pubKeyBytes) |
|
if block != nil { |
|
pubKeyBytes = block.Bytes |
|
} |
|
fmt.Printf("pubKeyBytes: %s", fmt.Sprint(pubKeyBytes)) |
|
pubKey, err := x509.ParsePKIXPublicKey(pubKeyBytes) |
|
if err != nil { |
|
return nil, fmt.Errorf("解析公钥失败: %w", err) |
|
} |
|
rsaPubKey, ok := pubKey.(*rsa.PublicKey) |
|
if !ok { |
|
return nil, errors.New("无效的RSA公钥类型1") |
|
} |
|
priKeyBytes, err := ioutil.ReadFile("manifest/config/dev_10702/pkcs8_private.pem") |
|
if err != nil { |
|
fmt.Println(err) |
|
} |
|
fmt.Printf("priKeyBytes: %s", priKeyBytes) |
|
block1, _ := pem.Decode(priKeyBytes) |
|
if block1 != nil { |
|
priKeyBytes = block1.Bytes |
|
} |
|
fmt.Printf("priKeyBytes: %s", fmt.Sprint(priKeyBytes)) |
|
priKey, err := x509.ParsePKCS8PrivateKey(priKeyBytes) |
|
if err != nil { |
|
return nil, fmt.Errorf("解析私钥失败: %w", err) |
|
} |
|
|
|
rsaPriKey, ok := priKey.(*rsa.PrivateKey) |
|
if !ok { |
|
return nil, errors.New("无效的RSA私钥类型2") |
|
} |
|
|
|
return &ViewModel{publicKey: rsaPubKey, privateKey: rsaPriKey}, nil |
|
} |
|
|
|
// EncryptDeviceInfo 加密设备信息 |
|
func (vm *ViewModel) EncryptDeviceInfo(deviceInfo map[string]string) (string, error) { |
|
jsonData, err := json.Marshal(deviceInfo) |
|
if err != nil { |
|
return "", fmt.Errorf("JSON序列化失败: %w", err) |
|
} |
|
|
|
plaintext := string(jsonData) |
|
maxBlockSize := vm.publicKey.Size() - 11 // PKCS#1 v1.5填充最大块大小 |
|
var encryptedBlocks [][]byte |
|
|
|
for i := 0; i < len(plaintext); i += maxBlockSize { |
|
end := i + maxBlockSize |
|
if end > len(plaintext) { |
|
end = len(plaintext) |
|
} |
|
|
|
block := []byte(plaintext[i:end]) |
|
encryptedBlock, err := rsa.EncryptPKCS1v15(rand.Reader, vm.publicKey, block) |
|
if err != nil { |
|
return "", fmt.Errorf("RSA加密失败: %w", err) |
|
} |
|
encryptedBlocks = append(encryptedBlocks, encryptedBlock) |
|
} |
|
|
|
return base64.StdEncoding.EncodeToString(bytesJoin(encryptedBlocks)), nil |
|
} |
|
|
|
// DecryptResponse 解密响应数据 |
|
func (vm *ViewModel) DecryptResponse(ciphertextBase64 string) (string, error) { |
|
ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertextBase64) |
|
if err != nil { |
|
return "", fmt.Errorf("响应数据Base64解码失败: %w", err) |
|
} |
|
|
|
maxBlockSize := vm.privateKey.Size() |
|
var decryptedBlocks [][]byte |
|
|
|
for i := 0; i < len(ciphertextBytes); i += maxBlockSize { |
|
end := i + maxBlockSize |
|
if end > len(ciphertextBytes) { |
|
end = len(ciphertextBytes) |
|
} |
|
|
|
block := ciphertextBytes[i:end] |
|
decryptedBlock, err := rsa.DecryptPKCS1v15(rand.Reader, vm.privateKey, block) |
|
if err != nil { |
|
return "", fmt.Errorf("RSA解密失败: %w", err) |
|
} |
|
decryptedBlocks = append(decryptedBlocks, decryptedBlock) |
|
} |
|
|
|
return string(bytesJoin(decryptedBlocks)), nil |
|
} |
|
|
|
// 辅助函数:合并字节切片 |
|
func bytesJoin(s [][]byte) []byte { |
|
var totalLen int |
|
for _, b := range s { |
|
totalLen += len(b) |
|
} |
|
res := make([]byte, totalLen) |
|
for i, b := range s { |
|
copy(res[i:], b) |
|
} |
|
return res |
|
} |
|
|
|
func EncryptDeviceInfo() string { |
|
// 设备公共信息 |
|
deviceInfo := map[string]string{ |
|
"bootTimeInSec": "1595643553", |
|
"countryCode": "CN", |
|
"language": "zh-Hans-CN", |
|
"deviceName": "e910dddb2748c36b47fcde5dd720eec1", |
|
"systemVersion": "14.0", |
|
"machine": "iPhone10,3", |
|
"memory": "3955589120", |
|
"disk": "63900340224", |
|
"sysFileTime": "1595214620.383940", |
|
"model": "D22AP", |
|
"timeZone": "28800", |
|
"deviceInitTime": "1632467920.301150749", |
|
} |
|
|
|
// 初始化ViewModel |
|
vm, err := NewViewModel() |
|
if err != nil { |
|
log.Printf("初始化失败: %v", err) |
|
return "" |
|
} |
|
|
|
// 加密设备信息 |
|
encryptedDeviceInfo, err := vm.EncryptDeviceInfo(deviceInfo) |
|
if err != nil { |
|
log.Printf("设备信息加密失败: %v", err) |
|
return "" |
|
} |
|
fmt.Printf("加密设备信息: %s\n", encryptedDeviceInfo) |
|
|
|
// 模拟响应解密(使用加密结果模拟响应数据) |
|
//responseData := encryptedDeviceInfo // 实际应从接口获取encrypted_device_info字段 |
|
return encryptedDeviceInfo |
|
} |
|
|
|
func main() { |
|
// 设备公共信息 |
|
deviceInfo := map[string]string{ |
|
"bootTimeInSec": "1595643553", |
|
"countryCode": "CN", |
|
"language": "zh-Hans-CN", |
|
"deviceName": "e910dddb2748c36b47fcde5dd720eec1", |
|
"systemVersion": "14.0", |
|
"machine": "iPhone10,3", |
|
"memory": "3955589120", |
|
"disk": "63900340224", |
|
"sysFileTime": "1595214620.383940", |
|
"model": "D22AP", |
|
"timeZone": "28800", |
|
"deviceInitTime": "1632467920.301150749", |
|
} |
|
|
|
// 替换为实际公钥(需去除换行符) |
|
pubKeyBase64 := "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCk2GwklLJO0m4Z5PffSSRlv7jNkQhFyoESukIu2duXN9YaC9G7SCQQnyHYs1Si/W4z/u5a4OXBE5+jZ9W9zmc1wfVelf2vnzTfKABA6AJhlsUXs2UjPQrxNRCgu4rALQ2TlbobqqLpIWtm5rqboXs3yJpRfgaLlJvAdihxx2XYQIDAQAB" |
|
|
|
// 初始化ViewModel |
|
//vm, err := NewViewModel() |
|
//if err != nil { |
|
// log.Fatalf("初始化失败: %v", err) |
|
//} |
|
// |
|
//// 加密设备信息 |
|
//encryptedDeviceInfo, err := vm.EncryptDeviceInfo(deviceInfo) |
|
//if err != nil { |
|
// log.Fatalf("设备信息加密失败: %v", err) |
|
//} |
|
//fmt.Printf("加密设备信息: %s\n", encryptedDeviceInfo) |
|
// |
|
//// 模拟响应解密(使用加密结果模拟响应数据) |
|
//responseData := encryptedDeviceInfo // 实际应从接口获取encrypted_device_info字段 |
|
////decrypt(responseData) decrypt(responseData) // |
|
//// 解密响应数据 |
|
//decryptedData, err := vm.DecryptResponse(responseData) |
|
//if err != nil { |
|
// log.Fatalf("响应解密失败: %v", err) |
|
//} |
|
//fmt.Printf("解密后数据: %s\n", decryptedData) |
|
// |
|
//// 解析JSON数组(示例) |
|
//var caidsArray []interface{} |
|
//if err := json.Unmarshal([]byte(decryptedData), &caidsArray); err != nil { |
|
// log.Fatalf("JSON解析失败: %v", err) |
|
//} |
|
//fmt.Printf("CAIDs数组: %+v\n", caidsArray) |
|
//} |
|
|
|
// 公钥字符串,注意需要剔除换行符 |
|
PUBK := pubKeyBase64 // 分配的API接入的公钥字符串 |
|
// 序列化设备信息为JSON |
|
jsonBytes, err := json.Marshal(deviceInfo) |
|
if err != nil { |
|
fmt.Printf("JSON序列化错误: %v\n", err) |
|
return |
|
} |
|
jsonStr := string(jsonBytes) |
|
|
|
decrypt(jsonStr) |
|
fmt.Printf("PUBK: %s\n", PUBK) |
|
//// 加密设备信息 |
|
//encryptedDeviceInfo, err := encryptWithPublicKey(jsonStr, PUBK) |
|
//if err != nil { |
|
// fmt.Printf("加密错误: %v\n", err) |
|
// return |
|
//} |
|
// |
|
//fmt.Printf("加密后的设备信息: %s\n", encryptedDeviceInfo) |
|
//// 将encryptedDeviceInfo填入请求中的encrypted_device_info字段 |
|
// |
|
//// 解密响应数据示例 |
|
//// 假设从响应中获取的data字段值 |
|
//responseData := "" |
|
//decryptedData, err := decryptWithPrivateKey(responseData, PUBK) |
|
//if err != nil { |
|
// fmt.Printf("解密错误: %v\n", err) |
|
// return |
|
//} |
|
// |
|
//fmt.Printf("解密后的响应数据: %s\n", decryptedData) |
|
//// 解析为JSON数组 |
|
//var caidsArray []interface{} |
|
//if err := json.Unmarshal([]byte(decryptedData), &caidsArray); err != nil { |
|
// fmt.Printf("JSON解析错误: %v\n", err) |
|
// return |
|
//} |
|
//fmt.Printf("解析后的CAIDS数组: %v\n", caidsArray) |
|
} |
|
|
|
// 使用公钥加密数据 |
|
func encryptWithPublicKey(data string, pubKeyStr string) (string, error) { |
|
// 解码Base64格式的公钥 |
|
pubKeyBytes, err := base64.StdEncoding.DecodeString(pubKeyStr) |
|
if err != nil { |
|
return "", fmt.Errorf("公钥Base64解码错误: %v", err) |
|
} |
|
|
|
// 解析公钥 |
|
publicKey, err := x509.ParsePKIXPublicKey(pubKeyBytes) |
|
if err != nil { |
|
return "", fmt.Errorf("公钥解析错误: %v", err) |
|
} |
|
|
|
// 断言为RSA公钥 |
|
rsaPubKey, ok := publicKey.(*rsa.PublicKey) |
|
if !ok { |
|
return "", errors.New("不是RSA公钥") |
|
} |
|
|
|
// 计算最大加密块大小 |
|
maxEncryptBlock := rsaPubKey.Size() - 42 // PKCS#1 OAEP加密需要预留42字节 |
|
|
|
dataBytes := []byte(data) |
|
dataLen := len(dataBytes) |
|
var encryptedBytes []byte |
|
|
|
// 分段加密 |
|
for i := 0; i < dataLen; i += maxEncryptBlock { |
|
end := i + maxEncryptBlock |
|
if end > dataLen { |
|
end = dataLen |
|
} |
|
|
|
// 加密当前块 |
|
encryptedBlock, err := rsa.EncryptOAEP( |
|
nil, |
|
rand.Reader, |
|
rsaPubKey, |
|
dataBytes[i:end], |
|
nil, |
|
) |
|
if err != nil { |
|
return "", fmt.Errorf("加密错误: %v", err) |
|
} |
|
|
|
encryptedBytes = append(encryptedBytes, encryptedBlock...) |
|
} |
|
|
|
// Base64编码加密结果 |
|
return base64.StdEncoding.EncodeToString(encryptedBytes), nil |
|
} |
|
|
|
// 使用私钥解密数据(完整修正版函数) |
|
func decryptWithPrivateKey(encryptedData string, privKeyStr string) (string, error) { |
|
// 解码Base64格式的加密数据 |
|
encryptedBytes, err := base64.StdEncoding.DecodeString(encryptedData) |
|
if err != nil { |
|
return "", fmt.Errorf("加密数据Base64解码错误: %v", err) |
|
} |
|
|
|
// 解码Base64格式的私钥 |
|
privKeyBytes, err := base64.StdEncoding.DecodeString(privKeyStr) |
|
if err != nil { |
|
return "", fmt.Errorf("私钥Base64解码错误: %v", err) |
|
} |
|
|
|
// 解析私钥 |
|
privateKey, err := x509.ParsePKCS8PrivateKey(privKeyBytes) |
|
if err != nil { |
|
return "", fmt.Errorf("私钥解析错误: %v", err) |
|
} |
|
|
|
// 断言为RSA私钥 |
|
rsaPrivKey, ok := privateKey.(*rsa.PrivateKey) |
|
if !ok { |
|
return "", errors.New("不是RSA私钥") |
|
} |
|
|
|
// 计算最大解密块大小 |
|
maxDecryptBlock := rsaPrivKey.Size() |
|
encryptedLen := len(encryptedBytes) |
|
var decryptedBytes []byte |
|
|
|
// 分段解密 |
|
for i := 0; i < encryptedLen; i += maxDecryptBlock { |
|
end := i + maxDecryptBlock |
|
if end > encryptedLen { |
|
end = encryptedLen |
|
} |
|
|
|
// 使用私钥进行解密(这是RSA的标准做法) |
|
decryptedBlock, err := rsa.DecryptOAEP( |
|
nil, |
|
rand.Reader, |
|
rsaPrivKey, |
|
encryptedBytes[i:end], |
|
nil, |
|
) |
|
if err != nil { |
|
return "", fmt.Errorf("解密错误: %v", err) |
|
} |
|
|
|
decryptedBytes = append(decryptedBytes, decryptedBlock...) |
|
} |
|
|
|
return string(decryptedBytes), nil |
|
}
|
|
|