OpenSSL将多个内存BIO写入同一个宿BIO

时间:2012-06-09 08:45:06

标签: cryptography openssl

我正在目标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;
    }

这样可行,但我担心的是输入缓冲区可能会变得任意大,所以我更愿意能够写入输出并让它在每次写入时刷新,而不是累积并执行整个加密/写入操作最后。

0 个答案:

没有答案