本文深入探讨了在使用Go语言进行AES-256 CBC加密后,通过Objective-C的CCCrypt进行解密时,可能出现的末尾数据块丢失问题。核心原因在于Go端采用了非标准的前置空格填充方式,而Objective-C解密时默认启用了PKCS7填充处理。通过将CCCrypt的填充选项设置为0,禁用自动填充,从而确保解密过程与加密端的行为一致,成功解决数据丢失。
在跨语言环境中实现加密与解密操作时,最常见的挑战之一是确保两端在算法、密钥、IV以及填充模式上保持完全一致。本教程将聚焦于一个具体的案例:使用Go语言加密的AES-256 CBC数据,在Objective-C中使用CCCrypt进行解密时,发现解密结果总是丢失最后一个数据块。
Go语言的加密代码片段展示了AES-256 CBC模式的实现。关键点在于其对明文的填充处理:
func encrypt(text_s, key_s string) byte[] {
text := []byte(text_s)
// 自定义填充逻辑:计算需要填充的字节数,并在明文前添加空格
n := aes.BlockSize - (len(text) % aes.BlockSize)
if n != aes.BlockSize || n != 0 {
text = append([]byte(strings.Repeat(" ", n)), text...)
}
// 初始化AES密钥和CBC加密器
key := []byte(key_s)[:32] // 确保密钥长度为32字节(AES256)
block, _ := aes.NewCipher(key)
// 生成随机IV并将其作为密文的前16字节
ret := make([]byte, aes.BlockSize + len(text))
iv := ret[:aes.BlockSize]
io.ReadFull(rand.Reader, iv)
cbc := cipher.NewCBCEncrypter(block, iv)
cbc.CryptBlocks(ret[aes.BlockSize:], text) // 执行加密
return ret
}从上述Go代码中可以观察到以下重要特征:
Objective-C端的解密代码使用了CommonCrypto框架中的CCCrypt函数。初始实现如下:
- (NSData *)decrypt:(NSData*)data {
// 密钥处理 (假设已正确获取并转换为NSData)
NSData *keyData = self.key; // 假设key已在外部初始化为NSData类型
// 从输入数据中分离IV和加密数据
size_t ivLength = kCCBlockSizeAES128; // AES块大小为16字节
size_t encryptedDataLength = [data length] - ivLength;
NSData *iv = [data subdataWithRange:NSMakeRange(0, ivLength)];
NSData *encrypted = [data subdataWithRange:NSMakeRange(ivLength, encryptedDataLength)];
// 为解密结果分配缓冲区
NSMutableData *ret = [NSMutableData dataWithLength:encryptedDataLength + ivLength]; // 预留一个块的额外空间
size_t numBytesDecrypted = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt, // 解密操作
kCCAlgorithmAES, // AES算法
kCCOptionPKCS7Padding, // 初始问题所在:启用了PKCS7填充选项
[keyData bytes], // 密钥
kCCKeySizeAES256, // 密钥大小
[iv bytes], // IV
[encrypted bytes], encryptedDataLength, // 输入密文及其长度
[ret mutableBytes], [ret length], // 输出缓冲区及其长度
&numBytesDecrypted // 实际解密字节数
);
NSLog(@"CCCrypt status: %d", status);
NSLog(@"Input dataLength: %d, Decrypted bytes: %d", (int)encryptedDataLength, (int)numBytesDecrypted);
if (status == kCCSuccess) {
// 返回解密后的数据
// 注意:如果需要手动处理填充,这里可能需要调整ret的长度
return [ret subdataWithRange:NSMakeRange(0, numBytesDecrypted)];
}
return nil;
}观察到的问题是:当期望解密得到80字节的数
据时,实际只得到64字节;期望得到128字节时,实际得到112字节。这表明解密结果总是比预期少一个数据块(16字节)。
问题的核心在于Go语言端采用了自定义的、非标准的、前置空格填充,而Objective-C的CCCrypt在调用时指定了kCCOptionPKCS7Padding选项。
kCCOptionPKCS7Padding选项指示CCCrypt在解密完成后,自动识别并移除PKCS7填充。然而,由于Go端根本没有使用PKCS7填充,而是添加了前置空格,CCCrypt在解解密后的数据中找不到有效的PKCS7填充,它可能会:
无论哪种情况,结果都是丢失了最后一个数据块。
既然Go端使用了自定义填充且不依赖PKCS7,那么在Objective-C解密时,就应该禁用CCCrypt的自动填充处理。这意味着需要将CCCrypt的选项参数从kCCOptionPKCS7Padding更改为0(即不启用任何特殊选项)。
修正后的Objective-C解密代码如下:
- (NSData *)decrypt:(NSData*)data {
NSData *keyData = self.key;
size_t ivLength = kCCBlockSizeAES128;
size_t encryptedDataLength = [data length] - ivLength;
NSData *iv = [data subdataWithRange:NSMakeRange(0, ivLength)];
NSData *encrypted = [data subdataWithRange:NSMakeRange(ivLength, encryptedDataLength)];
NSMutableData *ret = [NSMutableData dataWithLength:encryptedDataLength + ivLength];
size_t numBytesDecrypted = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt,
kCCAlgorithmAES,
0, // 关键修改:将填充选项设置为0,禁用自动PKCS7填充
[keyData bytes],
kCCKeySizeAES256,
[iv bytes],
[encrypted bytes], encryptedDataLength,
[ret mutableBytes], [ret length],
&numBytesDecrypted
);
NSLog(@"CCCrypt status: %d", status);
NSLog(@"Input dataLength: %d, Decrypted bytes: %d", (int)encryptedDataLength, (int)numBytesDecrypted);
if (status == kCCSuccess) {
// 返回实际解密的数据,此时数据中仍然包含Go端添加的前置空格填充
return [ret subdataWithRange:NSMakeRange(0, numBytesDecrypted)];
}
return nil;
}通过将填充选项设置为0,CCCrypt将不再尝试移除PKCS7填充。它会按照CBC模式解密所有输入的密文块,并返回完整的解密数据。此时,解密后的数据将包含Go端添加的前置空格填充,开发者可以根据Go端填充的规则(例如,移除前导空格)进行后续处理以获取原始明文。
解决Go与Objective-C之间AES CBC解密数据块丢失问题的关键在于识别并纠正两端填充模式的不匹配。Go端使用了自定义的前置空格填充,而Objective-C端默认启用了PKCS7填充处理。通过在Objective-C的CCCrypt调用中将填充选项设置为0,可以禁用其自动PKCS7填充,从而获得完整的解密数据。此后,如果需要,可以根据Go端的填充规则手动移除前置的空格填充。本案例强调了在跨平台加密实践中,对所有加密参数(特别是填充模式)进行严格同步的重要性。
# go
# go语言
# app
# 字节
# 数据加密
# 数据丢失
# 标准库
# crypto
相关文章:
在线教育网站制作平台,山西立德教育官网?
网站专业制作公司有哪些,做一个公司网站要多少钱?
如何在阿里云购买域名并搭建网站?
ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?
常州自助建站费用包含哪些项目?
如何在阿里云虚拟服务器快速搭建网站?
东莞专业制作网站的公司,东莞大学生网的网址是什么?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
内部网站制作流程,如何建立公司内部网站?
如何用PHP工具快速搭建高效网站?
ui设计制作网站有哪些,手机UI设计网址吗?
如何选择适合PHP云建站的开源框架?
网页设计网站制作软件,microsoft office哪个可以创建网页?
如何通过虚拟主机快速完成网站搭建?
视频网站app制作软件,有什么好的视频聊天网站或者软件?
如何通过智能用户系统一键生成高效建站方案?
建站主机选择指南:服务器配置与SEO优化实战技巧
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
c++ stringstream用法详解_c++字符串与数字转换利器
香港服务器网站卡顿?如何解决网络延迟与负载问题?
c# 在高并发下使用反射发射(Reflection.Emit)的性能
零服务器AI建站解决方案:快速部署与云端平台低成本实践
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
网站制作免费,什么网站能看正片电影?
如何在新浪SAE免费搭建个人博客?
如何快速重置建站主机并恢复默认配置?
制作旅游网站html,怎样注册旅游网站?
制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?
建站之星多图banner生成与模板自定义指南
建站主机选哪种环境更利于SEO优化?
单页制作网站有哪些,朋友给我发了一个单页网站,我应该怎么修改才能把他变成自己的呢,请求高手指点迷津?
Bpmn 2.0的XML文件怎么画流程图
如何用花生壳三步快速搭建专属网站?
,如何利用word制作宣传手册?
制作销售网站教学视频,销售网站有哪些?
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
香港服务器选型指南:免备案配置与高效建站方案解析
如何制作网站标识牌,动态网站如何制作(教程)?
如何通过云梦建站系统实现SEO快速优化?
建站之星各版本价格是多少?
独立制作一个网站多少钱,建立网站需要花多少钱?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
建站之星如何防范黑客攻击与数据泄露?
如何解决VPS建站LNMP环境配置常见问题?
整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?
大学网站设计制作软件有哪些,如何将网站制作成自己app?
早安海报制作网站推荐大全,企业早安海报怎么每天更换?
长沙做网站要多少钱,长沙国安网络怎么样?
广平建站公司哪家专业可靠?如何选择?
5种Android数据存储方式汇总
*请认真填写需求信息,我们会在24小时内与您取得联系。