Pregunta

Estoy trabajando en una aplicación para iPhone que recupera una clave pública RSA de un servicio web ASP.NET en el formulario:

<RSAKeyValue>
  <Modulus>qdd0paiiBJ+xYaN4TKDdbEzrJJw9xlbRAltb5OPdegjLoW60yOjL/sni52WVsGC9QxpNitZR33dnUscmI0cTJoxkXypPjbD94UpH+p4el2tuKBypHlE7bERApuUp55y8BiRkbQNFH8smZFWDwtIc/PsJryeGf8fAryel8c5V3PU=</Modulus>
  <Exponent>AQAB</Exponent>
</RSAKeyValue>

Necesito convertir esta respuesta en un NSData * del formato apropiado (de un intenso google, muy probablemente 'asn.1 der' formato binario. Tengo código en su lugar para convertir ambas partes de sus representaciones Base64 a los valores binarios originales, pero no puedo por la vida por la vida De mí, descubra una forma razonable de crear la clave binaria de una pieza.

El código que espera la clave es el -addPeerPublicKey:(NSString *) keyBits:(NSData *) método del SecKeyWrapper clase de Apple's CryptoExercise proyecto de ejemplo (código aquí).

Estaría más que feliz de implementar esto de otra manera: todo lo que necesito es cifrar una sola cadena (no se requiere descifrado). Sin embargo, por lo que puedo decir, el marco de seguridad incorporado tiene lo que necesito, si pudiera cerrar esta brecha de formato. Si hay una manera de convertir la llave y enviarla Base64 codificada del servicio web, también funciona para mí, pero tampoco puedo encontrar ninguna forma de codificarla ASN.1.

¿Fue útil?

Solución

Entonces, usé el SecKeyWrapper clase para generar una clave aleatoria, luego usó el -getPublicKeyBits Método para obtener la representación binaria de la clave pública (en cualquier formato se usa internamente). Suponiendo que es una forma de Der Asn.1, lo que lo hice a la consola como hex y lo cargué en este programa. Efectivamente, la representación interna es Der Asn.1, pero es una versión muy simplificada de lo que normalmente encontré para las representaciones clave RSA:

![SEQUENCE { INTEGER, INTEGER }][2]

No debería ser demasiado difícil de construir sobre la marcha desde un representante binario. del módulo y el exponente, ya que la codificación de DER es solo

30 (for SEQUENCE) LL (total sequence byte length) 
02 (INTEGER) LL (modulus byte length) XX XX... (modulus data bytes) 
02 LL XX XX XX... (exponent length and bytes)

Aquí está mi código, por simplicidad. Utiliza algunas libres de Google para XML+Base64, solo se dirige; También el código de demostración de Apple SecKeyWrapper. Ver Mi otra pregunta para una nota sobre cómo hacer esto funcione. Además, tenga en cuenta que es no ARC compatible; Esto se deja como un ejercicio para el lector (escribí esto hace años, ahora).

#define kTempPublicKey @"tempPayKey"
-(NSData *)encryptedDataWithXMLPublicKey:(NSString *)base64PublicKey data:(NSData *)data {
    if(![data length]){
        @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:@"Data not set." userInfo:nil];
    }
    GTMStringEncoding *base64 = [GTMStringEncoding rfc4648Base64StringEncoding];
    NSData *keyData = [base64 decode:base64PublicKey];
    NSError *err = nil;
    GDataXMLDocument *keyDoc = [[GDataXMLDocument alloc] initWithData:keyData options:0 error:&err];
    if(err){
        NSLog(@"Public key parse error: %@",err);
        [keyDoc release];
        return nil;
    }

    NSString *mod64 = [[[[keyDoc rootElement] elementsForName:@"Modulus"] lastObject] stringValue];
    NSString *exp64 = [[[[keyDoc rootElement] elementsForName:@"Exponent"] lastObject] stringValue];
    [keyDoc release];
    if(![mod64 length] || ![exp64 length]){
        @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:@"Malformed public key xml." userInfo:nil];
    }

    NSData *modBits = [base64 decode:mod64];
    NSData *expBits = [base64 decode:exp64];

    /* the following is my (bmosher) hack to hand-encode the mod and exp
     * into full DER encoding format, using the following as a guide:
     * http://luca.ntop.org/Teaching/Appunti/asn1.html
     * this is due to the unfortunate fact that the underlying API will
     * only accept this format (not the separate values)
     */

    // 6 extra bytes for tags and lengths
    NSMutableData *fullKey = [[NSMutableData alloc] initWithLength:6+[modBits length]+[expBits length]];
    unsigned char *fullKeyBytes = [fullKey mutableBytes];
    unsigned int bytep = 0; // current byte pointer
    fullKeyBytes[bytep++] = 0x30;
    if(4+[modBits length]+[expBits length] >= 128){
        fullKeyBytes[bytep++] = 0x81;
        [fullKey increaseLengthBy:1];
    }
    unsigned int seqLenLoc = bytep;
    fullKeyBytes[bytep++] = 4+[modBits length]+[expBits length];
    fullKeyBytes[bytep++] = 0x02;
    if([modBits length] >= 128){
        fullKeyBytes[bytep++] = 0x81;
        [fullKey increaseLengthBy:1];
        fullKeyBytes[seqLenLoc]++;
    }
    fullKeyBytes[bytep++] = [modBits length];
    [modBits getBytes:&fullKeyBytes[bytep]];
    bytep += [modBits length];
    fullKeyBytes[bytep++] = 0x02;
    fullKeyBytes[bytep++] = [expBits length];
    [expBits getBytes:&fullKeyBytes[bytep++]];

    SecKeyRef publicKey = [[SecKeyWrapper sharedWrapper] addPeerPublicKey:kTempPublicKey keyBits:fullKey];
    [fullKey release];

    NSData *encrypted = [[SecKeyWrapper sharedWrapper] wrapSymmetricKey:data keyRef:publicKey];
    // remove temporary key from keystore
    [[SecKeyWrapper sharedWrapper] removePeerPublicKey:kTempPublicKey];

    return encrypted;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top