我正在目标C下试验OpenSSL。我正在尝试编写SMIME非对称密钥加密数据。打开文件,加密文件并将其写入磁盘我没有问题。我可以加密单个内存缓冲区。我想要做的是实现一种分散 - 聚集方法,将多个内存缓冲区输入同一个加密BIO并串行写入磁盘。
我的代码很简单。我设置了一个密码并使用PEM_read_bio_X509_AUX()
获取公钥/证书。我将STACK_OF
X509s certs
推送到sk_X509_push(certs,...)
。我用writeBIO=BIO_new_file()
打开输出文件。我使用readBIO=BIO_new_mem_buf(buf,len);
创建了一个内存BIO,并使用p7=PKCS_encrypt(certs,readBIO,...);
对其进行加密。最后我用i2d_PKCS7_bio(writeBIO,p7);
将它写入输出。这适用于一个内存缓冲区。如果我尝试在循环中传递多个缓冲区,则只输出最后一个缓冲区。我已尝试在readBIO
的调用之间释放并重新分配p7
abd BIO_new_mem_buf
,但这不起作用。
有什么想法吗?
<小时/> 更新 - 我有一个解决方案但不是我喜欢的一个解决方案:
我有一个名为AETPublicKeyWrapper
的OpenSSL包装器@interface AETPublicKeyWrapper : NSObject { @private BIO *readBIO; BIO *writeBIO; STACK_OF(X509) *certs; const char *rmode,*wmode; PKCS7 *p7; EVP_PKEY *privateKey; const EVP_CIPHER *cipher; int informat,outformat,flags; } ... -(BOOL)openInputFile:(const char*)fname; -(BOOL)openOutputFile:(const char*)fname; -(BOOL)openInputBuffer; -(int)writeToInputBuffer:(const void*)buf length:(unsigned long long)len; -(BOOL)loadPublicKeyCert:(const char*)certFileName; ... -(BOOL)encryptInput; -(BOOL)writeEncryptedOutput; -(BOOL)writeDecryptedOutput; ...
这封装了各种OpenSSL API调用。例如-(BOOL)openOutputFile:
只是
-(BOOL)openOutputFile:(const char*)fname { if(!(writeBIO=BIO_new_file((char*)fname,"wb"))) return NO; return YES; }
我将多个缓冲区的加密例程转换为相同的输出:
AETPublicKeyWrapper *owrapper=[[AETPublicKeyWrapper alloc] init]; [owrapper loadPublicKeyCert:[keyPath cStringUsingEncoding:NSASCIIStringEncoding]] [owrapper openOutputFile:[saveAsPath cStringUsingEncoding:NSASCIIStringEncoding]] [owrapper openInputBuffer] /* fileData is a header */ [owrapper writeToInputBuffer:[fileData bytes] length:[fileData length]] /* dirArray is an array of buffers */ for(NSData *itemData in dirArray) [owrapper writeToInputBuffer:[itemData bytes] length:[itemData length]]; [owrapper encryptInput] [owrapper writeEncryptedOutput] [owrapper flush] [owrapper release]
各种方法都是(省略了大多数错误处理;强制转换是为了关闭编译器)
-(BOOL)loadPublicKeyCert:(const char*)certFileName { X509 *x=NULL; BIO *newCert; certs=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(certs,x); return YES; } -(BOOL)openInputBuffer { if(!(readBIO=BIO_new(BIO_s_mem()))) return NO; return YES; } -(int)writeToInputBuffer:(const void*)buf length:(unsigned long long)len { return BIO_write(readBIO,(void*)buf,(int)len); } -(BOOL)encryptInput { if(!(p7=PKCS7_encrypt(certs,readBIO,cipher,flags))) return NO; return YES; } -(BOOL)writeEncryptedOutput { if(i2d_PKCS7_bio(writeBIO,p7)<=0) return NO; return YES; }
这样可行,但我担心的是输入缓冲区可能会变得任意大,所以我更愿意能够写入输出并让它在每次写入时刷新,而不是累积并执行整个加密/写入操作最后。