0

我正在目标 C 下试验 OpenSSL。我正在尝试编写 SMIME 非对称密钥加密数据。我打开文件、加密文件并将其写入磁盘没有问题。我可以加密单个内存缓冲区。我想要做的是实现一种分散收集方法,将多个内存缓冲区馈入相同的加密 BIO 并串行写入磁盘。

我的代码很简单。我设置了一个密码并使用PEM_read_bio_X509_AUX(). 我把它推到STACK_OFX509s 上,certssk_X509_push(certs,...)。我打开我的输出文件writeBIO=BIO_new_file()。我创建了一个内存 BIOreadBIO=BIO_new_mem_buf(buf,len);并使用p7=PKCS_encrypt(certs,readBIO,...);. 最后,我将其写入输出,i2d_PKCS7_bio(writeBIO,p7);这仅适用于一个内存缓冲区。如果我尝试在循环中传递多个缓冲区,则仅输出最后一个。我已经尝试释放并重新分配在调用之间构建的readBIOabd ,但这不起作用。p7BIO_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)
          返回否;
       返回是;
    }

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

4

0 回答 0