使用AVFoundation读取含ASCII字符的QR码时stringValue返回nil的问题
解决加密ASCII字符QR码读取时stringValue返回nil的问题
看起来你遇到的核心问题是加密后的QR码包含非可打印ASCII字符,导致[metadataObj stringValue]无法正常解码成NSString,直接返回nil了。因为stringValue会尝试把QR码的原始字节按照标准字符串编码(比如UTF-8)去解析,而加密后的字节流大概率不是合法的字符串编码,所以这条路走不通。
先看你代码里的明显问题:
unsigned char buffer_to_decrypt=[metadataObj stringValue];
stringValue返回的是NSString*类型,你直接赋值给unsigned char变量,这不仅编译会报错,逻辑上也完全错误——你需要的是QR码存储的原始字节数据,而不是转成字符串后的内容。
正确处理方案:获取QR码原始字节数据
AVMetadataMachineReadableCodeObject提供了dataValue属性,它会直接返回QR码存储的原始字节NSData,不管这些字节是不是可打印ASCII字符,这才是你需要的加密数据载体。
修正后的代码如下:
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ unsigned char myKey[2]; myKey[0]=1; myKey[1]=2; if(metadataObjects == nil || [metadataObjects count] ==0) { qrCodeFrameView.frame=CGRectZero; return; // 增加return避免后续无效执行 } AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0]; if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) { // 关键:改用dataValue获取QR码原始字节数据 NSData *encryptedData = metadataObj.dataValue; if (!encryptedData) { NSLog(@"无法获取QR码原始数据"); qrCodeFrameView.frame=CGRectZero; return; } Encoder *encoder=[[Encoder alloc] init]; NSLog(@"原始加密数据长度:%lu", (unsigned long)encryptedData.length); // 分配解密缓冲区,长度与加密数据一致 NSUInteger dataLength = encryptedData.length; unsigned char *buffer_to_decrypt = malloc(dataLength); if (!buffer_to_decrypt) { NSLog(@"内存分配失败"); return; } [encryptedData getBytes:buffer_to_decrypt length:dataLength]; // 执行3DES解密(注意:3DES密钥长度要求16/24字节,当前2字节密钥不安全且可能导致解密失败) [encoder tripledes_decrypt:buffer_to_decrypt lenght:dataLength key:myKey]; // 将解密后的字节转为NSData NSData *decryptedData = [NSData dataWithBytes:buffer_to_decrypt length:dataLength]; NSLog(@"解密后data = %@", decryptedData); // 转为ASCII字符串 NSString *result=[[NSString alloc] initWithData:decryptedData encoding:NSASCIIStringEncoding]; NSLog(@"-----<<<<result>>>>%@",result); // 更新识别框并触发震动 AVMetadataMachineReadableCodeObject *barCodeObj=(AVMetadataMachineReadableCodeObject *)[_videoPreviewLayer transformedMetadataObjectForMetadataObject:metadataObj]; qrCodeFrameView.frame=barCodeObj.bounds; AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); [self stopReading]; _isReading = NO; // 释放手动分配的内存 free(buffer_to_decrypt); } }
额外提醒
- 3DES密钥长度问题:当前你使用的2字节密钥不符合3DES算法要求(标准要求16或24字节),不仅完全没有安全性,还可能导致解密函数执行失败,建议立即修正密钥长度。
- 内存管理:代码中用
malloc分配的缓冲区需要手动free,避免内存泄漏;ARC环境下NSData会自动管理内存,无需额外处理。 - QR码容量限制:加密后的数据长度不能超过目标QR码版本的容量上限,否则生成的QR码可能无法被正常识别。
内容的提问来源于stack exchange,提问作者hikmat_11
相关产品推荐
相关产品推荐

