我正在目标 C 下试验 OpenSSL。我正在尝试编写 SMIME 非对称密钥加密数据。我打开文件、加密文件并将其写入磁盘没有问题。我可以加密单个内存缓冲区。我想要做的是实现一种分散收集方法,将多个内存缓冲区馈入相同的加密 BIO 并串行写入磁盘。
我的代码很简单。我设置了一个密码并使用PEM_read_bio_X509_AUX()
. 我把它推到STACK_OF
X509s 上,certs
,sk_X509_push(certs,...)
。我打开我的输出文件writeBIO=BIO_new_file()
。我创建了一个内存 BIOreadBIO=BIO_new_mem_buf(buf,len);
并使用p7=PKCS_encrypt(certs,readBIO,...);
. 最后,我将其写入输出,i2d_PKCS7_bio(writeBIO,p7);
这仅适用于一个内存缓冲区。如果我尝试在循环中传递多个缓冲区,则仅输出最后一个。我已经尝试释放并重新分配在调用之间构建的readBIO
abd ,但这不起作用。p7
BIO_new_mem_buf
有任何想法吗?
更新 - 我有一个解决方案,但没有一个让我喜出望外的解决方案:
我有一个名为 AETPublicKeyWrapper 的 OpenSSL 包装器
@interface AETPublicKeyWrapper : NSObject { @私人的 生物*读取生物; 生物*写生物; STACK_OF(X509) *证书; 常量字符 *rmode,*wmode; PKCS7 *p7; EVP_PKEY *privateKey; 常量 EVP_CIPHER *密码; int 信息、输出格式、标志; } ... -(BOOL)openInputFile:(const char*)fname; -(BOOL)openOutputFile:(const char*)fname; -(BOOL)打开输入缓冲区; -(int)writeToInputBuffer:(const void*)buf 长度:(unsigned long long)len; -(BOOL)loadPublicKeyCert:(const char*)certFileName; ... -(BOOL)加密输入; -(BOOL)writeEncryptedOutput; -(BOOL)writeDecryptedOutput; ...
这封装了各种 OpenSSL API 调用。-(BOOL)openOutputFile:
例如只是
-(BOOL)openOutputFile:(const char*)fname { if(!(writeBIO=BIO_new_file((char*)fname,"wb"))) 返回否; 返回是; }
我的多个缓冲区到同一输出的加密例程如下所示:
AETPublicKeyWrapper *owrapper=[[AETPublicKeyWrapper alloc] init]; [owrapper loadPublicKeyCert:[keyPath cStringUsingEncoding:NSASCIIStringEncoding]] [owrapper openOutputFile:[saveAsPath cStringUsingEncoding:NSASCIIStringEncoding]] [owrapper openInputBuffer] /* fileData 是一个标题 */ [owrapper writeToInputBuffer:[fileData bytes] length:[fileData length]] /* dirArray 是一个缓冲区数组 */ for(NSData *itemData in dirArray) [owrapper writeToInputBuffer:[itemData bytes] 长度:[itemData length]]; [owrapper 加密输入] [owrapper writeEncryptedOutput] [owrapper 冲洗] [owrapper 发布]
各种方法是(省略了大多数错误处理;强制转换是为了关闭编译器)
-(BOOL)loadPublicKeyCert:(const char*)certFileName { X509 *x=NULL; 生物*新证书; 证书=sk_X509_new_null(); newCert=BIO_new(BIO_s_file()); BIO_read_filename(newCert,certFileName); x=PEM_read_bio_X509_AUX(newCert,NULL,NULL,NULL); sk_X509_push(证书,x); 返回是; } -(BOOL)openInputBuffer { if(!(readBIO=BIO_new(BIO_s_mem()))) 返回否; 返回是; } -(int)writeToInputBuffer:(const void*)buf 长度:(unsigned long long)len { 返回 BIO_write(readBIO,(void*)buf,(int)len); } -(BOOL)加密输入 { if(!(p7=PKCS7_encrypt(certs,readBIO,cipher,flags))) 返回否; 返回是; } -(BOOL)writeEncryptedOutput { 如果(i2d_PKCS7_bio(writeBIO,p7)<=0) 返回否; 返回是; }
这可行,但我担心输入缓冲区可能会变得任意大,所以我希望能够写入输出并让它在每次写入时刷新,而不是在最后累积并执行整个加密/写入操作.