Por lo que yo sé, usted está un poco en un riachuelo, con la paleta encerrada en la tienda de aplicaciones.
- iOS carece CMSEncoderAddSigners, CMSEncoderUpdateContent, CMSEncoderCopyEncodedContent que se necesita para esto.
- El uso de openssl o Chilkat tampoco es ideal, ya que la API de llavero de iOS no le da acceso (más) a la clave privada una vez importada.
He resuelto esto en el pasado tanto con openssl como con Chilkat.
En cada caso, sin embargo, 'guardo' una copia de la clave privada, ya que una vez que ingresa en el llavero, todo lo que puedo recuperar es un SecKeyRef (debe firmar un acuerdo/permiso adicional con apple to be capaz de volver a salir y aún estar en la tienda de aplicaciones. Invertir ingeniería de cualquiera de las aplicaciones de VPN (por ejemplo, el enebro uno) para ver los métodos/marco para vincular).
Para openssl - simplemente tome el código smime.c en las aplicaciones de openssl y modifique. Para que las cosas chilkat son mucho más simple:
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];
y donde el campo de identidad tiene la 'mantener su propia caché' tramposo:
-(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;
}
Advertencia: en la mayor parte de gestión MNGT/error anterior que he desnudado y/o lo reemplazó por afirma, ya que de lo contrario, se puso un poco demasiado manejable.
Gracias,
Dw.
No sé la respuesta, pero ¡buena suerte en su aplicación PassKit! –