Theo như tôi biết - bạn là một chút lên một con lạch - với mái chèo bị nhốt trong appstore.
- iOS thiếu CMSEncoderAddSigners, CMSEncoderUpdateContent, CMSEncoderCopyEncodedNội dung bạn cần cho điều này.
- Sử dụng openssl hoặc Chilkat cũng không lý tưởng - vì API keychain của iOS không cung cấp cho bạn quyền truy cập (nữa) vào khóa riêng tư sau khi được nhập.
Tôi đã giải quyết vấn đề này trong quá khứ với cả openssl và Chilkat.
Trong mỗi trường hợp, tôi 'lưu' bản sao khóa cá nhân - như khi nó đi vào móc khóa - tất cả những gì tôi có thể quay lại là SecKeyRef (bạn cần phải ký một thỏa thuận/quyền bổ sung với táo có thể lấy nó ra và vẫn ở trong appstore, ngược lại, bất kỳ kỹ sư nào của VPN (ví dụ: trình bách khoa toàn thư) ứng dụng để xem các phương thức/khung liên kết).
Đối với openssl - chỉ cần lấy mã smime.c trong các ứng dụng của openssl và sửa đổi. Đối với những thứ Chilkat là đơn giản hơn rất nhiều:
CkoCert * mine = [identity ckoCert];
assert([mime AddEncryptCert: mine] == YES);
for(id cc in backupCerts) {
assert([mime AddEncryptCert:cc] == YES);
}
for(id key in [headers allKeys]) {
[mime SetHeaderField:[NSString stringWithFormat:@"%s%@", X_HDR_PREFIX, key]
value:[headers objectForKey:key]
];
};
[mime SetBodyFromBinary:data];
assert([mime EncryptN] == YES);
return [mime GetMimeBytes];
và nơi mà các lĩnh vực nhận dạng có 'giữ bộ nhớ cache của riêng bạn' cheat:
-(id)initWithPKCS12:(NSData*)pkcs12der password:(NSString *)password {
if (password == nil)
password = [APPSETTINGS wellKnownPkcsPassword];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
password, kSecImportExportPassphrase,
nil];
CFArrayRef items;
OSStatus status = SecPKCS12Import((__bridge CFDataRef)pkcs12der,
(__bridge CFDictionaryRef)options, &items);
if (status != noErr) {
NSLog(@"PKCS12 importAsDer failed: Error %ld",(long)status);
...
}
if (!items || CFArrayGetCount(items) < 1) {
NSLog(@"PKCS12 importAsDer failed - nothing returned (%ld bytes DER)",
(long)[pkcs12der length]);
...
}
CFDictionaryRef dict0 = (CFDictionaryRef) CFArrayGetValueAtIndex(items, 0);
if (!dict0)
return nil;
SecIdentityRef iRef = (SecIdentityRef) CFDictionaryGetValue(dict0,
kSecImportItemIdentity);
CFArrayRef cRef = (CFArrayRef) CFDictionaryGetValue(dict0, kSecImportItemCertChain);
self = [self initWithIdentityRef:iRef withChainArrayRef:cRef];
CFRelease(items);
#if TARGET_OS_IPHONE
// We lack SecPrivate* on iOS. So we cheat a bit - rather than
// use the keychain we limt ourselves to our own *.p12's and
// keep a copy of the private key in memory.
//
# ifdef WITH_OPENSSL
const unsigned char * ptr = [pkcs12der bytes];
PKCS12 * p12 = d2i_PKCS12(NULL, &ptr, len);
char buff[1024];
if (!p12) {
NSLog(@"Could not decode PKCS#12: %s", ERR_error_string(ERR_get_error(), buff));
...
};
const char * pass = [password cStringUsingEncoding:NSASCIIStringEncoding];
if (PKCS12_parse(p12, pass, &pkey, &x509, NULL) != 1) {
NSLog(@"Could not parse PKCS#12: %s", ERR_error_string(ERR_get_error(), buff));
...
};
....
# else
ckoCert = [[CkoCert alloc] init];
if (!([ckoCert LoadPfxData:pkcs12der password:[APPSETTINGS wellKnownPkcsPassword]])) {
NSLog(@"PKCS12 loadPfxData failed: %@", [ckoCert LastErrorText]);
...
}
ckoPrivateKey = [ckoCert ExportPrivateKey];
# endif // chilkat or openssl
#endif // iOS
return self;
}
Cảnh báo: trong trên tôi đã tước nhất quản lý mngt/lỗi và/hoặc thay thế nó bằng cách khẳng định nếu không nó sẽ có một chút quá tốn kém.
Xin cảm ơn,
Dw.
Không biết câu trả lời nhưng may mắn trên ứng dụng PassKit của bạn! –