SecPKCS12Import在iOS 11和iOS 10上返回的结果不同。

5

这个函数的参数是一个Base64编码的PKCS#12证书字符串,然后解码并传递给SecPKCS12Import函数。在iOS 11之后的更新中,SecPKCS12Import会产生不同的结果。在两个操作系统版本上,安全错误返回值都为0。

let securityError: OSStatus = SecPKCS12Import(decodedData!, options, &items)

返回0个项目的列表。而在iOS 10中,数组中会有1个项目。
func certificateFromCertificate(certP12: String, psswd: String) -> SecCertificate {
    let decodedData = NSData(base64Encoded: certP12, options:NSData.Base64DecodingOptions(rawValue: 0))

    let keytmp : NSString = kSecImportExportPassphrase as NSString
    let options : NSDictionary = [keytmp : psswd]

    var certificateRef: SecCertificate? = nil

    var items : CFArray?

    let securityError: OSStatus = SecPKCS12Import(decodedData!, options, &items)

    let theArray: CFArray = items!
    if securityError == noErr && CFArrayGetCount(theArray) > 0 {
        let newArray = theArray as [AnyObject] as NSArray
        let dictionary = newArray.object(at: 0)
        let secIdentity = (dictionary as AnyObject)[kSecImportItemIdentity as String] as! SecIdentity
        let securityError = SecIdentityCopyCertificate(secIdentity , &certificateRef)
        if securityError != noErr {
            certificateRef = nil
        }
    }

    certificate = certificateRef

    return certificateRef!
}

这是一个在苹果开发者论坛上的帖子,说SecPKCS12Import实现了自动转换Base64。这意味着在将证书传递给函数之前,我应该对普通证书进行解码。这可能是问题所在吗?
我已经向Apple论坛技术支持事件提交了帖子。 开发环境: 编程语言:Swift 3
调试设备:Apple iPad mini Retina Wi-Fi 32GB ME280SL/A
开发设备:iMAC mini Xcode版本9.0 9A235

其他变量都没问题吗?decodedData 里面有东西吗?options 呢? - Adam
@McNight 我检查了 certP12 的值,它是相同的。 - Marek
你有检查错误吗?例如securityErrorDecodedData呢? - Brandon
@Brandon 安全错误返回0 - 成功。我发现了一个论坛文章forums.developer.apple.com/thread/82373,讨论了SecPKCS12Import中实现的自动从Base64解码的更改,这意味着我不应该传递解码后的值。尝试了但失败了。 - Marek
2个回答

2

使用 Xcode Version 9.0.1 (9A1004)Apple Swift version 4.0 (swiftlang-900.0.65.2 clang-900.0.37),我可以从您的函数中获得正常的结果。同时也适用于设置为3.2的Swift语言。

在您引用的帖子中,@eskimo说(加粗是我的):

您的选择是:

  • 提交兼容性错误反对iOS 11 beta,并希望它在GM之前修复
  • 按照文档中所述的方式更改应用程序以使用SecPKCS12Import,即撤消Base64解码

看起来有人提交了一个错误,并已经修复了问题(按照最初的文档工作)。没有自动解码来自Base64的内容。您提供了正确的解码。


0

苹果开发者支持团队已经调查了这个问题,并得出结论,特定的.p12文件未满足iOS 11的安全要求。

以下是来自苹果DTS的Quinn电子邮件内容:

To understand what’s going on you must set a breakpoint on the function SecKeyCreateRSAPrivateKey. This is a private function within the Security framework, so you’ll need to use a symbolic breakpoint (in the Breakpoints navigator, click the + button and choose Symbolic Breakpoint from the menu. Once you’ve done that, tap the “Test 1” button and you’ll stop at the breakpoint.

This function takes 4 arguments, but the two relevant ones are the second and third arguments, which are a pointer to the RSA private key

data to decode and the length of that data. Once you hit the breakpoint you can dump the data as follows:

(lldb) # Confirm the length in the third argument.
(lldb) p $arg3
(unsigned long) $0 = 1192
(lldb) # Dump the data pointed to be the second argument.
(lldb) memory read -f x -s 1 -c 1192 --force $arg2
… elided …

结果太长了,无法在此处包含,因此我取消了十六进制编码,并将结果作为文件附加在此处:RSAPrivateKey.asn1。 如果您使用dumpasn1转储它,您会看到问题:
$ dumpasn1 -p -a RSAPrivateKey.asn1 
SEQUENCE {
  INTEGER 0
  INTEGER
    …
  INTEGER 65537
  INTEGER
    00 0B 67 67 29 0A 38 38 7A 7E 17 39 E7 84 FB 7D
    02 D1 AB AD 21 27 4D CD 2C 09 C1 1F CB 73 5C 18
    37 D4 CE E2 98 61 19 3B 70 6C 1A 1B 33 E8 69 8C
    65 5B 77 B8 24 9C 90 8A 79 A7 4A 77 26 38 7C 3E
    70 3C 80 24 BD 73 DA 97 5A F3 90 0F 79 2D 45 F8
    2A 5A 37 03 4D 0C 80 DB 8F 99 67 55 D3 F3 70 CA
    2D F0 B6 48 6A D8 9A 95 CE AA C8 F1 96 24 04 61
    38 A1 7C CD 56 70 5E F9 13 D4 1B E2 F2 5D 28 67
    9A 30 E0 ED 71 84 4C EC 86 44 18 5F 64 70 46 D8
    6B 3A 52 2C D7 DE AF E5 E2 35 41 0D 1E FF E7 DE
    AC 43 83 5C A6 F2 2E C8 79 1A 30 87 7A 78 9B 42
    3E D9 2D AA C0 9D A6 7C E9 5C E3 6C 1E 8D 87 DF
    EB 05 DF CA F5 B9 2D BA B6 01 71 18 22 4D 25 4E
    D5 77 CB B8 9B 95 F9 C6 39 1C 0D D2 46 E4 4A 45
    D8 26 6F B4 25 03 E7 BE 91 02 43 7D DC B0 1E C8
    67 E8 2E 5F EA 3A 8D 1C 69 43 80 F9 60 69 BF BA
    01
    Error: Integer has non-DER encoding.
  INTEGER
    …
  INTEGER
    …
  INTEGER
    …
  INTEGER
    …
  INTEGER
    …
  }

请注意第四个INTEGER元素中引发的“Integer has non-DER encoding”错误。这是因为INTEGER数据不是规范的。在ASN.1 DER中,INTEGER是有符号的,这会引起歧义。像80 00这样的值可以被解释为-32768或32768。为了解决这个问题,ASN.1 DER要求将正数形式编码为00 80 00(还有一个类似的情况需要一个前导ff)。此外,DER明确要求只在必要时添加这个前导字节。在上面显示的情况下,第二个字节0b没有设置最高位,因此不能有那个前导00。
早期版本的iOS没有强制执行这个要求。iOS 11包括许多安全加固改变,拒绝无效编码的ASN.1 DER INTEGER就是其中之一。
我看到其他开发人员也受到了这个安全更改的影响,但那些情况更容易调试,因为密钥没有嵌入在PKCS#12中。例如,请参考以下DevForums线程。 https://forums.developer.apple.com/message/262593#262593 此外,这个问题很难调试,因为当你用openssl解包.p12时,它会忽略输入中的这个错误,并在输出时发出私钥的固定版本!
Quin建议我通过修复生成此PKCS#12数据的任何代码来解决此问题。如果不可能,您将需要编写(或获取)自己的代码来解析PKCS#12。iOS 11正确地拒绝了格式错误的私钥,这很可能不会改变。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接