【问题标题】:PKCS#12 Invalid PasswordPKCS#12 密码无效
【发布时间】:2016-11-17 22:19:41
【问题描述】:

在给定证书/私钥的一些数据的情况下,我在 iPhone 上使用此 OpenSSL 代码生成 PKCS#12 文件。我能够验证这个 PKCS#12 在 OpenSSL 上是否可解析,因为当我在代码中检查它时它不会打印出错误。但是,当我将它传输到我的服务器时,它说:Error: PKCS#12 MAC could not be verified. Invalid password? 有谁知道这是为什么?我使用的是相同的密码,即“密码”

 - (NSData *)generateP12AsNSData:(NSData *)keyData certificate:(NSData *)certificateData {
    //put the certificateData into a X509 certificate
    const unsigned char *certificateDataBytes = (const unsigned char*)[certificateData bytes];
    X509 *certificateX509 = d2i_X509(NULL, &certificateDataBytes, [certificateData length]);

    EVP_PKEY *privateKey;
    PKCS12 *p12;
    //cast the key data as an unsigned char so that we can convert it to the OpenSSL key format
    const unsigned char *bits = (unsigned char *) [keyData bytes];
    int length = (int)[keyData length];
    privateKey = EVP_PKEY_new();

    //convert the unsigned char to OpenSSL Key format
    RSA *rsa = NULL;
    d2i_RSAPrivateKey(&rsa, &bits, &length);
    EVP_PKEY_assign_RSA(privateKey, rsa);

    //create the PKCS#12
    OpenSSL_add_all_algorithms();
    p12 = PKCS12_create("password", "ExtraDeviceP12", privateKey, certificateX509, NULL, 0,0,0,0,0);

    //make sure the p12 exists
    if(!p12) {
        fprintf(stderr, "Error creating PKCS#12 ");
        ERR_print_errors_fp(stderr);
        return nil;
    }

    //error checking to make sure we generated the CSR correctly
    STACK_OF(X509) *ca = NULL;
    EVP_PKEY *parseKey;
    X509 *parseCert;
    if (!PKCS12_parse(p12, "password", &parseKey, &parseCert, &ca)) {
        printf("error parsing PKCS#12 file");
        return nil;
    }

    //convert the PKCS#12 to binary data
    //create a new memory BIO. A BIO is used for basic I/O abstraction.
    BIO *bio;
    bio = BIO_new(BIO_s_mem());
    //i2d_PKCS12_bio is used to export a PKCS12 object
    i2d_PKCS12_bio(bio, p12);
    BUF_MEM *buffer;
    BIO_get_mem_ptr(bio, &buffer);

    //int bioLen = BIO_pending(&buffer);


    char *buff = (char*)malloc(buffer->length);
    memcpy(buff, buffer->data, buffer->length - 1);
    buff[buffer->length - 1] = 0;
    NSData *data = [NSData dataWithBytes:buff length:buffer->length];

    NSString *string = [data base64EncodedStringWithOptions:0];
    NSLog(@"Base64 PKCS#12: %@", string);

    BIO_free_all(bio);

    return data;
}

编辑: 这是我的服务器端用 Javascript 编写的代码。在这种情况下,req.body 是从 iPhone 发送的 NSData。我收到无效密码错误。

  var p12b64 = req.body.toString('base64');    
  var p12Der = forge.util.decode64(pk12b64);
  var p12Asn1 = forge.asn1.fromDer(p12Der);
  var p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, 'password');

【问题讨论】:

  • 只更改 NSData 行会解决问题吗?我不能将二进制数据编码为 base64 吗?
  • 当我在 Shell 中运行 openssl pkcs12 -in p12.p12 -nocerts -out privateKey.pem 时出现。它要求输入密码,并在输入密码时导致该错误。 p12.p12 是一个包含数据的文件。我使用了不同的函数来创建它,因为我使用不同的格式进行了测试,所以它可以工作。
  • 我编辑了原帖。我在“上面的代码”中处理不当,如何解决?
  • 解决了,谢谢。如果需要,您可以发布答案,我可以将其标记为正确。

标签: c++ ios objective-c security openssl


【解决方案1】:

试试下面的。它向您展示了应该检查一些关键返回值的位置,并避免了数据的额外副本:

BIO *bio = BIO_new(BIO_s_mem());
ASSERT(bio != NULL);

int ret = i2d_PKCS12_bio(bio, p12);
ASSERT(ret == 1);

BUF_MEM *buffer;
BIO_get_mem_ptr(bio, &buffer);
ASSERT(buffer != NULL);

NSData *data = [NSData dataWithBytes:buffer->data length:buffer->length];
BIO_free_all(bio);

您可以在i2d_PKCS12_bio man pages 找到i2d_PKCS12_bio 的文档。

如果需要,您可以对来自 i2d_PKCS12_bio 的二进制数据进行 Base64 编码。有关使用 BIO 链并确保 Base64 字符串以 NULL 结尾的信息,请参阅 Non-printable character after generating random n-byte Base64 string

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 2015-02-14
    • 2019-05-28
    • 2017-03-16
    • 2020-09-16
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    相关资源
    最近更新 更多